Clean up YangInstanceIdentifierSerializer 95/109095/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 28 Nov 2023 14:25:14 +0000 (15:25 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 28 Nov 2023 14:30:25 +0000 (15:30 +0100)
Turn this class into a proper object, retaining DatabindContext and
having a serializePath() method.

JIRA: NETCONF-1157
Change-Id: I5c1b04346b17274c790fd02eb48cb0b952646f73
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/utils/parser/IdentifierCodec.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/utils/parser/YangInstanceIdentifierSerializer.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/utils/parser/YangInstanceIdentifierSerializerTest.java

index b5d9e10e062420cfc1ceaa4278e3d1f525a34063..101bc9d61124ff390e24a46950f4d81e5d70649b 100644 (file)
@@ -20,6 +20,6 @@ public final class IdentifierCodec {
     }
 
     public static String serialize(final YangInstanceIdentifier data, final DatabindContext databind) {
-        return YangInstanceIdentifierSerializer.create(databind, data);
+        return new YangInstanceIdentifierSerializer(databind).serializePath(data);
     }
 }
index 0899f75982f06d83e9ae9666fa96e076ac38bfaf..bb9d4b4a9da7084efa52a0cd92659d12853dfbcd 100644 (file)
@@ -7,8 +7,11 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.utils.parser;
 
+import static java.util.Objects.requireNonNull;
+
 import java.util.Map.Entry;
 import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.restconf.api.ApiPath;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.server.api.DatabindContext;
