Deprecate Clustered(DOM)DataTreeChangeListener
[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,
47             final @Nullable Class<? extends Augmentation<?>> augment) {
48         final var bindingPath = createBindingPath(serializer, domChange.getRootPath(), augment);
49         final var codec = serializer.getSubtreeCodec(bindingPath);
50         final var modification = LazyDataObjectModification.from(codec, domChange.getRootNode());
51         return modification == null ? null
52             : new LazyDataTreeModification(DataTreeIdentifier.of(datastoreType, bindingPath), modification);
53     }
54
55     static <T extends DataObject> @Nullable DataTreeModification<T> from(final CurrentAdapterSerializer serializer,
56             final DOMDataTreeCandidate candidate, final @Nullable Class<T> augment) {
57         final var domRootPath = candidate.getRootPath();
58         @SuppressWarnings("unchecked")
59         final var bindingPath = (InstanceIdentifier<T>) createBindingPath(serializer, domRootPath.path(), augment);
60         final var codec = serializer.getSubtreeCodec(bindingPath);
61         @SuppressWarnings("unchecked")
62         final var modification = (DataObjectModification<T>) LazyDataObjectModification.from(codec,
63             candidate.getRootNode());
64         return modification == null ? null
65             : new LazyDataTreeModification<>(DataTreeIdentifier.of(domRootPath.datastore(), bindingPath), modification);
66     }
67
68     static <T extends DataObject> @NonNull List<DataTreeModification<T>> from(final CurrentAdapterSerializer codec,
69             final List<DataTreeCandidate> domChanges, final LogicalDatastoreType datastoreType,
70             final @Nullable Class<? extends Augmentation<?>> augment) {
71         final var result = new ArrayList<DataTreeModification<T>>(domChanges.size());
72         for (var domChange : domChanges) {
73             final var bindingChange = LazyDataTreeModification.<T>from(codec, domChange, datastoreType, augment);
74             if (bindingChange != null) {
75                 result.add(bindingChange);
76             }
77         }
78         return result;
79     }
80
81     // We are given a DOM path, which does not reflect augmentations, as those are not representable in NormalizedNode
82     // world. This method takes care of reconstructing the InstanceIdentifier, appending the missing Augmentation. This
83     // important to get the correct codec into the mix -- otherwise we would be operating on the parent container's
84     // codec and mis-report what is actually going on.
85     @SuppressWarnings({"unchecked", "rawtypes"})
86     private static @NonNull InstanceIdentifier<?> createBindingPath(final CurrentAdapterSerializer serializer,
87             final YangInstanceIdentifier domPath, final @Nullable Class<?> augment) {
88         final var bindingPath = serializer.coerceInstanceIdentifier(domPath);
89         return augment == null ? bindingPath : bindingPath.augmentation((Class) augment.asSubclass(Augmentation.class));
90     }
91
92     @Override
93     public DataObjectModification<T> getRootNode() {
94         return rootNode;
95     }
96
97     @Override
98     public DataTreeIdentifier<T> getRootPath() {
99         return path;
100     }
101
102     @Override
103     public String toString() {
104         return MoreObjects.toStringHelper(this).add("path", path).add("rootNode", rootNode).toString();
105     }
106 }