Fix logic ensuring parent presence
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / BindingDOMWriteTransactionAdapter.java
index 25538b5693081888e1951109332cebacc4dcd155..f7f079b5c2a6c565990be10e0feb3ee907d563e5 100644 (file)
@@ -7,55 +7,94 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter;
 
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.ListenableFuture;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-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.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.util.concurrent.FluentFuture;
+import java.util.Map.Entry;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-class BindingDOMWriteTransactionAdapter<T extends DOMDataWriteTransaction> extends
-        AbstractWriteTransaction<T> implements WriteTransaction {
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
-    protected BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
+class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction> extends AbstractForwardedTransaction<T>
+        implements WriteTransaction {
+    BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
         super(delegateTx, codec);
     }
 
     @Override
-    public <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
-                                           final U data) {
-        put(store, path, data,false);
+    public final <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
+            final U data) {
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = toNormalized("put", path, data);
+        getDelegate().put(store, normalized.getKey(), normalized.getValue());
     }
 
     @Override
-    public <D extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<D> path,
-                                             final D data) {
-        merge(store, path, data,false);
+    public final <U extends DataObject> void mergeParentStructurePut(final LogicalDatastoreType store,
+            final InstanceIdentifier<U> path, final U data) {
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = toNormalized("put",
+            path, data);
+        ensureParentsByMerge(store, normalized.getKey(), path);
+        getDelegate().put(store, normalized.getKey(), normalized.getValue());
     }
 
+    @Override
+    public final <D extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<D> path,
+            final D data) {
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = toNormalized("merge", path, data);
+        getDelegate().merge(store, normalized.getKey(), normalized.getValue());
+    }
 
     @Override
-    public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
-        doDelete( store, path);
+    public final <U extends DataObject> void mergeParentStructureMerge(final LogicalDatastoreType store,
+            final InstanceIdentifier<U> path, final U data) {
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = toNormalized("merge", path, data);
+        ensureParentsByMerge(store, normalized.getKey(), path);
+        getDelegate().merge(store, normalized.getKey(), normalized.getValue());
     }
 
-    @Deprecated
     @Override
-    public ListenableFuture<RpcResult<TransactionStatus>> commit() {
-        throw new UnsupportedOperationException();
+    public final void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        checkArgument(!path.isWildcarded(), "Cannot delete wildcarded path %s", path);
+
+        final YangInstanceIdentifier normalized = getCodec().toYangInstanceIdentifierBlocking(path);
+        getDelegate().delete(store, normalized);
     }
 
     @Override
-    public CheckedFuture<Void,TransactionCommitFailedException> submit() {
-        return doSubmit();
+    public FluentFuture<? extends CommitInfo> commit() {
+        return getDelegate().commit();
     }
 
     @Override
-    public boolean cancel() {
-        return doCancel();
+    public final boolean cancel() {
+        return getDelegate().cancel();
+    }
+
+    /**
+     * Subclasses of this class are required to implement creation of parent nodes based on behaviour of their
+     * underlying transaction.
+     *
+     * @param store an instance of LogicalDatastoreType
+     * @param domPath an instance of YangInstanceIdentifier
+     * @param path an instance of InstanceIdentifier
+     */
+    private void ensureParentsByMerge(final LogicalDatastoreType store, final YangInstanceIdentifier domPath,
+            final InstanceIdentifier<?> path) {
+        final YangInstanceIdentifier parentPath = domPath.getParent();
+        if (parentPath != null && !parentPath.isEmpty()) {
+            final NormalizedNode<?, ?> parentNode = getCodec().instanceIdentifierToNode(parentPath);
+            getDelegate().merge(store, YangInstanceIdentifier.create(parentNode.getIdentifier()), parentNode);
+        }
+    }
+
+    private <U extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(
+            final String operation, final InstanceIdentifier<U> path, final U data) {
+        checkArgument(!path.isWildcarded(), "Cannot %s data into wildcarded path %s", operation, path);
+        return getCodec().toNormalizedNode(path, data);
     }
-}
\ No newline at end of file
+}