Update WriteOperations/TypedTransaction API design 67/77467/27
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 2 Nov 2018 21:17:39 +0000 (22:17 +0100)
committerRobert Varga <nite@hq.sk>
Thu, 22 Nov 2018 10:51:14 +0000 (10:51 +0000)
Overloading merge/put methods with a boolean prevents a quick
identification of users of costly operations. Moreover, the
documentation (and contract) does not completely reflect behaviour
as all purely-structural elements undergo automatic lifecycle:
for example non-presence containers are created as needed and
removed when they are no longer needed.

Update the design by deprecating boolean-taking methods in favor
of mergeParentStructureAnd{Merge,Put}, which are now implemented
as defaults. This will allow us to migrate users first and then
remove those methods in 4.0.0 timeframe.

Also update documentation to discourage the use of these methods,
as they have significant performance cost.

JIRA: MDSAL-382
Change-Id: I878863797dab01a1adfa2164a0ab0583b0641163
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/WriteOperations.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractWriteTransaction.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMWriteTransactionAdapter.java
binding/mdsal-binding-spi/src/main/java/org/opendaylight/mdsal/binding/spi/ForwardingReadWriteTransaction.java
binding/mdsal-binding-spi/src/main/java/org/opendaylight/mdsal/binding/spi/ForwardingWriteTransaction.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/TransactionAdapter.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/TypedWriteTransaction.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/TypedWriteTransactionImpl.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/WriteTrackingReadWriteTransaction.java

index 2bc0be80625a18e8aa1bfe404c89c0e740b31ca6..cf9e6e918e4e6bef26fdbf244828dde983fbe47c 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.mdsal.binding.api;
 
  */
 package org.opendaylight.mdsal.binding.api;
 
