Correct ActionProviderService method definition 63/99763/1
authorPeter Suna <peter.suna@pantheon.tech>
Tue, 15 Feb 2022 17:08:35 +0000 (18:08 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 15 Feb 2022 20:53:33 +0000 (21:53 +0100)
registerImplementation generics fail to account for KeyedListActions.
Fix that by making sure allow for KeyedInstanceIdentifiers as well as
InstanceIdentifiers.

JIRA: MDSAL-723
Change-Id: Iac402bb4390dbd1805fc930c2250b3c7c8343dc0
Signed-off-by: Peter Suna <peter.suna@pantheon.tech>
(cherry picked from commit 128c1abfb15284e16cdb471bcaacdf7cf6a60eb1)

binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionProviderService.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/ActionProviderServiceAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiActionProviderService.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractActionAdapterTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/ActionProviderServiceAdapterTest.java

index 0b546110680d93b8c2ae0f5770072b36251129b1..a818c833e74809dc65931a1b8113a71483ad2739 100644 (file)
@@ -40,17 +40,17 @@ public interface ActionProviderService extends BindingService {
      * @throws IllegalArgumentException if any of the {@code validNodes} does not match {@code datastore}
      * @throws UnsupportedOperationException if this service cannot handle requested datastore
      */
-    <P extends DataObject, A extends Action<InstanceIdentifier<P>, ?, ?>, S extends A>
+    <P extends DataObject, A extends Action<? extends InstanceIdentifier<P>, ?, ?>, S extends A>
         @NonNull ObjectRegistration<S> registerImplementation(@NonNull ActionSpec<A, P> spec, @NonNull S implementation,
-            @NonNull LogicalDatastoreType datastore, @NonNull Set<InstanceIdentifier<P>> validNodes);
+            @NonNull LogicalDatastoreType datastore, @NonNull Set<? extends InstanceIdentifier<P>> validNodes);
 
-    default <P extends DataObject, T extends Action<InstanceIdentifier<P>, ?, ?>, S extends T>
+    default <P extends DataObject, T extends Action<? extends InstanceIdentifier<P>, ?, ?>, S extends T>
         @NonNull ObjectRegistration<S> registerImplementation(final @NonNull ActionSpec<T, P> spec,
             final @NonNull S implementation, final @NonNull LogicalDatastoreType datastore) {
         return registerImplementation(spec, implementation, datastore, ImmutableSet.of());
     }
 
-    default <P extends DataObject, T extends Action<InstanceIdentifier<P>, ?, ?>, S extends T>
+    default <P extends DataObject, T extends Action<? extends InstanceIdentifier<P>, ?, ?>, S extends T>
         @NonNull ObjectRegistration<S> registerImplementation(final @NonNull ActionSpec<T, P> spec,
             final @NonNull S implementation) {
         return registerImplementation(spec, implementation, LogicalDatastoreType.OPERATIONAL);
index 8381b216e6edf4176fda65cf9839245cd6293cfa..6f8db3daa7e7667d3ce1df05d3633f97f8a07c3f 100644 (file)
@@ -66,9 +66,9 @@ public final class ActionProviderServiceAdapter extends AbstractBindingAdapter<D
     }
 
     @Override
-    public <P extends DataObject, A extends Action<InstanceIdentifier<P>, ?, ?>, S extends A>
+    public <P extends DataObject, A extends Action<? extends InstanceIdentifier<P>, ?, ?>, S extends A>
             ObjectRegistration<S> registerImplementation(final ActionSpec<A, P> spec, final S implementation,
-                final LogicalDatastoreType datastore, final Set<InstanceIdentifier<P>> validNodes) {
+                final LogicalDatastoreType datastore, final Set<? extends InstanceIdentifier<P>> validNodes) {
         final CurrentAdapterSerializer serializer = currentSerializer();
         final Absolute actionPath = serializer.getActionPath(spec);
         final Impl impl = new Impl(adapterContext(), actionPath, spec.type(), implementation);
index 90995d0446fa452d6912e9b70c34fd0edc017d1b..d04182e9dc03e2c4d022dbb49723f42de85104ae 100644 (file)
@@ -33,9 +33,9 @@ public final class OSGiActionProviderService extends AbstractAdaptedService<Acti
     }
 
     @Override
-    public <P extends DataObject, A extends Action<InstanceIdentifier<P>, ?, ?>, S extends A>
+    public <P extends DataObject, A extends Action<? extends InstanceIdentifier<P>, ?, ?>, S extends A>
         ObjectRegistration<S> registerImplementation(final ActionSpec<A, P> spec, final S implementation,
-            final LogicalDatastoreType datastore, final Set<InstanceIdentifier<P>> validNodes) {
+            final LogicalDatastoreType datastore, final Set<? extends InstanceIdentifier<P>> validNodes) {
         return delegate().registerImplementation(spec, implementation, datastore, validNodes);
     }
 
index 23ce80d4aa6aaabd54ddb372a232f2b329aece2e..bf543d5406e384fb3f2f363f7f2188fd89aee5ed 100644 (file)
@@ -13,11 +13,13 @@ import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containe
 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafBuilder;
 
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Cont;
+import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Lstio;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.Foo;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.foo.Input;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.foo.InputBuilder;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.foo.Output;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.foo.OutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.lstio.Fooio;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -25,6 +27,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absol
 
 public abstract class AbstractActionAdapterTest extends AbstractAdapterTest  {
     protected static final Absolute FOO_PATH = Absolute.of(Cont.QNAME, Foo.QNAME);
+    protected static final Absolute FOOIO_PATH = Absolute.of(Lstio.QNAME, Fooio.QNAME);
     protected static final NodeIdentifier FOO_INPUT = new NodeIdentifier(operationInputQName(Foo.QNAME.getModule()));
     protected static final NodeIdentifier FOO_OUTPUT = new NodeIdentifier(operationOutputQName(Foo.QNAME.getModule()));
     protected static final NodeIdentifier FOO_XYZZY = new NodeIdentifier(QName.create(Foo.QNAME, "xyzzy"));
index 0abf3f6f7e2bfc8db26416bbdd5cc7046dab4ea2..b5c06cae9f0c43ada7c53f284898e86ea0308692 100644 (file)
@@ -24,8 +24,12 @@ import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMActionInstance;
 import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Cont;
+import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Lstio;
+import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.LstioKey;
 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.Foo;
+import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.lstio.Fooio;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -33,6 +37,10 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class ActionProviderServiceAdapterTest extends AbstractActionAdapterTest {
     private static final @NonNull Foo FOO = (path, input) -> RpcResultBuilder.success(BINDING_FOO_OUTPUT).buildFuture();
+    private static final @NonNull Fooio FOOIO = (path, input) -> RpcResultBuilder.success(
+            new org.opendaylight.yang.gen.v1.urn.odl.actions.norev.lstio.fooio.OutputBuilder().build()).buildFuture();
+    private static final @NonNull QName KEYIO_QNAME = QName.create(Lstio.QNAME, "keyio");
+    private static final String LIST_KEY = "list-key";
 
     @Mock
     private DOMActionProviderService actionProvider;
@@ -55,6 +63,22 @@ public class ActionProviderServiceAdapterTest extends AbstractActionAdapterTest
             LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.create(new NodeIdentifier(Cont.QNAME)))));
     }
 
+    @Test
+    public void testKeyedInstanceRegistration() {
+        final InstanceIdentifier<Lstio> identifier = InstanceIdentifier.builder(Lstio.class, new LstioKey(LIST_KEY))
+                .build();
+
+        adapter.registerImplementation(ActionSpec.builder(Lstio.class).build(Fooio.class), FOOIO,
+                LogicalDatastoreType.OPERATIONAL, Set.of(identifier));
+
+        final YangInstanceIdentifier lstioYIID = YangInstanceIdentifier.builder()
+                .node(Lstio.QNAME)
+                .nodeWithKey(Lstio.QNAME, KEYIO_QNAME, LIST_KEY)
+                .build();
+        verify(actionProvider).registerActionImplementation(any(),
+                eq(DOMActionInstance.of(FOOIO_PATH, LogicalDatastoreType.OPERATIONAL, lstioYIID)));
+    }
+
     @Test
     public void testWildcardRegistration() {
         adapter.registerImplementation(ActionSpec.builder(Cont.class).build(Foo.class), FOO);