2 * Copyright (c) 2014 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 com.google.common.base.Preconditions.checkArgument;
12 import com.google.common.base.VerifyException;
13 import com.google.common.util.concurrent.FluentFuture;
14 import java.util.HashSet;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.mdsal.binding.api.WriteTransaction;
17 import org.opendaylight.mdsal.binding.dom.codec.api.BindingAugmentationCodecTreeNode;
18 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer.AugmentationResult;
19 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer.NodeResult;
20 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer.NormalizedResult;
21 import org.opendaylight.mdsal.common.api.CommitInfo;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
24 import org.opendaylight.yangtools.yang.binding.DataObject;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
29 class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction> extends AbstractForwardedTransaction<T>
30 implements WriteTransaction {
31 BindingDOMWriteTransactionAdapter(final AdapterContext adapterContext, final T delegateTx) {
32 super(adapterContext, delegateTx);
36 public final <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
38 put(store, toNormalized("put", path, data));
41 private void put(final LogicalDatastoreType store, final NormalizedResult normalized) {
42 final var delegate = getDelegate();
43 final var domPath = normalized.path();
45 if (normalized instanceof AugmentationResult augment) {
46 // Augmentation: put() child nodes provided with augmentation, delete() those having no data
47 final var putIds = new HashSet<YangInstanceIdentifier.PathArgument>();
48 for (var child : augment.children()) {
49 final var childId = child.name();
50 delegate.put(store, domPath.node(childId), child);
53 for (var childId : augment.possibleChildren()) {
54 if (!putIds.contains(childId)) {
55 delegate.delete(store, domPath.node(childId));
58 } else if (normalized instanceof NodeResult node) {
59 delegate.put(store, domPath, node.node());
61 throw new VerifyException("Unhandled result " + normalized);
67 public final <U extends DataObject> void mergeParentStructurePut(final LogicalDatastoreType store,
68 final InstanceIdentifier<U> path, final U data) {
69 final var serializer = adapterContext().currentSerializer();
70 final var normalized = toNormalized(serializer, "put", path, data);
71 ensureParentsByMerge(serializer, store, normalized);
72 put(store, normalized);
76 public final <D extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<D> path,
78 merge(store, toNormalized("merge", path, data));
81 private void merge(final LogicalDatastoreType store, final NormalizedResult normalized) {
82 final var delegate = getDelegate();
83 final var domPath = normalized.path();
85 if (normalized instanceof AugmentationResult augment) {
86 // Augmentation: merge individual children
87 for (var child : augment.children()) {
88 delegate.merge(store, domPath.node(child.name()), child);
90 } else if (normalized instanceof NodeResult node) {
91 delegate.merge(store, domPath, node.node());
93 throw new VerifyException("Unhandled result " + normalized);
99 public final <U extends DataObject> void mergeParentStructureMerge(final LogicalDatastoreType store,
100 final InstanceIdentifier<U> path, final U data) {
101 final var serializer = adapterContext().currentSerializer();
102 final var normalized = toNormalized(serializer, "merge", path, data);
103 ensureParentsByMerge(serializer, store, normalized);
104 merge(store, normalized);
108 public final void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
109 checkArgument(!path.isWildcarded(), "Cannot delete wildcarded path %s", path);
110 final var serializer = adapterContext().currentSerializer();
112 // Lookup the codec and the corresponding path
113 final var codecWithPath = serializer.getSubtreeCodecWithPath(path);
114 final var domPath = codecWithPath.path();
115 final var delegate = getDelegate();
116 if (codecWithPath.codec() instanceof BindingAugmentationCodecTreeNode<?> augmentCodec) {
117 // Deletion of an augmentation: issue a delete on all potential children of the augmentation
118 for (var childPath : augmentCodec.childPathArguments()) {
119 delegate.delete(store, domPath.node(childPath));
122 delegate.delete(store, domPath);
127 public FluentFuture<? extends CommitInfo> commit() {
128 return getDelegate().commit();
132 public final boolean cancel() {
133 return getDelegate().cancel();
137 public FluentFuture<?> completionFuture() {
138 return getDelegate().completionFuture();
142 * Subclasses of this class are required to implement creation of parent nodes based on behaviour of their
143 * underlying transaction.
145 * @param serializer Current serializer
146 * @param store an instance of LogicalDatastoreType
147 * @param normalized NormalizedResult of the operation
149 private void ensureParentsByMerge(final CurrentAdapterSerializer serializer, final LogicalDatastoreType store,
150 final NormalizedResult normalized) {
151 final var path = normalized.path();
152 // AugmentationResult already points to parent path
153 final var parentPath = normalized instanceof AugmentationResult ? path : path.getParent();
154 if (parentPath != null && !parentPath.isEmpty()) {
155 final var parentNode = ImmutableNodes.fromInstanceId(serializer.getRuntimeContext().modelContext(),
157 getDelegate().merge(store, YangInstanceIdentifier.of(parentNode.name()), parentNode);
161 private <U extends DataObject> @NonNull NormalizedResult toNormalized(final String operation,
162 final InstanceIdentifier<U> path, final U data) {
163 return toNormalized(adapterContext().currentSerializer(), operation, path, data);
166 private static <U extends DataObject> @NonNull NormalizedResult toNormalized(
167 final CurrentAdapterSerializer serializer, final String operation, final InstanceIdentifier<U> path,
169 checkArgument(!path.isWildcarded(), "Cannot %s data into wildcarded path %s", operation, path);
170 return serializer.toNormalizedNode(path, data);