+import com.google.common.annotations.Beta;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -22,13 +23,8 @@ public interface WriteOperations {
      * whole subtree will be replaced by the specified data.
      *
      * <p>
      * whole subtree will be replaced by the specified data.
      *
      * <p>
-     * This method does not automatically create missing parent nodes. It is equivalent to invoking
-     * {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
-     * with <code>createMissingParents</code> set to false.
-     *
-     * <p>
-     * If you need to make sure that a parent object exists but you do not want modify
-     * its pre-existing state by using put, consider using {@link #merge} instead.
+     * If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
+     * put, consider using {@link #merge} instead.
      *
      * @param store the logical data store which should be modified
      * @param path the data object path
      *
      * @param store the logical data store which should be modified
      * @param path the data object path
@@ -47,32 +43,65 @@ public interface WriteOperations {
      * If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
      * put, consider using {@link #merge} instead.
      *
      * If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
      * put, consider using {@link #merge} instead.
      *
-     * <p>
-     * Note: Using <code>createMissingParents</code> with value true, may introduce garbage in data store, or recreate
-     * nodes, which were deleted by previous transaction.
+     * <b>WARNING:</b> Using this method may introduce garbage in data store, or recreate nodes, which were deleted by
+     *                 a previous transaction. It is not necessary in most scenarios and has a significantly higher cost
+     *                 than {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject)} and should only be used
+     *                 when absolutely necessary.
      *
      * @param store the logical data store which should be modified
      * @param path the data object path
      * @param data the data object to be written to the specified path
      * @param createMissingParents if {@link #CREATE_MISSING_PARENTS}, any missing parent nodes will be automatically
      *
      * @param store the logical data store which should be modified
      * @param path the data object path
      * @param data the data object to be written to the specified path
      * @param createMissingParents if {@link #CREATE_MISSING_PARENTS}, any missing parent nodes will be automatically
-     *                             created using a merge operation.
+     *                             created using a merge operation. <b>WARNING:</b> using this option is not needed
+     *                             in most scenarios and has a significant performance cost and should be avoided
+     *                             whenever possible.
      * @throws IllegalStateException if the transaction has already been submitted
      * @throws NullPointerException if any of the arguments is null
      * @throws IllegalStateException if the transaction has already been submitted
      * @throws NullPointerException if any of the arguments is null
+     * @deprecated Use {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject)} or
+     *             {@link #mergeParentStructurePut(LogicalDatastoreType, InstanceIdentifier, DataObject)}
+     *             instead.
      */
      */
+    @Deprecated
     <T extends DataObject> void put(@NonNull LogicalDatastoreType store, @NonNull InstanceIdentifier<T> path,
             @NonNull T data, boolean createMissingParents);
 
     /**
     <T extends DataObject> void put(@NonNull LogicalDatastoreType store, @NonNull InstanceIdentifier<T> path,
             @NonNull T data, boolean createMissingParents);
 
     /**
-     * Merges a piece of data with the existing data at a specified path. Any pre-existing data which is not explicitly
-     * overwritten will be preserved. This means that if you store a container, its child lists will be merged.
+     * Stores a piece of data at the specified path. This acts as an add / replace operation, which is to say that whole
+     * subtree will be replaced by the specified data. Unlike
+     * {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject)}, this method will attempt to create
+     * semantically-significant parent nodes, like list entries and presence containers, as indicated by {@code path}.
      *
      * <p>
      *
      * <p>
-     * This method does not automatically create missing parent nodes. It is equivalent to invoking
-     * {@link #merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
-     * with <code>createMissingParents</code> set to false.
+     * If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
+     * put, consider using {@link #merge} instead.
+     *
+     * <p>
+     * <b>WARNING:</b> Using this method may introduce garbage in data store, or recreate nodes, which were deleted by
+     *                 a previous transaction. It also has a significantly higher cost than
+     *                 {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject)} and should only be used when
+     *                 absolutely necessary.
+     *
+     * @param store the logical data store which should be modified
+     * @param path the data object path
+     * @param data the data object to be written to the specified path
+     * @throws IllegalStateException if the transaction has already been submitted
+     * @throws NullPointerException if any of the arguments is null
+     */
+    // FIXME: 4.0.0: make this method non-default
+    // TODO: can we come up with a better name?
+    @Beta
+    default <T extends DataObject> void mergeParentStructurePut(@NonNull final LogicalDatastoreType store,
+            @NonNull final InstanceIdentifier<T> path, @NonNull final T data) {
+        put(store, path, data, CREATE_MISSING_PARENTS);
+    }
+
+    /**
+     * Merges a piece of data with the existing data at a specified path. Any pre-existing data which is not explicitly
+     * overwritten will be preserved. This means that if you store a container, its child lists will be merged.
      *
      * <p>
      * If you require an explicit replace operation, use {@link #put} instead.
      *
      * <p>
      * If you require an explicit replace operation, use {@link #put} instead.
+     *
      * @param store the logical data store which should be modified
      * @param path the data object path
      * @param data the data object to be merged to the specified path
      * @param store the logical data store which should be modified
      * @param path the data object path
      * @param data the data object to be merged to the specified path
@@ -93,13 +122,48 @@ public interface WriteOperations {
      * @param path the data object path
      * @param data the data object to be merged to the specified path
      * @param createMissingParents if {@link #CREATE_MISSING_PARENTS}, any missing parent nodes will be automatically
      * @param path the data object path
      * @param data the data object to be merged to the specified path
      * @param createMissingParents if {@link #CREATE_MISSING_PARENTS}, any missing parent nodes will be automatically
-     *                             created using a merge operation.
+     *                             created using a merge operation. <b>WARNING:</b> using this option is not needed
+     *                             in most scenarios and has a significant performance cost and should be avoided
+     *                             whenever possible.
      * @throws IllegalStateException if the transaction has already been submitted
      * @throws NullPointerException if any of the arguments is null
      * @throws IllegalStateException if the transaction has already been submitted
      * @throws NullPointerException if any of the arguments is null
+     * @deprecated Use {@link #merge(LogicalDatastoreType, InstanceIdentifier, DataObject)} or
+     *             {@link #mergeParentStructureMerge(LogicalDatastoreType, InstanceIdentifier, DataObject)}
+     *             instead.
      */
      */
+    @Deprecated
     <T extends DataObject> void merge(@NonNull LogicalDatastoreType store, @NonNull InstanceIdentifier<T> path,
             @NonNull T data, boolean createMissingParents);
 
     <T extends DataObject> void merge(@NonNull LogicalDatastoreType store, @NonNull InstanceIdentifier<T> path,
             @NonNull T data, boolean createMissingParents);
 
+    /**
+     * Merges a piece of data with the existing data at a specified path. Any pre-existing data which is not explicitly
+     * overwritten will be preserved. This means that if you store a container, its child lists will be merged. Unlike
+     * {@link #merge(LogicalDatastoreType, InstanceIdentifier, DataObject)}, this method will attempt to create
+     * semantically-significant parent nodes, like list entries and presence containers, as indicated by {@code path}.
+     *
+     * <p>
+     * If you require an explicit replace operation, use {@link #put} instead.
+     *
+     * <p>
+     * <b>WARNING:</b> Using this method may introduce garbage in data store, or recreate nodes, which were deleted by
+     *                 a previous transaction. It is not necessary in most scenarios and has a significantly higher cost
+     *                 than {@link #merge(LogicalDatastoreType, InstanceIdentifier, DataObject)}. It should only be used
+     *                 when absolutely necessary.
+     *
+     * @param store the logical data store which should be modified
+     * @param path the data object path
+     * @param data the data object to be merged to the specified path
+     * @throws IllegalStateException if the transaction has already been submitted
+     * @throws NullPointerException if any of the arguments is null
+     */
+    // FIXME: 4.0.0: make this method non-default
+    // TODO: can we come up with a better name?
+    @Beta
+    default <T extends DataObject> void mergeParentStructureMerge(@NonNull final LogicalDatastoreType store,
+            @NonNull final InstanceIdentifier<T> path, @NonNull final T data) {
+        merge(store, path, data, CREATE_MISSING_PARENTS);
+    }
+
     /**
      * Removes a piece of data from specified path. This operation does not fail if the specified path does not exist.
      *
     /**
      * Removes a piece of data from specified path. This operation does not fail if the specified path does not exist.
      *
@@ -111,11 +175,24 @@ public interface WriteOperations {
 
     /**
      * Flag value indicating that missing parents should be created.
 
     /**
      * Flag value indicating that missing parents should be created.
+     *
+     * <p>
+     * <b>WARNING:</b> Using this flag may introduce garbage in data store, or recreate nodes, which were deleted by
+     *                 a previous transaction. It is not necessary in most scenarios and also has a significantly higher
+     *                 cost than {@link #FAIL_ON_MISSING_PARENTS} and should only be used when absolutely necessary.
+     *
+     * @deprecated To be removed with {@link #merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
+     *             and {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}.
      */
      */
+    @Deprecated
     boolean CREATE_MISSING_PARENTS = true;
 
     /**
      * Flag value indicating that missing parents should cause an error.
     boolean CREATE_MISSING_PARENTS = true;
 
     /**
      * Flag value indicating that missing parents should cause an error.
+     *
+     * @deprecated To be removed with {@link #merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
+     *             and {@link #put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}.
      */
      */
+    @Deprecated
     boolean FAIL_ON_MISSING_PARENTS = false;
 }
     boolean FAIL_ON_MISSING_PARENTS = false;
 }
index f1162ab30659ff0fc014b25d1b835b4fdeb56286..083760e57d06cac20711240106b68a158c45ec24 100644 (file)
@@ -22,9 +22,9 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 /**
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 /**
- * Abstract Base Transaction for transactions which are backed by
- * {@link DOMDataTreeWriteTransaction}.
+ * Abstract Base Transaction for transactions which are backed by {@link DOMDataTreeWriteTransaction}.
  */
  */
+// FIXME: 4.0.0: hide this class and merge it with BindingDOMWriteTransactionAdapter
 public abstract class AbstractWriteTransaction<T extends DOMDataTreeWriteTransaction> extends
         AbstractForwardedTransaction<T> {
 
 public abstract class AbstractWriteTransaction<T extends DOMDataTreeWriteTransaction> extends
         AbstractForwardedTransaction<T> {
 
@@ -34,9 +34,7 @@ public abstract class AbstractWriteTransaction<T extends DOMDataTreeWriteTransac
 
     public final <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
             final U data, final boolean createParents) {
 
     public final <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
             final U data, final boolean createParents) {
-        checkArgument(!path.isWildcarded(), "Cannot put data into wildcarded path %s", path);
-
-        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec().toNormalizedNode(path, data);
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = toNormalized("put", path, data);
         if (createParents) {
             ensureParentsByMerge(store, normalized.getKey(), path);
         }
         if (createParents) {
             ensureParentsByMerge(store, normalized.getKey(), path);
         }
@@ -46,9 +44,7 @@ public abstract class AbstractWriteTransaction<T extends DOMDataTreeWriteTransac
 
     public final <U extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
             final U data,final boolean createParents) {
 
     public final <U extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
             final U data,final boolean createParents) {
-        checkArgument(!path.isWildcarded(), "Cannot merge data into wildcarded path %s", path);
-
-        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = getCodec().toNormalizedNode(path, data);
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = toNormalized("merge", path, data);
         if (createParents) {
             ensureParentsByMerge(store, normalized.getKey(), path);
         }
         if (createParents) {
             ensureParentsByMerge(store, normalized.getKey(), path);
         }
@@ -56,6 +52,12 @@ public abstract class AbstractWriteTransaction<T extends DOMDataTreeWriteTransac
         getDelegate().merge(store, normalized.getKey(), normalized.getValue());
     }
 
         getDelegate().merge(store, normalized.getKey(), normalized.getValue());
     }
 
+    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);
+    }
+
     /**
      * Use {@link YangInstanceIdentifier#getParent()} instead.
      */
     /**
      * Use {@link YangInstanceIdentifier#getParent()} instead.
      */
index 4c4c4b56920bc988ac5b9d5cac3bc69a2ab4655d..cff986948a25a62ec91ef88822cd7a3d129756e2 100644 (file)
@@ -16,9 +16,8 @@ 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.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction> extends
-        AbstractWriteTransaction<T> implements WriteTransaction {
-
+class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction> extends AbstractWriteTransaction<T>
+        implements WriteTransaction {
     BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
         super(delegateTx, codec);
     }
     BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
         super(delegateTx, codec);
     }
@@ -26,16 +25,15 @@ class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction> e
     @Override
     public final <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
             final U data) {
     @Override
     public final <U extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
             final U data) {
-        put(store, path, data,false);
+        put(store, path, data, false);
     }
 
     @Override
     public final <D extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<D> path,
             final D data) {
     }
 
     @Override
     public final <D extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<D> path,
             final D data) {
-        merge(store, path, data,false);
+        merge(store, path, data, false);
     }
 
     }
 
