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 org.opendaylight.mdsal.dom.api.DOMDataWriteTransaction;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.util.concurrent.CheckedFuture;
15 import java.util.Map.Entry;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
18 import org.opendaylight.yangtools.yang.binding.DataObject;
19 import org.opendaylight.yangtools.yang.binding.Identifiable;
20 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 * Abstract Base Transaction for transactions which are backed by
27 * {@link DOMDataWriteTransaction}
29 public abstract class AbstractWriteTransaction<T extends DOMDataWriteTransaction> extends
30 AbstractForwardedTransaction<T> {
32 protected AbstractWriteTransaction(final T delegate, final BindingToNormalizedNodeCodec codec) {
33 super(delegate, codec);
36 public final <U extends DataObject> void put(final LogicalDatastoreType store,
37 final InstanceIdentifier<U> path, final U data, final boolean createParents) {
38 Preconditions.checkArgument(!path.isWildcarded(), "Cannot put data into wildcarded path %s", path);
40 final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec().toNormalizedNode(path, data);
42 ensureParentsByMerge(store, normalized.getKey(), path);
44 ensureListParentIfNeeded(store,path,normalized);
47 getDelegate().put(store, normalized.getKey(), normalized.getValue());
50 public final <U extends DataObject> void merge(final LogicalDatastoreType store,
51 final InstanceIdentifier<U> path, final U data,final boolean createParents) {
52 Preconditions.checkArgument(!path.isWildcarded(), "Cannot merge data into wildcarded path %s", path);
54 final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec().toNormalizedNode(path, data);
56 ensureParentsByMerge(store, normalized.getKey(), path);
58 ensureListParentIfNeeded(store,path,normalized);
61 getDelegate().merge(store, normalized.getKey(), normalized.getValue());
66 * Ensures list parent if item is list, otherwise noop.
69 * One of properties of binding specification is that it is imposible
70 * to represent list as a whole and thus it is impossible to write
71 * empty variation of MapNode without creating parent node, with
75 * This actually makes writes such as
77 * put("Nodes", new NodesBuilder().build());
78 * put("Nodes/Node[key]", new NodeBuilder().setKey("key").build());
80 * To result in three DOM operations:
82 * put("/nodes",domNodes);
83 * merge("/nodes/node",domNodeList);
84 * put("/nodes/node/node[key]",domNode);
88 * In order to allow that to be inserted if necessary, if we know
89 * item is list item, we will try to merge empty MapNode or OrderedNodeMap
90 * to ensure list exists.
92 * @param store Data Store type
93 * @param path Path to data (Binding Aware)
94 * @param normalized Normalized version of data to be written
96 private void ensureListParentIfNeeded(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
97 final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized) {
98 if (Identifiable.class.isAssignableFrom(path.getTargetType())) {
99 final YangInstanceIdentifier parentMapPath = normalized.getKey().getParent();
100 Preconditions.checkArgument(parentMapPath != null, "Map path %s does not have a parent", path);
102 final NormalizedNode<?, ?> emptyParent = getCodec().getDefaultNodeFor(parentMapPath);
103 getDelegate().merge(store, parentMapPath, emptyParent);
108 * @deprecated Use {@link YangInstanceIdentifier#getParent()} instead.
111 protected static Optional<YangInstanceIdentifier> getParent(final YangInstanceIdentifier child) {
112 return Optional.fromNullable(child.getParent());
116 * Subclasses of this class are required to implement creation of parent nodes based on
117 * behaviour of their underlying transaction.
123 protected final void ensureParentsByMerge(final LogicalDatastoreType store, final YangInstanceIdentifier domPath,
124 final InstanceIdentifier<?> path) {
125 final YangInstanceIdentifier parentPath = domPath.getParent();
126 if (parentPath != null) {
127 final NormalizedNode<?, ?> parentNode = getCodec().instanceIdentifierToNode(parentPath);
128 getDelegate().merge(store, YangInstanceIdentifier.create(parentNode.getIdentifier()), parentNode);
132 protected final void doDelete(final LogicalDatastoreType store,
133 final InstanceIdentifier<?> path) {
134 Preconditions.checkArgument(!path.isWildcarded(), "Cannot delete wildcarded path %s", path);
136 final YangInstanceIdentifier normalized = getCodec().toYangInstanceIdentifierBlocking(path);
137 getDelegate().delete(store, normalized);
140 protected final CheckedFuture<Void,TransactionCommitFailedException> doSubmit() {
141 return getDelegate().submit();
144 protected final boolean doCancel() {
145 return getDelegate().cancel();