Bug 1227: Removed #close() from Write Transactions.
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / impl / AbstractForwardedTransaction.java
index 4f9c429e503da20ba4f7308fea81b5f061cb71ca..3fac0dc93adf55b47002abedeff09ad0646d5726 100644 (file)
@@ -17,10 +17,10 @@ import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Nullable;
 
-import org.eclipse.xtext.xbase.lib.Exceptions;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
@@ -78,17 +78,21 @@ public class AbstractForwardedTransaction<T extends AsyncTransaction<org.openday
             @Nullable
             @Override
             public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
-                try {
-                    final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path,
-                            normalizedNode.get()) : null;
-                    if(dataObject != null) {
+                if (normalizedNode.isPresent()) {
+                    final DataObject dataObject;
+                    try {
+                        dataObject = codec.toBinding(path, normalizedNode.get());
+                    } catch (DeserializationException e) {
+                        LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
+                        throw new IllegalStateException("Failed to create dataobject", e);
+                    }
+
+                    if (dataObject != null) {
                         updateCache(store, path, dataObject);
+                        return Optional.of(dataObject);
                     }
-                    return Optional.fromNullable(dataObject);
-                } catch (DeserializationException e) {
-                    Exceptions.sneakyThrow(e);
                 }
-                return null;
+                return Optional.absent();
             }
         });
     }
@@ -107,28 +111,54 @@ public class AbstractForwardedTransaction<T extends AsyncTransaction<org.openday
         final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
                 .toNormalizedNode(path, data);
 
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
-        try {
-            List<PathArgument> currentArguments = new ArrayList<>();
-            DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
-            Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
-            while (iterator.hasNext()) {
-                PathArgument currentArg = iterator.next();
+        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+        ensureParentsByMerge(writeTransaction, store, normalizedPath, path);
+        LOG.debug("Tx: {} : Putting data {}", getDelegate().getIdentifier(), normalizedPath);
+        writeTransaction.put(store, normalizedPath, normalized.getValue());
+    }
+
+    protected void doMergeWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
+            final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+        invalidateCache(store, path);
+        final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+                .toNormalizedNode(path, data);
+
+        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+        ensureParentsByMerge(writeTransaction, store, normalizedPath, path);
+        LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalizedPath);
+        writeTransaction.merge(store, normalizedPath, normalized.getValue());
+    }
+
+    private void ensureParentsByMerge(final DOMDataReadWriteTransaction writeTransaction,
+            final LogicalDatastoreType store,
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath,
+            final InstanceIdentifier<?> path) {
+        List<PathArgument> currentArguments = new ArrayList<>();
+        DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
+        Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
+        while (iterator.hasNext()) {
+            PathArgument currentArg = iterator.next();
+            try {
                 currentOp = currentOp.getChild(currentArg);
-                currentArguments.add(currentArg);
-                org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
-                        currentArguments);
-                boolean isPresent = writeTransaction.read(store, currentPath).get().isPresent();
-                if (isPresent == false && iterator.hasNext()) {
-                    writeTransaction.put(store, currentPath, currentOp.createDefault(currentArg));
-                }
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", path), e);
+            }
+            currentArguments.add(currentArg);
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
+                    currentArguments);
+
+            final Optional<NormalizedNode<?, ?>> d;
+            try {
+                d = writeTransaction.read(store, currentPath).get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
+                throw new IllegalStateException("Failed to read pre-existing data", e);
             }
-        } catch (InterruptedException | ExecutionException e) {
-            e.printStackTrace();
-        }
-        //LOG .info("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
-        writeTransaction.put(store, normalized.getKey(), normalized.getValue());
 
+            if (!d.isPresent() && iterator.hasNext()) {
+                writeTransaction.merge(store, currentPath, currentOp.createDefault(currentArg));
+            }
+        }
     }
 
     protected void doMerge(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
@@ -150,8 +180,8 @@ public class AbstractForwardedTransaction<T extends AsyncTransaction<org.openday
         return writeTransaction.commit();
     }
 
-    protected void doCancel(final DOMDataWriteTransaction writeTransaction) {
-        writeTransaction.cancel();
+    protected boolean doCancel(final DOMDataWriteTransaction writeTransaction) {
+        return writeTransaction.cancel();
     }
 
     protected ListenableFuture<Optional<DataObject>> doRead(final DOMDataReadTransaction readTransaction,