-
     @Override
     public final void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
         doDelete(store, path);
     @Override
     public final void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
         doDelete(store, path);
index 10ddc5ff0e6410c67fb4a9fa3565e2c05edb7124..5950cd951441bce6197dceffe66359a364f12852 100644 (file)
@@ -40,11 +40,18 @@ public class ForwardingReadWriteTransaction extends ForwardingTransaction implem
     }
 
     @Override
     }
 
     @Override
+    @Deprecated
     public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.put(store, path, data, createMissingParents);
     }
 
     public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.put(store, path, data, createMissingParents);
     }
 
+    @Override
+    public <T extends DataObject> void mergeParentStructurePut(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, final T data) {
+        delegate.mergeParentStructurePut(store, path, data);
+    }
+
     @Override
     public <T extends DataObject> FluentFuture<Optional<T>> read(final LogicalDatastoreType store,
             final InstanceIdentifier<T> path) {
     @Override
     public <T extends DataObject> FluentFuture<Optional<T>> read(final LogicalDatastoreType store,
             final InstanceIdentifier<T> path) {
@@ -68,11 +75,18 @@ public class ForwardingReadWriteTransaction extends ForwardingTransaction implem
     }
 
     @Override
     }
 
     @Override
+    @Deprecated
     public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.merge(store, path, data, createMissingParents);
     }
 
     public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.merge(store, path, data, createMissingParents);
     }
 
