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.controller.md.sal.binding.impl;
10 import java.util.Collections;
11 import java.util.Map.Entry;
13 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
16 import org.opendaylight.yangtools.yang.binding.DataObject;
17 import org.opendaylight.yangtools.yang.binding.Identifiable;
18 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
19 import org.opendaylight.yangtools.yang.common.RpcResult;
20 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
25 import com.google.common.base.Optional;
26 import com.google.common.collect.Iterables;
27 import com.google.common.util.concurrent.ListenableFuture;
31 * Abstract Base Transaction for transactions which are backed by
32 * {@link DOMDataWriteTransaction}
34 public class AbstractWriteTransaction<T extends DOMDataWriteTransaction> extends
35 AbstractForwardedTransaction<T> {
37 private static final Logger LOG = LoggerFactory.getLogger(AbstractWriteTransaction.class);
39 protected AbstractWriteTransaction(final T delegate,
40 final BindingToNormalizedNodeCodec codec) {
41 super(delegate, codec);
44 protected final void doPut(final LogicalDatastoreType store,
45 final InstanceIdentifier<?> path, final DataObject data) {
46 final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec()
47 .toNormalizedNode(path, data);
48 ensureListParentIfNeeded(store,path,normalized);
49 getDelegate().put(store, normalized.getKey(), normalized.getValue());
55 * Ensures list parent if item is list, otherwise noop.
58 * One of properties of binding specification is that it is imposible
59 * to represent list as a whole and thus it is impossible to write
60 * empty variation of MapNode without creating parent node, with
64 * This actually makes writes such as
66 * put("Nodes", new NodesBuilder().build());
67 * put("Nodes/Node[key]", new NodeBuilder().setKey("key").build());
69 * To result in three DOM operations:
71 * put("/nodes",domNodes);
72 * merge("/nodes/node",domNodeList);
73 * put("/nodes/node/node[key]",domNode);
77 * In order to allow that to be inserted if necessary, if we know
78 * item is list item, we will try to merge empty MapNode or OrderedNodeMap
79 * to ensure list exists.
81 * @param store Data Store type
82 * @param path Path to data (Binding Aware)
83 * @param normalized Normalized version of data to be written
85 private void ensureListParentIfNeeded(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
86 final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized) {
87 if(Identifiable.class.isAssignableFrom(path.getTargetType())) {
88 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier parentMapPath = getParent(normalized.getKey()).get();
89 NormalizedNode<?, ?> emptyParent = getCodec().getDefaultNodeFor(parentMapPath);
90 getDelegate().merge(store, parentMapPath, emptyParent);
95 // FIXME (should be probaly part of InstanceIdentifier)
96 protected static Optional<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getParent(
97 final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier child) {
99 Iterable<PathArgument> mapEntryItemPath = child.getPathArguments();
100 int parentPathSize = Iterables.size(mapEntryItemPath) - 1;
101 if(parentPathSize > 1) {
102 return Optional.of(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(Iterables.limit(mapEntryItemPath, parentPathSize)));
103 } else if(parentPathSize == 0) {
104 return Optional.of(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(Collections.<PathArgument>emptyList()));
106 return Optional.absent();
110 protected final void doMerge(final LogicalDatastoreType store,
111 final InstanceIdentifier<?> path, final DataObject data) {
113 final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec()
114 .toNormalizedNode(path, data);
115 ensureListParentIfNeeded(store,path,normalized);
116 getDelegate().merge(store, normalized.getKey(), normalized.getValue());
119 protected final void doDelete(final LogicalDatastoreType store,
120 final InstanceIdentifier<?> path) {
121 final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = getCodec().toNormalized(path);
122 getDelegate().delete(store, normalized);
125 protected final ListenableFuture<RpcResult<TransactionStatus>> doCommit() {
126 return getDelegate().commit();
129 protected final boolean doCancel() {
130 return getDelegate().cancel();