Update binding-dom adaptation to remove AugmentationNode
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / LazyDataTreeModification.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.dom.adapter;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.MoreObjects;
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.mdsal.binding.api.DataObjectModification;
18 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
19 import org.opendaylight.mdsal.binding.api.DataTreeModification;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.mdsal.dom.api.DOMDataTreeCandidate;
22 import org.opendaylight.yangtools.yang.binding.Augmentation;
23 import org.opendaylight.yangtools.yang.binding.DataObject;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
27
28 /**
29  * Lazily translated {@link DataTreeModification} based on {@link DataTreeCandidate}.
30  *
31  * <p>
32  * {@link DataTreeModification} represents Data tree change event, but whole tree is not translated or resolved eagerly,
33  * but only child nodes which are directly accessed by user of data object modification.
34  */
35 final class LazyDataTreeModification<T extends DataObject> implements DataTreeModification<T> {
36     private final @NonNull DataTreeIdentifier<T> path;
37     private final @NonNull DataObjectModification<T> rootNode;
38
39     private LazyDataTreeModification(final DataTreeIdentifier<T> path, final DataObjectModification<T> modification) {
40         this.path = requireNonNull(path);
41         rootNode = requireNonNull(modification);
42     }
43
44     @SuppressWarnings({"unchecked", "rawtypes"})
45     static <T extends DataObject> @Nullable DataTreeModification<T> from(final CurrentAdapterSerializer serializer,
46             final DataTreeCandidate domChange, final LogicalDatastoreType datastoreType, final Class<T> augment) {
47         final var bindingPath = createBindingPath(serializer, domChange.getRootPath(), augment);
48         final var codec = serializer.getSubtreeCodec(bindingPath);
49         final var modification = LazyDataObjectModification.from(codec, domChange.getRootNode());
50         return modification == null ? null
51             : new LazyDataTreeModification(DataTreeIdentifier.create(datastoreType, bindingPath), modification);
52     }
53
54     @SuppressWarnings({"unchecked", "rawtypes"})
55     static <T extends DataObject> @Nullable DataTreeModification<T> from(final CurrentAdapterSerializer serializer,
56             final DOMDataTreeCandidate candidate, final Class<T> augment) {
57         final var domRootPath = candidate.getRootPath();
58         final var bindingPath = createBindingPath(serializer, domRootPath.getRootIdentifier(), augment);
59         final var codec = serializer.getSubtreeCodec(bindingPath);
60         final var modification = LazyDataObjectModification.from(codec, candidate.getRootNode());
61         return modification == null ? null
62             : new LazyDataTreeModification(DataTreeIdentifier.create(domRootPath.getDatastoreType(), bindingPath),
63                 modification);
64     }
65
66     static <T extends DataObject> @NonNull List<DataTreeModification<T>> from(final CurrentAdapterSerializer codec,
67             final List<DataTreeCandidate> domChanges, final LogicalDatastoreType datastoreType,
68             final Class<T> augment) {
69         final var result = new ArrayList<DataTreeModification<T>>(domChanges.size());
70         for (var domChange : domChanges) {
71             final var bindingChange = from(codec, domChange, datastoreType, augment);
72             if (bindingChange != null) {
73                 result.add(bindingChange);
74             }
75         }
76         return result;
77     }
78
79     // We are given a DOM path, which does not reflect augmentations, as those are not representable in NormalizedNode
80     // world. This method takes care of reconstructing the InstanceIdentifier, appending the missing Augmentation. This
81     // important to get the correct codec into the mix -- otherwise we would be operating on the parent container's
82     // codec and mis-report what is actually going on.
83     @SuppressWarnings({"unchecked", "rawtypes"})
84     private static @NonNull InstanceIdentifier<?> createBindingPath(final CurrentAdapterSerializer serializer,
85             final YangInstanceIdentifier domPath, final Class<?> augment) {
86         final var bindingPath = serializer.coerceInstanceIdentifier(domPath);
87         return augment == null ? bindingPath : bindingPath.augmentation((Class) augment.asSubclass(Augmentation.class));
88     }
89
90     @Override
91     public DataObjectModification<T> getRootNode() {
92         return rootNode;
93     }
94
95     @Override
96     public DataTreeIdentifier<T> getRootPath() {
97         return path;
98     }
99
100     @Override
101     public String toString() {
102         return MoreObjects.toStringHelper(this).add("path", path).add("rootNode", rootNode).toString();
103     }
104 }