Add another alternative SchemaContextUtil.findDataSchemaNode() 36/86636/1
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 30 Dec 2019 08:11:16 +0000 (09:11 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 30 Dec 2019 19:34:48 +0000 (20:34 +0100)
We have a number of call sites which are using the XPath variant
of SchemaContextUtil.findDataSchemaNode() in context where the
complexity is not warranted.

Introduce utility methods to migrate those callers to a simplified
version which takes resolved QNames (but does not use SchemaPath),
reducing proliferation of PathExpressionImpl.

JIRA: YANGTOOLS-1060
Change-Id: Id645563733af448f42ecdc62b26205c1a97a2216
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 0c48f313a0e06974816cf0d114a83ad1139219b4)

yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java
yang/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtilTest.java
yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/openconfigver/OpenconfigVersionComplexTest.java

index a8323182f62be2b8011cb809ef87240866f84fb9..93fc7dd3ed19f7cd81316f1875f2cbcd6625071c 100644 (file)
@@ -18,6 +18,7 @@ import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Deque;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -25,6 +26,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.AbstractQName;
@@ -84,20 +86,17 @@ public final class SchemaContextUtil {
     }
 
     /**
-     * Method attempts to find DataSchemaNode in Schema Context via specified
-     * Schema Path. The returned DataSchemaNode from method will be the node at
-     * the end of the SchemaPath. If the DataSchemaNode is not present in the
-     * Schema Context the method will return <code>null</code>. <br>
-     * In case that Schema Context or Schema Path are not specified correctly
-     * (i.e. contains <code>null</code> values) the method will throw
-     * IllegalArgumentException.
+     * Method attempts to find DataSchemaNode in Schema Context via specified Schema Path. The returned DataSchemaNode
+     * from method will be the node at the end of the SchemaPath. If the DataSchemaNode is not present in the Schema
+     * Context the method will return {@code null}.
      *
-     * @param context
-     *            Schema Context
-     * @param schemaPath
-     *            Schema Path to search for
-     * @return SchemaNode from the end of the Schema Path or <code>null</code>
-     *         if the Node is not present.
+     * <p>
+     * In case that Schema Context or Schema Path are not specified correctly (i.e. contains {@code null} values) the
+     * method will throw IllegalArgumentException.
+     *
+     * @param context Schema Context
+     * @param schemaPath Schema Path to search for
+     * @return SchemaNode from the end of the Schema Path or {@code null} if the Node is not present.
      * @throws NullPointerException if context or schemaPath is null
      */
     public static SchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) {
@@ -111,6 +110,35 @@ public final class SchemaContextUtil {
         return findNodeInSchemaContext(context, prefixedPath);
     }
 
+    /**
+     * Attempt to find a DataSchemaNode based on its path from root, similar to
+     * {@link #findDataSchemaNode(SchemaContext, Module, PathExpression)} without requiring an expression.
+     *
+     * @param context Schema Context
+     * @param path Path to search for
+     * @return SchemaNode from the end of the Schema Path or {@code null} if the Node is not present.
+     * @throws NullPointerException if a any argument is null or if the path contains a null element
+     */
+    @Beta
+    public static SchemaNode findDataSchemaNode(final SchemaContext context, final List<QName> path) {
+        return findTargetNode(context, null, YangLocationPath.absolute(
+            path.stream().map(YangXPathAxis.CHILD::asStep).collect(Collectors.toList())));
+    }
+
+    /**
+     * Attempt to find a DataSchemaNode based on its path from root, similar to
+     * {@link #findDataSchemaNode(SchemaContext, Module, PathExpression)} without requiring an expression.
+     *
+     * @param context Schema Context
+     * @param path Path to search for
+     * @return SchemaNode from the end of the Schema Path or {@code null} if the Node is not present.
+     * @throws NullPointerException if a any argument is null or if the path contains a null element
+     */
+    @Beta
+    public static SchemaNode findDataSchemaNode(final SchemaContext context, final QName... path) {
+        return findDataSchemaNode(context, Arrays.asList(path));
+    }
+
     /**
      * Method attempts to find DataSchemaNode inside of provided Schema Context
      * and Yang Module accordingly to Non-conditional Revision Aware XPath. The
@@ -209,7 +237,7 @@ public final class SchemaContextUtil {
     //
     //        which would then be passed in to a method similar to this one. In static contexts, like MD-SAL codegen,
     //        that feels like an overkill.
-    // FIXME: YANGTOOLS-1052: this is a static analysis util, move it to yang-model-sa
+    // FIXME: YANGTOOLS-1052: this is a static analysis util, move it to a dedicated class
     public static SchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, final Module module,
             final SchemaNode actualSchemaNode, final PathExpression relativeXPath) {
         checkState(!relativeXPath.isAbsolute(), "Revision Aware XPath MUST be relative i.e. MUST contains ../, "
@@ -655,7 +683,7 @@ public final class SchemaContextUtil {
         LOG.debug("Derefencing path {}", targetPath);
 
         final SchemaNode deref = targetPath.isAbsolute()
-                ? findTargetNode(context, actualSchemaNode,
+                ? findTargetNode(context, actualSchemaNode.getQName().getModule(),
                     ((LocationPathSteps) targetPath.getSteps()).getLocationPath())
                         : findDataSchemaNodeForRelativeXPath(context, module, actualSchemaNode, targetPath);
         if (deref == null) {
@@ -669,9 +697,8 @@ public final class SchemaContextUtil {
         return findTargetNode(context, resolveRelativePath(context, module, deref, qnames));
     }
 
-    private static @Nullable SchemaNode findTargetNode(final SchemaContext context, final SchemaNode actualSchemaNode,
+    private static @Nullable SchemaNode findTargetNode(final SchemaContext context, final QNameModule defaultModule,
             final YangLocationPath path) {
-        final QNameModule defaultModule = actualSchemaNode.getQName().getModule();
         final Deque<QName> ret = new ArrayDeque<>();
         for (Step step : path.getSteps()) {
             if (step instanceof AxisStep) {
index 8aa887641e8c950e994d826648fd53be32a57232..b47e541232039def5f55fb3798e7893dbd8bb318 100644 (file)
@@ -131,7 +131,7 @@ public class SchemaContextUtilTest {
 
     @Test(expected = NullPointerException.class)
     public void findDataSchemaNodeIllegalArgumentTest() {
-        SchemaContextUtil.findDataSchemaNode(mock(SchemaContext.class), null);
+        SchemaContextUtil.findDataSchemaNode(mock(SchemaContext.class), (SchemaPath) null);
     }
 
     @Test(expected = NullPointerException.class)
index 1c047dd36133c3899dcce5c758c0145629f2925b..3ebbcb0c887860b6064d4580e953766b05e326b3 100644 (file)
@@ -14,10 +14,10 @@ import static org.junit.Assert.assertNull;
 import java.net.URI;
 import org.junit.Test;
 import org.opendaylight.yangtools.concepts.SemVer;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
-import org.opendaylight.yangtools.yang.model.util.PathExpressionImpl;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
 
@@ -55,18 +55,22 @@ public class OpenconfigVersionComplexTest {
         assertEquals(SemVer.valueOf("2.26.465"), foobar.getSemanticVersion().get());
 
         // check imported components
-        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context, foo,
-                new PathExpressionImpl("/bar:root/bar:test-container/bar:number", true)));
+        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(bar.getQNameModule(), "root"),
+            QName.create(bar.getQNameModule(), "test-container"),
+            QName.create(bar.getQNameModule(), "number")));
 
-        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context, foo,
-                new PathExpressionImpl("/bar:should-present", true)));
+        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(bar.getQNameModule(), "should-present")));
 
         // check not imported components
-        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context, foo,
-                new PathExpressionImpl("/bar:root/bar:test-container/bar:oldnumber", true)));
+        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(bar.getQNameModule(), "root"),
+            QName.create(bar.getQNameModule(), "test-container"),
+            QName.create(bar.getQNameModule(), "oldnumber")));
 
-        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context, foo,
-                new PathExpressionImpl("/bar:should-not-be-present", true)));
+        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(bar.getQNameModule(), "should-not-be-present")));
     }
 
     @Test
@@ -101,26 +105,33 @@ public class OpenconfigVersionComplexTest {
         assertEquals(SemVer.valueOf("7.13.99"), foobar.getSemanticVersion().get());
 
         // check used augmentations
-        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context, bar,
-                new PathExpressionImpl("/foobar:root/foobar:test-container/bar:should-present-leaf-1", true)));
+        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(foobar.getQNameModule(), "root"),
+            QName.create(foobar.getQNameModule(), "test-container"),
+            QName.create(bar.getQNameModule(), "should-present-leaf-1")));
 
-        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context, bar,
-                new PathExpressionImpl("/foobar:root/foobar:test-container/bar:should-present-leaf-2", true)));
+        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(foobar.getQNameModule(), "root"),
+            QName.create(foobar.getQNameModule(), "test-container"),
+            QName.create(bar.getQNameModule(), "should-present-leaf-2")));
 
         // check not used augmentations
-        assertNull("This component should not be present",
-                SchemaContextUtil.findDataSchemaNode(context, bar, new PathExpressionImpl(
-                        "/foobar:root/foobar:test-container/bar:should-not-be-present-leaf-1", true)));
-
-        assertNull("This component should not be present",
-                SchemaContextUtil.findDataSchemaNode(context, bar, new PathExpressionImpl(
-                        "/foobar:root/foobar:test-container/bar:should-not-be-present-leaf-2", true)));
+        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(foobar.getQNameModule(), "root"),
+            QName.create(foobar.getQNameModule(), "test-container"),
+            QName.create(bar.getQNameModule(), "should-not-be-present-leaf-1")));
+        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(foobar.getQNameModule(), "root"),
+            QName.create(foobar.getQNameModule(), "test-container"),
+            QName.create(bar.getQNameModule(), "should-not-be-present-leaf-2")));
 
         // check if correct foobar module was included
-        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context, bar,
-                new PathExpressionImpl("/foobar:root/foobar:included-correct-mark", true)));
+        assertNotNull("This component should be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(foobar.getQNameModule(), "root"),
+            QName.create(foobar.getQNameModule(), "included-correct-mark")));
 
-        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context, bar,
-                new PathExpressionImpl("/foobar:root/foobar:included-not-correct-mark", true)));
+        assertNull("This component should not be present", SchemaContextUtil.findDataSchemaNode(context,
+            QName.create(foobar.getQNameModule(), "root"),
+            QName.create(foobar.getQNameModule(), "included-not-correct-mark")));
     }
 }