X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fbinding%2Fimpl%2FAbstractWriteTransaction.java;h=9eceeb1e436b96fd1e063e8b79e3a96bcaf54c94;hp=5ce66874b129ce3684cca1638a4308646165d058;hb=refs%2Fchanges%2F19%2F8619%2F3;hpb=fcd8c22ad9fa15570b6727a277c7f6f17b3460b2 diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java index 5ce66874b1..9eceeb1e43 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractWriteTransaction.java @@ -7,18 +7,23 @@ */ package org.opendaylight.controller.md.sal.binding.impl; +import java.util.Collections; import java.util.Map.Entry; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; import com.google.common.util.concurrent.ListenableFuture; /** @@ -38,15 +43,76 @@ public class AbstractWriteTransaction extends protected final void doPut(final LogicalDatastoreType store, final InstanceIdentifier path, final DataObject data) { - final Entry> normalized = getCodec() + final Entry> normalized = getCodec() .toNormalizedNode(path, data); + ensureListParentIfNeeded(store,path,normalized); getDelegate().put(store, normalized.getKey(), normalized.getValue()); } + + /** + * + * Ensures list parent if item is list, otherwise noop. + * + *

+ * One of properties of binding specification is that it is imposible + * to represent list as a whole and thus it is impossible to write + * empty variation of MapNode without creating parent node, with + * empty list. + * + *

+ * This actually makes writes such as + *

+     * put("Nodes", new NodesBuilder().build());
+     * put("Nodes/Node[key]", new NodeBuilder().setKey("key").build());
+     * 
+ * To result in three DOM operations: + *
+     * put("/nodes",domNodes);
+     * merge("/nodes/node",domNodeList);
+     * put("/nodes/node/node[key]",domNode);
+     * 
+ * + * + * In order to allow that to be inserted if necessary, if we know + * item is list item, we will try to merge empty MapNode or OrderedNodeMap + * to ensure list exists. + * + * @param store Data Store type + * @param path Path to data (Binding Aware) + * @param normalized Normalized version of data to be written + */ + private void ensureListParentIfNeeded(final LogicalDatastoreType store, final InstanceIdentifier path, + final Entry> normalized) { + if(Identifiable.class.isAssignableFrom(path.getTargetType())) { + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier parentMapPath = getParent(normalized.getKey()).get(); + NormalizedNode emptyParent = getCodec().getDefaultNodeFor(parentMapPath); + getDelegate().merge(store, parentMapPath, emptyParent); + } + + } + + // FIXME (should be probaly part of InstanceIdentifier) + protected static Optional getParent( + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier child) { + + Iterable mapEntryItemPath = child.getPathArguments(); + int parentPathSize = Iterables.size(mapEntryItemPath) - 1; + if(parentPathSize > 1) { + return Optional.of(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(Iterables.limit(mapEntryItemPath, parentPathSize))); + } else if(parentPathSize == 0) { + return Optional.of(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(Collections.emptyList())); + } else { + return Optional.absent(); + } + } + protected final void doMerge(final LogicalDatastoreType store, final InstanceIdentifier path, final DataObject data) { + final Entry> normalized = getCodec() .toNormalizedNode(path, data); + ensureListParentIfNeeded(store,path,normalized); getDelegate().merge(store, normalized.getKey(), normalized.getValue()); }