Introduce ReadOperations.exists() 39/77739/3
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 13 Nov 2018 18:18:30 +0000 (19:18 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 13 Nov 2018 21:25:59 +0000 (22:25 +0100)
This method exists in the DOM API, but for some reason it was left
out if the Binding API. Introduce it as default methods riding on
the read() method and override them in all known implementations,
so the request is efficiently routed.

Change-Id: Id56332d6f720396305ac68e40554e62fd17c34fb
JIRA: MDSAL-389
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ReadOperations.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractForwardedTransaction.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMReadTransactionAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMReadWriteTransactionAdapter.java
binding/mdsal-binding-spi/src/main/java/org/opendaylight/mdsal/binding/spi/ForwardingReadTransaction.java
binding/mdsal-binding-spi/src/main/java/org/opendaylight/mdsal/binding/spi/ForwardingReadWriteTransaction.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/TypedReadTransaction.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/TypedReadTransactionImpl.java
binding/mdsal-binding-util/src/main/java/org/opendaylight/mdsal/binding/util/TypedReadWriteTransactionImpl.java

index 57afb7298842a9b7cebcc579abbed5dab0585740..13c50f00948844ddbae6289d98b24008e63d2748 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.mdsal.binding.api;
 
 import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
@@ -29,8 +30,8 @@ public interface ReadOperations {
      *
      * @param store Logical data store from which read should occur.
      * @param path Path which uniquely identifies subtree which client want to read
-     * @return a FluentFuture containing the result of the read. The Future blocks until the commit operation is
-     *         complete. Once complete:
+     * @return a FluentFuture containing the result of the read. The Future blocks until the operation is complete. Once
+     *         complete:
      *         <ul>
      *         <li>If the data at the supplied path exists, the Future returns an Optional object containing the data.
      *         </li>
@@ -39,7 +40,35 @@ public interface ReadOperations {
      *         an exception derived from ReadFailedException.</li>
      *         </ul>
      * @throws NullPointerException if any of the arguments is null
+     * @throws IllegalArgumentException if the path is {@link InstanceIdentifier#isWildcarded()}
      */
     <T extends DataObject> @NonNull FluentFuture<Optional<T>> read(@NonNull LogicalDatastoreType store,
             @NonNull InstanceIdentifier<T> path);
+
+    /**
+     * Determines if data data exists in the provided logical data store located at the provided path.
+     *
+     * <p>
+     * Default implementation just delegates to {@link #read(LogicalDatastoreType, InstanceIdentifier)}. Implementations
+     * are recommended to override with a more efficient implementation.
+     *
+     * @param store Logical data store from which read should occur.
+     * @param path Path which uniquely identifies subtree which client want to read
+     * @return a FluentFuture containing the result of the check. The Future blocks until the operation is complete.
+     *         Once complete:
+     *         <ul>
+     *         <li>If the data at the supplied path exists, the Future returns {@link Boolean#TRUE}.
+     *         </li>
+     *         <li>If the data at the supplied path does not exist, the Future returns {@link Boolean#FALSE}.</li>
+     *         <li>If the check fails, the Future will fail with a {@link ReadFailedException} or an exception derived
+     *             from ReadFailedException.</li>
+     *         </ul>
+     * @throws NullPointerException if any of the arguments is null
+     * @throws IllegalArgumentException if the path is {@link InstanceIdentifier#isWildcarded()} and the implementation
+     *                                  does not support evaluating wildcards.
+     */
+    default @NonNull FluentFuture<Boolean> exists(final @NonNull LogicalDatastoreType store,
+            final @NonNull InstanceIdentifier<?> path) {
+        return read(store, path).transform(Optional::isPresent, MoreExecutors.directExecutor());
+    }
 }
index 34d32726b1597344b5284b8b42ade154bd7dfb3c..28b63ec8b9e16856fb21b1bf423b301d194c2c8f 100644 (file)
@@ -53,11 +53,18 @@ abstract class AbstractForwardedTransaction<T extends DOMDataTreeTransaction> im
         return codec;
     }
 
-    protected final <D extends DataObject> FluentFuture<Optional<D>> doRead(final DOMDataTreeReadOperations readOps,
-            final LogicalDatastoreType store, final InstanceIdentifier<D> path) {
+    protected final <D extends DataObject> @NonNull FluentFuture<Optional<D>> doRead(
+            final DOMDataTreeReadOperations readOps, final LogicalDatastoreType store,
+            final InstanceIdentifier<D> path) {
         checkArgument(!path.isWildcarded(), "Invalid read of wildcarded path %s", path);
 
         return readOps.read(store, codec.toYangInstanceIdentifierBlocking(path))
                 .transform(codec.getCodecRegistry().deserializeFunction(path)::apply, MoreExecutors.directExecutor());
     }
+
+    protected final @NonNull FluentFuture<Boolean> doExists(final DOMDataTreeReadOperations readOps,
+            final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        checkArgument(!path.isWildcarded(), "Invalid exists of wildcarded path %s", path);
+        return readOps.exists(store, codec.toYangInstanceIdentifierBlocking(path));
+    }
 }
index 0cf1a4b47b7e4e379096c3e929f6f0ff546f2bd9..a088ac00d0168b91e3a7a1d11be72fcd8156550c 100644 (file)
@@ -26,7 +26,12 @@ final class BindingDOMReadTransactionAdapter extends AbstractForwardedTransactio
     @Override
     public <T extends DataObject> FluentFuture<Optional<T>> read(final LogicalDatastoreType store,
             final InstanceIdentifier<T> path) {
-        return doRead(getDelegate(),store, path);
+        return doRead(getDelegate(), store, path);
+    }
+
+    @Override
+    public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        return doExists(getDelegate(), store, path);
     }
 
     @Override
index 7bb2dfd891c027841299e44c75341c431199eecd..a8868b6547c85417f219600e22fa8b6e8fcae4de 100644 (file)
@@ -28,4 +28,9 @@ class BindingDOMReadWriteTransactionAdapter extends BindingDOMWriteTransactionAd
             final InstanceIdentifier<T> path) {
         return doRead(getDelegate(), store, path);
     }