+    @Override
+    public <T extends DataObject> void mergeParentStructureMerge(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, final T data) {
+        delegate.mergeParentStructureMerge(store, path, data);
+    }
+
     @Override
     public FluentFuture<? extends CommitInfo> commit() {
         return delegate.commit();
     @Override
     public FluentFuture<? extends CommitInfo> commit() {
         return delegate.commit();
index 01d5b39b937942145203ebabd968945f797cb6cb..814a24b11e987bfedd419e51f7252d07933e8bc0 100644 (file)
@@ -39,11 +39,18 @@ public class ForwardingWriteTransaction extends ForwardingTransaction implements
     }
 
     @Override
     }
 
     @Override
+    @Deprecated
     public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.put(store, path, data, createMissingParents);
     }
 
     public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.put(store, path, data, createMissingParents);
     }
 
+    @Override
+    public <T extends DataObject> void mergeParentStructurePut(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, final T data) {
+        delegate.mergeParentStructurePut(store, path, data);
+    }
+
     @Override
     public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data) {
     @Override
     public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data) {
@@ -51,11 +58,18 @@ public class ForwardingWriteTransaction extends ForwardingTransaction implements
     }
 
     @Override
     }
 
     @Override
+    @Deprecated
     public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.merge(store, path, data, createMissingParents);
     }
 
     public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
             final T data, final boolean createMissingParents) {
         delegate.merge(store, path, data, createMissingParents);
     }
 
