2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.mdsal.binding.dom.adapter;
10 import static java.util.Objects.requireNonNull;
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;
29 * Lazily translated {@link DataTreeModification} based on {@link DataTreeCandidate}.
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.
35 final class LazyDataTreeModification<T extends DataObject> implements DataTreeModification<T> {
36 private final @NonNull DataTreeIdentifier<T> path;
37 private final @NonNull DataObjectModification<T> rootNode;
39 private LazyDataTreeModification(final DataTreeIdentifier<T> path, final DataObjectModification<T> modification) {
40 this.path = requireNonNull(path);
41 rootNode = requireNonNull(modification);
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);
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);
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);
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));
93 public DataObjectModification<T> getRootNode() {
98 public DataTreeIdentifier<T> getRootPath() {
103 public String toString() {
104 return MoreObjects.toStringHelper(this).add("path", path).add("rootNode", rootNode).toString();