+
+    @Override
+    public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        return doExists(getDelegate(), store, path);
+    }
 }
index 9d6892c4327a06b4c22375241e1b2ba67a6d94ce..86e3d0f92223db0381179627c02b30225eeb33f3 100644 (file)
@@ -37,6 +37,11 @@ public class ForwardingReadTransaction extends ForwardingTransaction implements
         return delegate.read(store, path);
     }
 
+    @Override
+    public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        return delegate.exists(store, path);
+    }
+
     @Override
     public void close() {
         delegate.close();
index 3336299d9b14b5b846fdc850aedd86bef7f3c714..10ddc5ff0e6410c67fb4a9fa3565e2c05edb7124 100644 (file)
@@ -51,6 +51,11 @@ public class ForwardingReadWriteTransaction extends ForwardingTransaction implem
         return delegate.read(store, path);
     }
 
+    @Override
+    public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        return delegate.exists(store, path);
+    }
+
     @Override
     public boolean cancel() {
         return delegate.cancel();
index 2a856877a246099cbb318f142977a557052cc7a5..0178224b2ed8ce7901377eebb36ab80a7b42dc39 100644 (file)
@@ -151,5 +151,11 @@ public final class TransactionAdapter {
             checkStore(store);
             return delegate().read(path);
         }
+
+        @Override
+        public FluentFuture<Boolean> exists(final LogicalDatastoreType store,final InstanceIdentifier<?> path) {
+            checkStore(store);
+            return delegate().exists(path);
+        }
     }
 }
index f42e69203de73518c6c0809a7582dfe6f695c315..845923191f191b6ae0123f8d2acecbf7c58d35eb 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.mdsal.binding.util;
 
 import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Optional;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 import org.opendaylight.mdsal.binding.api.Transaction;
@@ -34,4 +35,18 @@ public interface TypedReadTransaction<D extends Datastore> extends Transaction {
      * @return A future providing access to the result of the read, when it’s available, or any error encountered.
      */
     <T extends DataObject> FluentFuture<Optional<T>> read(InstanceIdentifier<T> path);
+
+    /**
+     * Determines if an object exists at the given path. Default implementation just delegates to
+     * {@link #read(InstanceIdentifier)}. Implementations are recommended to override with a more efficient
+     * implementation.
+     *
+     * @see ReadTransaction#exists(LogicalDatastoreType, InstanceIdentifier)
+     *
+     * @param path The path to read from.
+     * @return A future providing access to the result of the check, when it’s available, or any error encountered.
+     */
+    default FluentFuture<Boolean> exists(final InstanceIdentifier<?> path) {
+        return read(path).transform(Optional::isPresent, MoreExecutors.directExecutor());
+    }
 }
index 3176b924e1ed260ad5e50f4ff82085bdcc81b555..31ee12788e2adffb2a293d6b4af55e26c0a1555e 100644 (file)
@@ -28,4 +28,9 @@ final class TypedReadTransactionImpl<D extends Datastore> extends TypedTransacti
     public <T extends DataObject> FluentFuture<Optional<T>> read(final InstanceIdentifier<T> path) {
         return delegate().read(getDatastoreType(), path);
     }
+
+    @Override
+    public FluentFuture<Boolean> exists(final InstanceIdentifier<?> path) {
+        return delegate().exists(getDatastoreType(), path);
+    }
 }
index ae121603f3b5760cf0b154c87b987e18d0ef6c4f..192785390548908e8040583c158e8c86e00259ee 100644 (file)
@@ -29,4 +29,9 @@ class TypedReadWriteTransactionImpl<D extends Datastore>
     public final <T extends DataObject> FluentFuture<Optional<T>> read(final InstanceIdentifier<T> path) {
         return delegate().read(getDatastoreType(), path);
     }
+
+    @Override
+    public FluentFuture<Boolean> exists(final InstanceIdentifier<?> path) {
+        return delegate().exists(getDatastoreType(), path);
+    }
 }