+    @Override
+    public <T extends DataObject> void mergeParentStructureMerge(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, final T data) {
+        delegate.mergeParentStructureMerge(store, path, data);
+    }
+
     @Override
     public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
         delegate.delete(store, path);
     @Override
     public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
         delegate.delete(store, path);
index 0178224b2ed8ce7901377eebb36ab80a7b42dc39..c24f36342e16c618db75d3d731b4a78fc7f51fb6 100644 (file)
@@ -87,12 +87,20 @@ public final class TransactionAdapter {
         }
 
         @Override
         }
 
         @Override
+        @Deprecated
         public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
                 final T data, final boolean createMissingParents) {
             checkStore(store);
             delegate.put(path, data, createMissingParents);
         }
 
         public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
                 final T data, final boolean createMissingParents) {
             checkStore(store);
             delegate.put(path, data, createMissingParents);
         }
 
+        @Override
+        public <T extends DataObject> void mergeParentStructurePut(final LogicalDatastoreType store,
+                final InstanceIdentifier<T> path, final T data) {
+            checkStore(store);
+            delegate.mergeParentStructurePut(path, data);
+        }
+
         @Override
         public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
                 final T data) {
         @Override
         public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
                 final T data) {
@@ -101,12 +109,20 @@ public final class TransactionAdapter {
         }
 
         @Override
         }
 
         @Override
+        @Deprecated
         public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
                 final T data, final boolean createMissingParents) {
             checkStore(store);
             delegate.merge(path, data, createMissingParents);
         }
 
         public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
                 final T data, final boolean createMissingParents) {
             checkStore(store);
             delegate.merge(path, data, createMissingParents);
         }
 
