Add CopyPolicy.EXACT_REPLICA 08/94908/2
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 31 Jan 2021 12:44:02 +0000 (13:44 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 31 Jan 2021 15:30:26 +0000 (16:30 +0100)
There is a slight difference in copy handling of 'type' statement
after conversion to CONTEXT_INDEPENDENT -- as that policy ends up
being also affected by substatements, which is not correct.

Add CopyPolicy.EXACT_REPLICA, which forces the reactor do disregard
any substatements' conflicting policy.

JIRA: YANGTOOLS-1208
Change-Id: Ib000edf416b706d0c9f3f4c9f292c9b971092c31
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
13 files changed:
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractIdentityRefSpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractLeafrefSpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractTypeStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/BitsSpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/Decimal64SpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/EnumSpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/InstanceIdentifierSpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/UnionSpecificationSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/typedef/TypedefStatementSupport.java
yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1208Test.java
yang/yang-parser-rfc7950/src/test/resources/bugs/YT1208/typedef.yang [new file with mode: 0644]
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.java

index 84823f6531bf33ceda01b4dc89a43e7f09d1eab1..dfe906ab8806d8fa6567add8ecc5c99ecffcfbb8 100644 (file)
@@ -434,21 +434,21 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     }
 
     private void summarizeSubstatementPolicy() {
-        if (noSensitiveSubstatements()) {
+        if (definition().support().copyPolicy() == CopyPolicy.EXACT_REPLICA || noSensitiveSubstatements()) {
             setAllSubstatementsContextIndependent();
         }
     }
 
     /**
-     * Determine whether any substatements are context-sensitive as determined by {@link StatementSupport#copyPolicy()}.
-     * Only {@link CopyPolicy#CONTEXT_INDEPENDENT} and {@link CopyPolicy#IGNORE} are context-insensitive. Note that
-     * statements which are not {@link StmtContext#isSupportedToBuildEffective()} are all considered
-     * context-insensitive.
+     * Determine whether any substatements are copy-sensitive as determined by {@link StatementSupport#copyPolicy()}.
+     * Only {@link CopyPolicy#CONTEXT_INDEPENDENT}, {@link CopyPolicy#EXACT_REPLICA} and {@link CopyPolicy#IGNORE} are
+     * copy-insensitive. Note that statements which are not {@link StmtContext#isSupportedToBuildEffective()} are all
+     * considered copy-insensitive.
      *
      * <p>
      * Implementations are expected to call {@link #noSensitiveSubstatements()} to actually traverse substatement sets.
      *
-     * @return True if no substatements require context-sensitive handling
+     * @return True if no substatements require copy-sensitive handling
      */
     abstract boolean noSensitiveSubstatements();
 
@@ -469,6 +469,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
                 switch (stmt.definition().support().copyPolicy()) {
                     case CONTEXT_INDEPENDENT:
+                    case EXACT_REPLICA:
                     case IGNORE:
                         break;
                     default:
@@ -654,6 +655,8 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         final StatementSupport<A, D, E> support = definition.support();
         final CopyPolicy policy = support.copyPolicy();
         switch (policy) {
+            case EXACT_REPLICA:
+                return replicaAsChildOf(parent);
             case CONTEXT_INDEPENDENT:
                 if (allSubstatementsContextIndependent()) {
                     return replicaAsChildOf(parent);
index 1a021517aa16eb529164ef04236e744aebfedcc2..150fa20e1c09de990b731acef2cba7a3ed51d339 100644 (file)
@@ -35,7 +35,7 @@ abstract class AbstractIdentityRefSpecificationSupport
         extends AbstractStringStatementSupport<IdentityRefSpecification,
             EffectiveStatement<String, IdentityRefSpecification>> {
     AbstractIdentityRefSpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index c081afb0d6a5d5bd7d5730a1c74954b157b434a0..774a3a1e9f59551638ca79822186ce746c35dd08 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 abstract class AbstractLeafrefSpecificationSupport extends AbstractStringStatementSupport<LeafrefSpecification,
             EffectiveStatement<String, LeafrefSpecification>> {
     AbstractLeafrefSpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index a05b18a35cae7dc0f5287f8bf301cbd58a80e14c..c714e129973231899deca3e5e757d81bc93a447a 100644 (file)
@@ -152,7 +152,7 @@ abstract class AbstractTypeStatementSupport
         Iterables.<String>concat(STATIC_BUILT_IN_TYPES.keySet(), DYNAMIC_BUILT_IN_TYPES.keySet())), key -> key);
 
     AbstractTypeStatementSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index 2159c21ae8502b46c6cbd1d294a6951679c1cd72..1e84112959da3903f93578856eb9e4edbbdb3430 100644 (file)
@@ -33,7 +33,7 @@ final class BitsSpecificationSupport
         .build();
 
     BitsSpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index 51c885f6cc2064c62c5fe559c7d0c74090e831a6..15973bfcec82f1faa50dc62e15f855cf397ac42c 100644 (file)
@@ -32,7 +32,7 @@ final class Decimal64SpecificationSupport extends AbstractStringStatementSupport
         .build();
 
     Decimal64SpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index 23d58431fb5ca56950043dd03962691cda6cd46c..285c8997599ba29d1db6fa1abd5ab90b1a9416c5 100644 (file)
@@ -31,7 +31,7 @@ final class EnumSpecificationSupport
             SubstatementValidator.builder(YangStmtMapping.TYPE).addMultiple(YangStmtMapping.ENUM).build();
 
     EnumSpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index 82c6fa497538dd9a192def9ecf4b7d61907bb0f4..1f7eba6b735e90d4c819d567c0539a4234dde7be 100644 (file)
@@ -30,7 +30,7 @@ final class InstanceIdentifierSpecificationSupport
         .build();
 
     InstanceIdentifierSpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index f684c725d253d371bdc506bdccf3e0c948974240..e4164ac690e18f2080ec6aee2417e954ab7d64fc 100644 (file)
@@ -31,7 +31,7 @@ final class UnionSpecificationSupport
         .build();
 
     UnionSpecificationSupport() {
-        super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
     }
 
     @Override
index 5eb99e3d8553d31a31113c98157b8ec2f8a0594c..34e6c2c5af646728661107ec8a99968988c3d4c1 100644 (file)
@@ -51,7 +51,7 @@ public final class TypedefStatementSupport extends
     private static final TypedefStatementSupport INSTANCE = new TypedefStatementSupport();
 
     private TypedefStatementSupport() {
-        super(YangStmtMapping.TYPEDEF, StatementPolicy.contextIndependent());
+        super(YangStmtMapping.TYPEDEF, StatementPolicy.exactReplica());
     }
 
     public static TypedefStatementSupport getInstance() {
index d43f7b82c0ad51bd508546a02af800be6737f0ab..85072b1528ef99eeb350e2e3273f8840e2c33674 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement
 import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 
 public class YT1208Test {
     @Test
@@ -171,4 +172,21 @@ public class YT1208Test {
         assertSame(contBar, grpBar);
     }
 
+    @Test
+    public void testTypedefStatementReuse() throws Exception {
+        final ModuleEffectiveStatement module = StmtTestUtils.parseYangSource("/bugs/YT1208/typedef.yang")
+            .getModuleStatements()
+            .get(QNameModule.create(URI.create("foo")));
+        assertNotNull(module);
+
+        final TypedefEffectiveStatement grpBar = module
+            .findFirstEffectiveSubstatement(GroupingEffectiveStatement.class).orElseThrow()
+            .findFirstEffectiveSubstatement(ContainerEffectiveStatement.class).orElseThrow()
+            .findFirstEffectiveSubstatement(TypedefEffectiveStatement.class).orElseThrow();
+        final TypedefEffectiveStatement contBar = module
+            .findFirstEffectiveSubstatement(ContainerEffectiveStatement.class).orElseThrow()
+            .findFirstEffectiveSubstatement(TypedefEffectiveStatement.class).orElseThrow();
+
+        assertSame(contBar, grpBar);
+    }
 }
diff --git a/yang/yang-parser-rfc7950/src/test/resources/bugs/YT1208/typedef.yang b/yang/yang-parser-rfc7950/src/test/resources/bugs/YT1208/typedef.yang
new file mode 100644 (file)
index 0000000..7466b58
--- /dev/null
@@ -0,0 +1,22 @@
+module foo {
+  namespace foo;
+  prefix foo;
+
+  extension foo;
+
+  grouping grp {
+    container foo {
+      typedef bar {
+        type string;
+        // This extension must not prevent 'bar' reuse
+        foo:foo;
+      }
+
+      leaf baz {
+        type bar;
+      }
+    }
+  }
+
+  uses grp;
+}
index 241e208aa545cfa0c373cb1b30d27a0d2cf6b387..82a3e37fb8b232f67eaefb4a019409a183b53fc2 100644 (file)
@@ -66,6 +66,18 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
             return (StatementPolicy<A, D>) EqualSemantics.CONTEXT_INDEPENDENT;
         }
 
+        /**
+         * Return a {@link StatementPolicy} for {@link CopyPolicy#EXACT_REPLICA}.
+         *
+         * @param <A> Argument type
+         * @param <D> Declared Statement representation
+         * @return Exact-replica policy
+         */
+        @SuppressWarnings("unchecked")
+        public static final <A, D extends DeclaredStatement<A>> @NonNull StatementPolicy<A, D> exactReplica() {
+            return (StatementPolicy<A, D>) EqualSemantics.EXACT_REPLICA;
+        }
+
         /**
          * Return a {@link StatementPolicy} for {@link CopyPolicy#IGNORE}.
          *
@@ -145,6 +157,8 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
                 new EqualSemantics<>((copy, stmt, substatements) -> false);
             static final @NonNull EqualSemantics<?, ?> CONTEXT_INDEPENDENT =
                 new EqualSemantics<>(CopyPolicy.CONTEXT_INDEPENDENT, (copy, stmt, substatements) -> true);
+            static final @NonNull EqualSemantics<?, ?> EXACT_REPLICA =
+                new EqualSemantics<>(CopyPolicy.EXACT_REPLICA, (copy, stmt, substatements) -> true);
 
             private final @NonNull StatementEquality<A, D> equality;
 
@@ -479,6 +493,13 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
          */
         // TODO: does this mean source must have transitioned to ModelProcessingPhase.EFFECTIVE_MODEL?
         CONTEXT_INDEPENDENT,
+        /**
+         * Reuse the source statement context in the new place completely. This policy is more stringent than
+         * {@link #CONTEXT_INDEPENDENT} in that the statement is dependent on circumstances of its original definition
+         * and any copy operation must replicate it exactly as is. This implies ignoring the usual policy of its
+         * substatements. A typical example of such a statement is {@code type}.
+         */
+        EXACT_REPLICA,
         /**
          * Create a copy sharing declared instance, but otherwise having a separate disconnected lifecycle.
          */