@@ -28,26 +31,30 @@ import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
  * Serializer for {@link YangInstanceIdentifier} to {@link String} for restconf.
  */
 public final class YangInstanceIdentifierSerializer {
+    private final @NonNull DatabindContext databind;
 
-    private YangInstanceIdentifierSerializer() {
-        // Hidden on purpose
+    public YangInstanceIdentifierSerializer(final DatabindContext databind) {
+        this.databind = requireNonNull(databind);
     }
 
     /**
      * Method to create String from {@link Iterable} of {@link PathArgument} which are parsing from data with the help
      * of an {@link EffectiveModelContext}.
      *
-     * @param databind for validate of parsing path arguments
-     * @param data path to data
+     * @param path path to data
      * @return {@link String}
      */
-    public static String create(final DatabindContext databind, final YangInstanceIdentifier data) {
+    public String serializePath(final YangInstanceIdentifier path) {
+        if (path.isEmpty()) {
+            return "";
+        }
+
         final var current = databind.schemaTree().getRoot();
         final var variables = new MainVarsWrapper(current);
-        final var path = new StringBuilder();
+        final var sb = new StringBuilder();
 
         QNameModule parentModule = null;
-        for (final PathArgument arg : data.getPathArguments()) {
+        for (var arg : path.getPathArguments()) {
             // get module of the parent
             final var currentContext = variables.getCurrent();
 
@@ -59,7 +66,7 @@ public final class YangInstanceIdentifierSerializer {
                 ? composite.childByArg(arg) : null;
             if (childContext == null) {
                 throw new RestconfDocumentedException(
-                    "Invalid input '%s': schema for argument '%s' (after '%s') not found".formatted(data, arg, path),
+                    "Invalid input '%s': schema for argument '%s' (after '%s') not found".formatted(path, arg, sb),
                     ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT);
             }
 
@@ -72,24 +79,24 @@ public final class YangInstanceIdentifierSerializer {
             // condition is satisfied also for the first path argument
             if (!arg.getNodeType().getModule().equals(parentModule)) {
                 // append slash if it is not the first path argument
-                if (path.length() > 0) {
-                    path.append('/');
+                if (sb.length() > 0) {
+                    sb.append('/');
                 }
 
-                path.append(prefixForNamespace(arg.getNodeType(), databind.modelContext())).append(':');
+                sb.append(prefixForNamespace(arg.getNodeType())).append(':');
             } else {
-                path.append('/');
+                sb.append('/');
             }
 
-            path.append(arg.getNodeType().getLocalName());
+            sb.append(arg.getNodeType().getLocalName());
             if (arg instanceof NodeIdentifierWithPredicates withPredicates) {
-                prepareNodeWithPredicates(path, withPredicates.entrySet());
+                prepareNodeWithPredicates(sb, withPredicates.entrySet());
             } else if (arg instanceof NodeWithValue<?> withValue) {
-                prepareNodeWithValue(path, withValue.getValue());
+                prepareNodeWithValue(sb, withValue.getValue());
             }
         }
 
-        return path.toString();
+        return sb.toString();
     }
 
     private static void prepareNodeWithValue(final StringBuilder path, final Object value) {
@@ -122,8 +129,8 @@ public final class YangInstanceIdentifierSerializer {
      * @param qname {@link QName}
      * @return {@link String}
      */
-    private static String prefixForNamespace(final QName qname, final EffectiveModelContext schemaContext) {
-        return schemaContext.findModuleStatement(qname.getModule()).orElseThrow().argument().getLocalName();
+    private String prefixForNamespace(final QName qname) {
+        return databind.modelContext().findModuleStatement(qname.getModule()).orElseThrow().argument().getLocalName();
     }
 
     private static final class MainVarsWrapper {
index 459c8f042cd11b2ecad3935592393aa4a525a22c..656c8a4143e3b57485aee899f5c72e0baedb0ee4 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.collect.ImmutableMap;
 import java.util.Map;
 import org.junit.jupiter.api.Test;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.common.errors.RestconfError;
 import org.opendaylight.restconf.server.api.DatabindContext;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
@@ -27,8 +28,8 @@ import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
  * Unit tests for {@link YangInstanceIdentifierSerializer}.
  */
 class YangInstanceIdentifierSerializerTest {
-    private static final DatabindContext DATABIND = DatabindContext.ofModel(
-        YangParserTestUtils.parseYangResourceDirectory("/restconf/parser/serializer"));
+    private static final YangInstanceIdentifierSerializer SERIALIZER = new YangInstanceIdentifierSerializer(
+        DatabindContext.ofModel(YangParserTestUtils.parseYangResourceDirectory("/restconf/parser/serializer")));
 
     /**
      * Positive test of serialization of <code>YangInstanceIdentifier</code> containing container node to
@@ -36,7 +37,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeContainerTest() {
-        assertEquals("serializer-test:contA", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:contA", SERIALIZER.serializePath(
             YangInstanceIdentifier.of(QName.create("serializer:test", "2016-06-06", "contA"))));
     }
 
@@ -46,7 +47,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeContainerWithLeafTest() {
-        assertEquals("serializer-test:contA/leaf-A", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:contA/leaf-A", SERIALIZER.serializePath(
             YangInstanceIdentifier.of(
                 QName.create("serializer:test", "2016-06-06", "contA"),
                 QName.create("serializer:test", "2016-06-06", "leaf-A"))));
@@ -61,8 +62,8 @@ class YangInstanceIdentifierSerializerTest {
         final var list = QName.create("serializer:test", "2016-06-06", "list-A");
         final var leafList = QName.create("serializer:test", "2016-06-06", "leaf-list-AA");
 
-        assertEquals("serializer-test:contA/list-A=100/leaf-list-AA=instance",
-            YangInstanceIdentifierSerializer.create(DATABIND, YangInstanceIdentifier.builder()
+        assertEquals("serializer-test:contA/list-A=100/leaf-list-AA=instance", SERIALIZER.serializePath(
+            YangInstanceIdentifier.builder()
                 .node(QName.create("serializer:test", "2016-06-06", "contA"))
                 .node(list)
                 .node(NodeIdentifierWithPredicates.of(list, QName.create(list, "list-key"), 100))
@@ -78,7 +79,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeListWithNoKeysTest() {
-        assertEquals("serializer-test:list-no-key", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:list-no-key", SERIALIZER.serializePath(
             YangInstanceIdentifier.of(
                 QName.create("serializer:test", "2016-06-06", "list-no-key"),
                 QName.create("serializer:test", "2016-06-06", "list-no-key"))));
@@ -91,7 +92,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeMapWithNoKeysTest() {
-        assertEquals("serializer-test:list-one-key", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:list-one-key", SERIALIZER.serializePath(
             YangInstanceIdentifier.builder()
                 .node(QName.create("serializer:test", "2016-06-06", "list-one-key"))
                 .nodeWithKey(QName.create("serializer:test", "2016-06-06", "list-one-key"), Map.of())
@@ -105,7 +106,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeMapWithOneKeyTest() {
-        assertEquals("serializer-test:list-one-key=value", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:list-one-key=value", SERIALIZER.serializePath(
             YangInstanceIdentifier.builder()
                 .node(QName.create("serializer:test", "2016-06-06", "list-one-key"))
                 .nodeWithKey(QName.create("serializer:test", "2016-06-06", "list-one-key"),
@@ -122,8 +123,8 @@ class YangInstanceIdentifierSerializerTest {
     void serializeMapWithMultipleKeysTest() {
         final var list = QName.create("serializer:test", "2016-06-06", "list-multiple-keys");
 
-        assertEquals("serializer-test:list-multiple-keys=value-1,2,true",
-            YangInstanceIdentifierSerializer.create(DATABIND, YangInstanceIdentifier.builder()
+        assertEquals("serializer-test:list-multiple-keys=value-1,2,true", SERIALIZER.serializePath(
+            YangInstanceIdentifier.builder()
                 .node(list)
                 .nodeWithKey(list, ImmutableMap.of(
                     QName.create(list, "name"), "value-1",
@@ -139,7 +140,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeLeafTest() {
-        assertEquals("serializer-test:leaf-0", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:leaf-0", SERIALIZER.serializePath(
             YangInstanceIdentifier.of(QName.create("serializer:test", "2016-06-06", "leaf-0"))));
     }
 
@@ -150,7 +151,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeLeafListTest() {
-        assertEquals("serializer-test:leaf-list-0=instance", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:leaf-list-0=instance", SERIALIZER.serializePath(
             YangInstanceIdentifier.builder()
                 .node(QName.create("serializer:test", "2016-06-06", "leaf-list-0"))
                 .node(new NodeWithValue<>(QName.create("serializer:test", "2016-06-06", "leaf-list-0"), "instance"))
@@ -164,8 +165,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeNullSchemaContextNegativeTest() {
-        assertThrows(NullPointerException.class,
-            () -> YangInstanceIdentifierSerializer.create(null, YangInstanceIdentifier.of()));
+        assertThrows(NullPointerException.class, () -> new YangInstanceIdentifierSerializer(null));
     }
 
     /**
@@ -175,8 +175,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeNullDataNegativeTest() {
-        assertThrows(NullPointerException.class,
-            () -> YangInstanceIdentifierSerializer.create(DATABIND, null));
+        assertThrows(NullPointerException.class, () -> SERIALIZER.serializePath(null));
     }
 
     /**
@@ -186,7 +185,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeEmptyDataTest() {
-        assertEquals("", YangInstanceIdentifierSerializer.create(DATABIND, YangInstanceIdentifier.of()));
+        assertEquals("", SERIALIZER.serializePath(YangInstanceIdentifier.of()));
     }
 
     /**
@@ -195,15 +194,9 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeChildNodeNotFoundNegativeTest() {
-        final var data = YangInstanceIdentifier.of(
-                QName.create("serializer:test", "2016-06-06", "contA"),
-                QName.create("serializer:test", "2016-06-06", "not-existing-leaf"));
-
-        final var ex = assertThrows(RestconfDocumentedException.class,
-            () -> YangInstanceIdentifierSerializer.create(DATABIND, data));
-        final var errors = ex.getErrors();
-        assertEquals(1, errors.size());
-        final var error = errors.get(0);
+        final var error = assertError(YangInstanceIdentifier.of(
+            QName.create("serializer:test", "2016-06-06", "contA"),
+            QName.create("serializer:test", "2016-06-06", "not-existing-leaf")));
         assertEquals("""
             Invalid input '/(serializer:test?revision=2016-06-06)contA/not-existing-leaf': schema for argument \
             '(serializer:test?revision=2016-06-06)not-existing-leaf' (after 'serializer-test:contA') not found""",
@@ -217,13 +210,12 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializePercentEncodingTest() {
-        assertEquals("serializer-test:list-one-key=foo%3Afoo bar%2Ffoo%2Cbar%2F%27bar%27",
-            YangInstanceIdentifierSerializer.create(DATABIND,
-                YangInstanceIdentifier.builder()
-                    .node(QName.create("serializer:test", "2016-06-06", "list-one-key"))
-                    .nodeWithKey(QName.create("serializer:test", "2016-06-06", "list-one-key"),
-                        QName.create("serializer:test", "2016-06-06", "list-one-key"), "foo:foo bar/foo,bar/'bar'")
-                    .build()));
+        assertEquals("serializer-test:list-one-key=foo%3Afoo bar%2Ffoo%2Cbar%2F%27bar%27", SERIALIZER.serializePath(
+            YangInstanceIdentifier.builder()
+                .node(QName.create("serializer:test", "2016-06-06", "list-one-key"))
+                .nodeWithKey(QName.create("serializer:test", "2016-06-06", "list-one-key"),
+                    QName.create("serializer:test", "2016-06-06", "list-one-key"), "foo:foo bar/foo,bar/'bar'")
+                .build()));
     }
 
     /**
@@ -231,7 +223,7 @@ class YangInstanceIdentifierSerializerTest {
      */
     @Test
     void serializeNoPercentEncodingTest() {
-        assertEquals("serializer-test:list-one-key=foo\"b\"bar", YangInstanceIdentifierSerializer.create(DATABIND,
+        assertEquals("serializer-test:list-one-key=foo\"b\"bar", SERIALIZER.serializePath(
             YangInstanceIdentifier.builder()
                 .node(QName.create("serializer:test", "2016-06-06", "list-one-key"))
                 .nodeWithKey(QName.create("serializer:test", "2016-06-06", "list-one-key"),
@@ -249,7 +241,7 @@ class YangInstanceIdentifierSerializerTest {
         final var child = QName.create("serializer:test", "2016-06-06", "augmented-leaf");
 
         assertEquals("serializer-test-included:augmented-list=100/serializer-test:augmented-leaf",
-            YangInstanceIdentifierSerializer.create(DATABIND, YangInstanceIdentifier.builder()
+            SERIALIZER.serializePath(YangInstanceIdentifier.builder()
                 .node(list)
                 .node(NodeIdentifierWithPredicates.of(list, QName.create(list, "list-key"), 100))
                 .node(child)
@@ -266,18 +258,12 @@ class YangInstanceIdentifierSerializerTest {
     void serializeIncludedNodesSerializationTest() {
         final var list = QName.create("serializer:test:included", "2016-06-06", "augmented-list");
 
-        final var data = YangInstanceIdentifier.builder()
-                .node(list)
-                .node(NodeIdentifierWithPredicates.of(list, QName.create(list, "list-key"), 100))
-                // child should has different namespace
-                .node(QName.create("serializer:test:included", "2016-06-06", "augmented-leaf"))
-                .build();
-
-        final var ex = assertThrows(RestconfDocumentedException.class,
-            () -> YangInstanceIdentifierSerializer.create(DATABIND, data));
-        final var errors = ex.getErrors();
-        assertEquals(1, errors.size());
-        final var error = errors.get(0);
+        final var error = assertError(YangInstanceIdentifier.builder()
+            .node(list)
+            .node(NodeIdentifierWithPredicates.of(list, QName.create(list, "list-key"), 100))
+            // child should has different namespace
+            .node(QName.create("serializer:test:included", "2016-06-06", "augmented-leaf"))
+            .build());
         assertEquals("""
             Invalid input '/(serializer:test:included?revision=2016-06-06)augmented-list/augmented-list[{(\
             serializer:test:included?revision=2016-06-06)list-key=100}]/augmented-leaf': schema for argument \
@@ -286,4 +272,12 @@ class YangInstanceIdentifierSerializerTest {
         assertEquals(ErrorType.APPLICATION, error.getErrorType());
         assertEquals(ErrorTag.UNKNOWN_ELEMENT, error.getErrorTag());
     }
+
+    private static RestconfError assertError(final YangInstanceIdentifier path) {
+        final var ex = assertThrows(RestconfDocumentedException.class, () -> SERIALIZER.serializePath(path));
+        final var errors = ex.getErrors();
+        assertEquals(1, errors.size());
+        return errors.get(0);
+    }
+
 }