+        @Override
+        public <T extends DataObject> void mergeParentStructureMerge(final LogicalDatastoreType store,
+                final InstanceIdentifier<T> path, final T data) {
+            checkStore(store);
+            delegate.mergeParentStructureMerge(path, data);
+        }
+
         @Override
         public boolean cancel() {
             throw new UnsupportedOperationException("Managed transactions must not be cancelled");
         @Override
         public boolean cancel() {
             throw new UnsupportedOperationException("Managed transactions must not be cancelled");
index f8be2a4ed3ae9b88e5a68a2e2a566fbe2aac7013..e2790eb6b59773e6effed3ca3d35bec928eaa4b7 100644 (file)
@@ -7,8 +7,9 @@
  */
 package org.opendaylight.mdsal.binding.util;
 
  */
 package org.opendaylight.mdsal.binding.util;
 
+import com.google.common.annotations.Beta;
 import org.opendaylight.mdsal.binding.api.Transaction;
 import org.opendaylight.mdsal.binding.api.Transaction;
-import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.api.WriteOperations;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -18,13 +19,13 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  * with {@link ManagedNewTransactionRunner} (it doesn’t support explicit cancel or commit operations).
  *
  * @param <D> The logical datastore handled by the transaction.
  * with {@link ManagedNewTransactionRunner} (it doesn’t support explicit cancel or commit operations).
  *
  * @param <D> The logical datastore handled by the transaction.
- * @see WriteTransaction
+ * @see WriteOperations
  */
 public interface TypedWriteTransaction<D extends Datastore> extends Transaction {
     /**
      * Writes an object to the given path.
      *
  */
 public interface TypedWriteTransaction<D extends Datastore> extends Transaction {
     /**
      * Writes an object to the given path.
      *
-     * @see WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject)
+     * @see WriteOperations#put(LogicalDatastoreType, InstanceIdentifier, DataObject)
      *
      * @param path The path to write to.
      * @param data The object to write.
      *
      * @param path The path to write to.
      * @param data The object to write.
@@ -35,20 +36,40 @@ public interface TypedWriteTransaction<D extends Datastore> extends Transaction
     /**
      * Writes an object to the given path, creating missing parents if requested.
      *
     /**
      * Writes an object to the given path, creating missing parents if requested.
      *
-     * @see WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)
+     * @see WriteOperations#put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)
      *
      * @param path The path to write to.
      * @param data The object to write.
      *
      * @param path The path to write to.
      * @param data The object to write.
-     * @param createMissingParents {@link WriteTransaction#CREATE_MISSING_PARENTS} to create missing parents,
-     * {@link WriteTransaction#FAIL_ON_MISSING_PARENTS} to fail if parents are missing.
+     * @param createMissingParents {@link WriteOperations#CREATE_MISSING_PARENTS} to create missing parents,
+     *                             {@link WriteOperations#FAIL_ON_MISSING_PARENTS} to fail if parents are missing.
      * @param <T> The type of the provided object.
      * @param <T> The type of the provided object.
+     * @deprecated Use {@link #put(InstanceIdentifier, DataObject)} or
+     *             {@link #mergeParentStructurePut(InstanceIdentifier, DataObject)} instead.
      */
      */
+    @Deprecated
     <T extends DataObject> void put(InstanceIdentifier<T> path, T data, boolean createMissingParents);
 
     <T extends DataObject> void put(InstanceIdentifier<T> path, T data, boolean createMissingParents);
 
+    /**
+     * Writes an object to the given path, creating significant parents, like presence containers and list entries,
+     * if needed.
+     *
+     * @see WriteOperations#mergeParentStructurePut(LogicalDatastoreType, InstanceIdentifier, DataObject)
+     *
+     * @param path The path to write to.
+     * @param data The object to write.
+     * @param <T> The type of the provided object.
+     */
+    // TODO: can we come up with a better name?
+    @Beta
+    @SuppressWarnings("deprecation")
+    default <T extends DataObject> void mergeParentStructurePut(final InstanceIdentifier<T> path, final T data) {
+        put(path, data, WriteOperations.CREATE_MISSING_PARENTS);
+    }
+
     /**
      * Merges an object with the data already present at the given path.
      *
     /**
      * Merges an object with the data already present at the given path.
      *
-     * @see WriteTransaction#merge(LogicalDatastoreType, InstanceIdentifier, DataObject)
+     * @see WriteOperations#merge(LogicalDatastoreType, InstanceIdentifier, DataObject)
      *
      * @param path The path to write to.
      * @param data The object to merge.
      *
      * @param path The path to write to.
      * @param data The object to merge.
@@ -57,22 +78,44 @@ public interface TypedWriteTransaction<D extends Datastore> extends Transaction
     <T extends DataObject> void merge(InstanceIdentifier<T> path, T data);
 
     /**
     <T extends DataObject> void merge(InstanceIdentifier<T> path, T data);
 
     /**
-     * Merges an object with the data already present at the given path, creating missing parents if requested.
+     * Merges an object with the data already present at the given path, creating significant parents, like presence
+     * containers and list entries, if needed.
      *
      *
-     * @see WriteTransaction#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)
+     * @see WriteOperations#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)
      *
      * @param path The path to write to.
      * @param data The object to merge.
      *
      * @param path The path to write to.
      * @param data The object to merge.
-     * @param createMissingParents {@link WriteTransaction#CREATE_MISSING_PARENTS} to create missing parents,
-     * {@link WriteTransaction#FAIL_ON_MISSING_PARENTS} to fail if parents are missing.
+     * @param createMissingParents {@link WriteOperations#CREATE_MISSING_PARENTS} to create missing parents,
+     *                             {@link WriteOperations#FAIL_ON_MISSING_PARENTS} to fail if parents are missing.
      * @param <T> The type of the provided object.
      * @param <T> The type of the provided object.
+     * @deprecated Use {@link #merge(InstanceIdentifier, DataObject)} or
+     *             {@link #mergeParentStructureMerge(InstanceIdentifier, DataObject)} instead.
      */
      */
+    @Deprecated
     <T extends DataObject> void merge(InstanceIdentifier<T> path, T data, boolean createMissingParents);
 
     <T extends DataObject> void merge(InstanceIdentifier<T> path, T data, boolean createMissingParents);
 
+    /**
+     * Merges an object with the data already present at the given path, creating missing parents if requested.
+     *
+     * @see WriteOperations#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)
+     *
+     * @param path The path to write to.
+     * @param data The object to merge.
+     * @param <T> The type of the provided object.
+     */
+    // FIXME: 4.0.0: make this method non-default
+    // TODO: can we come up with a better name?
+    @Beta
+    @SuppressWarnings("deprecation")
+    default <T extends DataObject> void mergeParentStructureMerge(final InstanceIdentifier<T> path,
+            final T data) {
+        merge(path, data, WriteOperations.CREATE_MISSING_PARENTS);
+    }
+
     /**
      * Deletes the object present at the given path.
      *
     /**
      * Deletes the object present at the given path.
      *
-     * @see WriteTransaction#delete(LogicalDatastoreType, InstanceIdentifier)
+     * @see WriteOperations#delete(LogicalDatastoreType, InstanceIdentifier)
      *
      * @param path The path to delete.
      */
      *
      * @param path The path to delete.
      */
index 60fa3b98ae5155314b5ab5968c2c45ae7b93e73c..409cb02800ab85318812112246b4249c1c9a248d 100644 (file)
@@ -30,12 +30,20 @@ class TypedWriteTransactionImpl<D extends Datastore, X extends WriteTransaction>
     }
 
     @Override
     }
 
     @Override
+    @Deprecated
     public final <T extends DataObject> void put(final InstanceIdentifier<T> path, final T data,
             final boolean createMissingParents) {
         delegate().put(getDatastoreType(), path, data, createMissingParents);
         postOperation();
     }
 
     public final <T extends DataObject> void put(final InstanceIdentifier<T> path, final T data,
             final boolean createMissingParents) {
         delegate().put(getDatastoreType(), path, data, createMissingParents);
         postOperation();
     }
 
+    @Override
+    public final <T extends DataObject> void mergeParentStructurePut(final InstanceIdentifier<T> path,
+            final T data) {
+        delegate().mergeParentStructurePut(getDatastoreType(), path, data);
+        postOperation();
+    }
+
     @Override
     public final <T extends DataObject> void merge(final InstanceIdentifier<T> path, final T data) {
         delegate().merge(getDatastoreType(), path, data);
     @Override
     public final <T extends DataObject> void merge(final InstanceIdentifier<T> path, final T data) {
         delegate().merge(getDatastoreType(), path, data);
@@ -43,12 +51,20 @@ class TypedWriteTransactionImpl<D extends Datastore, X extends WriteTransaction>
     }
 
     @Override
     }
 
     @Override
+    @Deprecated
     public final <T extends DataObject> void merge(final InstanceIdentifier<T> path, final T data,
             final boolean createMissingParents) {
         delegate().merge(getDatastoreType(), path, data, createMissingParents);
         postOperation();
     }
 
     public final <T extends DataObject> void merge(final InstanceIdentifier<T> path, final T data,
             final boolean createMissingParents) {
         delegate().merge(getDatastoreType(), path, data, createMissingParents);
         postOperation();
     }
 
+    @Override
+    public final <T extends DataObject> void mergeParentStructureMerge(final InstanceIdentifier<T> path,
+            final T data) {
+        delegate().mergeParentStructureMerge(getDatastoreType(), path, data);
+        postOperation();
+    }
+
     @Override
     public final void delete(final InstanceIdentifier<?> path) {
         delegate().delete(getDatastoreType(), path);
     @Override
     public final void delete(final InstanceIdentifier<?> path) {
         delegate().delete(getDatastoreType(), path);
index 9df66175d14b14d4218ede5e7f9600d64a9f3083..26030a80ce3c21306013293b4a22369fc1610998 100644 (file)
@@ -16,43 +16,62 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 /**
  * Read-write transaction which keeps track of writes.
  */
 /**
  * Read-write transaction which keeps track of writes.
  */
-class WriteTrackingReadWriteTransaction extends ForwardingReadWriteTransaction implements WriteTrackingTransaction {
+final class WriteTrackingReadWriteTransaction extends ForwardingReadWriteTransaction
+        implements WriteTrackingTransaction {
     // This is volatile to ensure we get the latest value; transactions aren't supposed to be used in multiple threads,
     // but the cost here is tiny (one read penalty at the end of a transaction) so we play it safe
     private volatile boolean written;
 
     // This is volatile to ensure we get the latest value; transactions aren't supposed to be used in multiple threads,
     // but the cost here is tiny (one read penalty at the end of a transaction) so we play it safe
     private volatile boolean written;
 
-    WriteTrackingReadWriteTransaction(ReadWriteTransaction delegate) {
+    WriteTrackingReadWriteTransaction(final ReadWriteTransaction delegate) {
         super(delegate);
     }
 
     @Override
         super(delegate);
     }
 
     @Override
-    public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
+    public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data) {
         super.put(store, path, data);
         written = true;
     }
 
     @Override
         super.put(store, path, data);
         written = true;
     }
 
     @Override
-    public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
-            boolean createMissingParents) {
+    @Deprecated
+    public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data, final boolean createMissingParents) {
         super.put(store, path, data, createMissingParents);
         written = true;
     }
 
     @Override
         super.put(store, path, data, createMissingParents);
         written = true;
     }
 
     @Override
-    public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
+    public <T extends DataObject> void mergeParentStructurePut(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, final T data) {
+        super.mergeParentStructurePut(store, path, data);
+        written = true;
+    }
+
+    @Override
+    public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data) {
         super.merge(store, path, data);
         written = true;
     }
 
     @Override
         super.merge(store, path, data);
         written = true;
     }
 
     @Override
-    public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
-            boolean createMissingParents) {
+    @Deprecated
+    public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data, final boolean createMissingParents) {
         super.merge(store, path, data, createMissingParents);
         written = true;
     }
 
     @Override
         super.merge(store, path, data, createMissingParents);
         written = true;
     }
 
     @Override
-    public void delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
+    public <T extends DataObject> void mergeParentStructureMerge(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, final T data) {
+        super.mergeParentStructureMerge(store, path, data);
+        written = true;
+    }
+
+    @Override
+    public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
         super.delete(store, path);
         written = true;
     }
         super.delete(store, path);
         written = true;
     }