Deprecate public InstanceIdentifierContext 12/100212/2
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 21 Mar 2022 21:27:15 +0000 (22:27 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 21 Mar 2022 22:06:35 +0000 (23:06 +0100)
We need to reign in semantics of what different combinations of callers
we have and what are they trying to achieve. Deprecate the public
constructor and expose static methods to create instances with
appropriate shape.

JIRA: NETCONF-818
Change-Id: I452e92cd5e7f46bccb9b00799894aa7ee375cc48
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-common/src/main/java/org/opendaylight/restconf/common/context/InstanceIdentifierContext.java
restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ControllerContext.java
restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java
restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/restconf/impl/nn/to/xml/test/NnToXmlWithDataFromSeveralModulesTest.java
restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/utils/parser/ParserIdentifier.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/XmlNormalizedNodeBodyWriterTest.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/utils/parser/AbstractFieldsTranslatorTest.java

index 6bd93dddc01cde95f7d43a9fc3f6b78b1cc8e201..669fcb3b97e90db9760ef5ec329db3df35562dc7 100644 (file)
@@ -7,9 +7,14 @@
  */
 package org.opendaylight.restconf.common.context;
 
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 
 public final class InstanceIdentifierContext {
@@ -18,6 +23,30 @@ public final class InstanceIdentifierContext {
     private final DOMMountPoint mountPoint;
     private final EffectiveModelContext schemaContext;
 
+    private InstanceIdentifierContext(final EffectiveModelContext context, final DOMMountPoint mountPoint) {
+        instanceIdentifier = YangInstanceIdentifier.empty();
+        schemaContext = requireNonNull(context);
+        schemaNode = schemaContext;
+        this.mountPoint = mountPoint;
+    }
+
+    private InstanceIdentifierContext(final EffectiveModelContext context, final RpcDefinition rpc,
+            final DOMMountPoint mountPoint) {
+        instanceIdentifier = null;
+        schemaContext = requireNonNull(context);
+        schemaNode = requireNonNull(rpc);
+        this.mountPoint = mountPoint;
+    }
+
+    private InstanceIdentifierContext(final EffectiveModelContext context, final ContainerLike rpcInputOutput,
+            final DOMMountPoint mountPoint) {
+        instanceIdentifier = null;
+        schemaContext = requireNonNull(context);
+        schemaNode = requireNonNull(rpcInputOutput);
+        this.mountPoint = mountPoint;
+    }
+
+    @Deprecated(forRemoval = true)
     public InstanceIdentifierContext(final YangInstanceIdentifier instanceIdentifier, final SchemaNode schemaNode,
             final DOMMountPoint mountPoint, final EffectiveModelContext context) {
         this.instanceIdentifier = instanceIdentifier;
@@ -26,6 +55,32 @@ public final class InstanceIdentifierContext {
         schemaContext = context;
     }
 
+    public static @NonNull InstanceIdentifierContext ofLocalRoot(final EffectiveModelContext context) {
+        return new InstanceIdentifierContext(context, null);
+    }
+
+    public static @NonNull InstanceIdentifierContext ofLocalRpcInput(final EffectiveModelContext context,
+            // FIXME: this this method really needed?
+            final RpcDefinition rpc) {
+        return new InstanceIdentifierContext(context, rpc.getInput(), null);
+    }
+
+    public static @NonNull InstanceIdentifierContext ofLocalRpcOutput(final EffectiveModelContext context,
+            // FIXME: we want to re-validate this, so might as well take a QName
+            final RpcDefinition rpc) {
+        return new InstanceIdentifierContext(context, rpc, null);
+    }
+
+    public static @NonNull InstanceIdentifierContext ofMountPointRoot(final DOMMountPoint mountPoint,
+            final EffectiveModelContext mountContext) {
+        return new InstanceIdentifierContext(mountContext, requireNonNull(mountPoint));
+    }
+
+    public static @NonNull InstanceIdentifierContext ofMountPointRpcOutput(final DOMMountPoint mountPoint,
+            final EffectiveModelContext mountContext, final RpcDefinition rpc) {
+        return new InstanceIdentifierContext(mountContext, rpc, requireNonNull(mountPoint));
+    }
+
     public YangInstanceIdentifier getInstanceIdentifier() {
         return instanceIdentifier;
     }
index cc01ef9fe477410590be4a659429d6fdb701237e..6c338cc1c03a33b0934b1fbac137b110279d981f 100644 (file)
@@ -166,7 +166,7 @@ public final class ControllerContext implements EffectiveModelContextListener, C
         checkPreconditions();
 
         if (restconfInstance == null) {
-            return new InstanceIdentifierContext(YangInstanceIdentifier.empty(), globalSchema, null, globalSchema);
+            return InstanceIdentifierContext.ofLocalRoot(globalSchema);
         }
 
         final List<String> pathArgs = urlPathArgsDecode(SLASH_SPLITTER.split(restconfInstance));
@@ -577,8 +577,7 @@ public final class ControllerContext implements EffectiveModelContextListener, C
                 }
 
                 if (returnJustMountPoint || strings.size() == 1) {
-                    return new InstanceIdentifierContext(YangInstanceIdentifier.empty(), mountPointSchema, mount,
-                        mountPointSchema);
+                    return InstanceIdentifierContext.ofMountPointRoot(mount, mountPointSchema);
                 }
 
                 final String moduleNameBehindMountPoint = toModuleName(strings.get(1));
index 2330b7fe0cb0af6efd764dfe5c09dabc32ac1bdf..f08f37bf4108fc4838befc1b65d90b8c87ffeb76 100644 (file)
@@ -451,11 +451,11 @@ public final class RestconfImpl implements RestconfService {
 
         if (resultData != null && ((ContainerNode) resultData).isEmpty()) {
             throw new WebApplicationException(Response.Status.NO_CONTENT);
-        } else {
-            return new NormalizedNodeContext(
-                    new InstanceIdentifierContext(null, resultNodeSchema, mountPoint, schemaContext),
-                    resultData, QueryParametersParser.parseWriterParameters(uriInfo));
         }
+
+        return new NormalizedNodeContext(
+            new InstanceIdentifierContext(null, resultNodeSchema, mountPoint, schemaContext),
+            resultData, QueryParametersParser.parseWriterParameters(uriInfo));
     }
 
     @SuppressFBWarnings(value = "NP_LOAD_OF_KNOWN_NULL_VALUE",
@@ -528,8 +528,9 @@ public final class RestconfImpl implements RestconfService {
         //
         //        This is legacy code, so if anybody cares to do that refactor, feel free to contribute, but I am not
         //        doing that work.
-        return new NormalizedNodeContext(new InstanceIdentifierContext(null, rpc, mountPoint, schemaContext), result,
-            QueryParametersParser.parseWriterParameters(uriInfo));
+        final var iic = mountPoint == null ? InstanceIdentifierContext.ofLocalRpcOutput(schemaContext, rpc)
+            : InstanceIdentifierContext.ofMountPointRpcOutput(mountPoint, schemaContext, rpc);
+        return new NormalizedNodeContext(iic, result, QueryParametersParser.parseWriterParameters(uriInfo));
     }
 
     private static @NonNull NormalizedNode nonnullInput(final SchemaNode rpc, final NormalizedNode input) {
index ab7bc38fac3c49af86ea07acb0393f88cbb21b37..270e649c6c3cc85a7f6bf643238278e3bb19965f 100644 (file)
@@ -108,7 +108,7 @@ public class NnToXmlWithDataFromSeveralModulesTest extends
         dataContSchemaContNode.withChild(modul2.build());
 
         final NormalizedNodeContext testNormalizedNodeContext = new NormalizedNodeContext(
-                new InstanceIdentifierContext(null, schemaContext, null, schemaContext),
+                InstanceIdentifierContext.ofLocalRoot(schemaContext),
                 dataContSchemaContNode.build());
 
         return testNormalizedNodeContext;
index e87352cbb82603a0eca31e8eb9b8f3acb2769e43..f4909eb24c9e7ceb4c3c90f418f9c56902934d17 100644 (file)
@@ -261,23 +261,18 @@ public class InvokeRpcMethodTest {
         final QName rpcQName = QName.create(rpcModule.getQNameModule(), "make-toast");
 
         RpcDefinition rpcDef = null;
-        ContainerLike rpcInputSchemaNode = null;
         for (final RpcDefinition rpc : rpcModule.getRpcs()) {
             if (rpcQName.isEqualWithoutRevision(rpc.getQName())) {
-                rpcInputSchemaNode = rpc.getInput();
                 rpcDef = rpc;
                 break;
             }
         }
 
         assertNotNull(rpcDef);
-        assertNotNull(rpcInputSchemaNode);
-        final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> containerBuilder =
-                SchemaAwareBuilders.containerBuilder(rpcInputSchemaNode);
 
-        final NormalizedNodeContext payload =
-                new NormalizedNodeContext(new InstanceIdentifierContext(null, rpcInputSchemaNode,
-                null, schemaContext), containerBuilder.build());
+        final NormalizedNodeContext payload = new NormalizedNodeContext(
+                InstanceIdentifierContext.ofLocalRpcInput(schemaContext, rpcDef),
+                SchemaAwareBuilders.containerBuilder(rpcDef.getInput()).build());
 
         doReturn(immediateFluentFuture(expResult)).when(brokerFacade).invokeRpc(eq(path), any(NormalizedNode.class));
 
index 4fc681c6c1a43ed568bac26725aacc78c57eda60..d4aabad83e9c7261890e32b7e61d60fb3d3263cc 100644 (file)
@@ -118,16 +118,17 @@ public final class ParserIdentifier {
     private static InstanceIdentifierContext createIIdContext(final EffectiveModelContext schemaContext,
             final String url, final @Nullable DOMMountPoint mountPoint) {
         final YangInstanceIdentifier urlPath = IdentifierCodec.deserialize(url, schemaContext);
+        // First things first: an empty path means data invocation on SchemaContext
+        if (urlPath.isEmpty()) {
+            return mountPoint != null ? InstanceIdentifierContext.ofMountPointRoot(mountPoint, schemaContext)
+                : InstanceIdentifierContext.ofLocalRoot(schemaContext);
+        }
+
         return new InstanceIdentifierContext(urlPath, getPathSchema(schemaContext, urlPath), mountPoint, schemaContext);
     }
 
     private static SchemaNode getPathSchema(final EffectiveModelContext schemaContext,
             final YangInstanceIdentifier urlPath) {
-        // First things first: an empty path means data invocation on SchemaContext
-        if (urlPath.isEmpty()) {
-            return schemaContext;
-        }
-
         // Peel the last component and locate the parent data node, empty path resolves to SchemaContext
         final DataSchemaContextNode<?> parent = DataSchemaContextTree.from(schemaContext)
                 .findChild(verifyNotNull(urlPath.getParent()))
index eb426c30766f1c3121375517944f0b436b0f7be8..e1277b1d0dbc15a62168070e845d40d381329478 100644 (file)
@@ -8,35 +8,34 @@
 package org.opendaylight.restconf.nb.rfc8040.jersey.providers;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.mock;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import javax.ws.rs.core.MediaType;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class XmlNormalizedNodeBodyWriterTest {
     @Test
-    public void testWriteEmptyRootContainer() throws Exception {
+    public void testWriteEmptyRootContainer() throws IOException {
         final EffectiveModelContext schemaContext = mock(EffectiveModelContext.class);
-
-        final SchemaNode schemaNode = mock(SchemaNode.class);
-        doReturn(SchemaPath.ROOT).when(schemaNode).getPath();
+        doCallRealMethod().when(schemaContext).getPath();
 
         final NormalizedNodePayload nodePayload = NormalizedNodePayload.of(
-            new InstanceIdentifierContext(YangInstanceIdentifier.empty(), schemaNode, null, schemaContext),
+            InstanceIdentifierContext.ofLocalRoot(schemaContext),
             Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(SchemaContext.NAME)).build());
 
         final ByteArrayOutputStream output = new ByteArrayOutputStream();
@@ -48,15 +47,12 @@ public class XmlNormalizedNodeBodyWriterTest {
     }
 
     @Test
-    public void testRootContainerWrite() throws Exception {
+    public void testRootContainerWrite() throws IOException {
         final EffectiveModelContext schemaContext =
                 TestRestconfUtils.loadSchemaContext("/instanceidentifier/yang", null);
 
-        final SchemaNode schemaNode = mock(SchemaNode.class);
-        doReturn(SchemaPath.ROOT).when(schemaNode).getPath();
-
         final NormalizedNodePayload nodePayload = NormalizedNodePayload.of(
-            new InstanceIdentifierContext(YangInstanceIdentifier.empty(), schemaNode, null, schemaContext),
+            InstanceIdentifierContext.ofLocalRoot(schemaContext),
             Builders.containerBuilder()
                 .withNodeIdentifier(new NodeIdentifier(SchemaContext.NAME))
                 .withChild(Builders.containerBuilder()
index 2e6d7ff0563863e1578232e137360f0e0b5fe81c..766a630c61a13a2faa3771251d49e9473be22406 100644 (file)
@@ -49,6 +49,8 @@ public abstract class AbstractFieldsTranslatorTest<T> {
     private InstanceIdentifierContext identifierJukebox;
     private InstanceIdentifierContext identifierTestServices;
 
+    // FIXME: remove all this mocking -- just parse the underlying model and be done with it
+
     // container jukebox
     @Mock
     private ContainerSchemaNode containerJukebox;