Tighten canReuseCurrent() contract
[yangtools.git] / parser / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / StatementSupport.java
index 0db910ffaf15505e09b0fbd35900aad05b493ca3..6a4a4f2e3bdd1697847b6f7f54979fef7c714419 100644 (file)
@@ -12,7 +12,7 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.VerifyException;
-import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
@@ -39,9 +39,9 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
  * @param <E> Effective Statement representation
  */
 public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
-        implements StatementDefinition, StatementFactory<A, D, E> {
+        implements StatementFactory<A, D, E> {
     /**
-     * A baseline class for implementing the {@link StatementFactory#canReuseCurrent(Current, Current, Collection)}
+     * A baseline class for implementing the {@link StatementFactory#canReuseCurrent(Current, Current, List)}
      * contract in a manner which is consistent with a statement's {@link CopyPolicy}.
      *
      * @param <A> Argument type
@@ -129,7 +129,7 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
         }
 
         abstract boolean canReuseCurrent(@NonNull Current<A, D> copy, @NonNull Current<A, D> current,
-            @NonNull Collection<? extends EffectiveStatement<?, ?>> substatements);
+            @NonNull List<? extends EffectiveStatement<?, ?>> substatements);
 
         private static final class AlwaysFail<A, D extends DeclaredStatement<A>> extends StatementPolicy<A, D> {
             static final @NonNull AlwaysFail<?, ?> IGNORE = new AlwaysFail<>(CopyPolicy.IGNORE);
@@ -141,7 +141,7 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
 
             @Override
             boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
-                    final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+                    final List<? extends EffectiveStatement<?, ?>> substatements) {
                 throw new VerifyException("This implementation should never be invoked");
             }
         }
@@ -167,7 +167,7 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
 
             @Override
             boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
-                    final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+                    final List<? extends EffectiveStatement<?, ?>> substatements) {
                 return equality.canReuseCurrent(copy, current, substatements);
             }
         }
@@ -184,7 +184,7 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
     public interface StatementEquality<A, D extends DeclaredStatement<A>> {
         /**
          * Determine whether {@code current} statement has the same semantics as the provided copy. See the contract
-         * specification of {@link StatementFactory#canReuseCurrent(Current, Current, Collection)}.
+         * specification of {@link StatementFactory#canReuseCurrent(Current, Current, List)}.
          *
          * @param copy Copy of current effective context
          * @param current Current effective context
@@ -192,27 +192,37 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
          * @return True if {@code current} can be reused in place of {@code copy}, false if the copy needs to be used.
          */
         boolean canReuseCurrent(@NonNull Current<A, D> copy, @NonNull Current<A, D> current,
-            @NonNull Collection<? extends EffectiveStatement<?, ?>> substatements);
+            @NonNull List<? extends EffectiveStatement<?, ?>> substatements);
     }
 
+    /**
+     * Projection of {@link StatementSupport}s available within a particular source. This namespace is purely virtual
+     * and its behaviour corresponds to {@link NamespaceBehaviour#rootStatementLocal(ParserNamespace)} and is always
+     * available.
+     * Its contents are derived from {@link StatementSupportBundle}s active in the current {@link ModelProcessingPhase}
+     * as well as {@link StatementDefinitions} and {@link StmtContext#yangVersion()} of the source root statement.
+     */
+    @Beta
+    public static final @NonNull ParserNamespace<QName, StatementSupport<?, ?, ?>> NAMESPACE =
+        new ParserNamespace<>("statementSupports");
+
     private final @NonNull StatementPolicy<A, D> policy;
-    private final @NonNull StatementDefinition def;
+    private final @NonNull StatementDefinition publicDefinition;
     private final @NonNull CopyPolicy copyPolicy;
 
     @Beta
     protected StatementSupport(final StatementSupport<A, D, E> delegate) {
         checkArgument(delegate != this);
-        this.def = delegate.def;
-        this.policy = delegate.policy;
-        this.copyPolicy = delegate.copyPolicy;
+        publicDefinition = delegate.publicDefinition;
+        policy = delegate.policy;
+        copyPolicy = delegate.copyPolicy;
     }
 
     @Beta
     protected StatementSupport(final StatementDefinition publicDefinition, final StatementPolicy<A, D> policy) {
-        checkArgument(publicDefinition != this);
-        this.def = requireNonNull(publicDefinition);
+        this.publicDefinition = requireNonNull(publicDefinition);
         this.policy = requireNonNull(policy);
-        this.copyPolicy = policy.copyPolicy;
+        copyPolicy = policy.copyPolicy;
     }
 
     /**
@@ -225,7 +235,13 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
      * @return public statement definition, which will be present in built statements.
      */
     public final @NonNull StatementDefinition getPublicView() {
-        return def;
+        return publicDefinition;
+    }
+
+    // Appropriate to most definitions
+    // Non-final for compatible extensions
+    public @NonNull StatementDefinition definition() {
+        return publicDefinition;
     }
 
     /**
@@ -267,10 +283,16 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
 
     @Override
     public final boolean canReuseCurrent(final Current<A, D> copy, final Current<A, D> current,
-            final Collection<? extends EffectiveStatement<?, ?>> substatements) {
+            final List<? extends EffectiveStatement<?, ?>> substatements) {
         return policy.canReuseCurrent(copy, current, substatements);
     }
 
+    @Override
+    public EffectiveStatementState extractEffectiveState(final E stmt) {
+        // Not implemented for most statements
+        return null;
+    }
+
     /**
      * Parses textual representation of argument in object representation.
      *
@@ -432,26 +454,16 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
         return false;
     }
 
-    @Override
-    public final QName getStatementName() {
-        return def.getStatementName();
+    public final @NonNull QName statementName() {
+        return publicDefinition.getStatementName();
     }
 
-    @Override
-    public final Optional<ArgumentDefinition> getArgumentDefinition() {
-        return def.getArgumentDefinition();
+    public final @Nullable QName argumentName() {
+        return publicDefinition.getArgumentDefinition().map(ArgumentDefinition::argumentName).orElse(null);
     }
 
-    @Override
-    // Non-final for compatible extensions
-    public Class<? extends DeclaredStatement<?>> getDeclaredRepresentationClass() {
-        return def.getDeclaredRepresentationClass();
-    }
-
-    @Override
-    // Non-final for compatible extensions
-    public Class<? extends EffectiveStatement<?,?>> getEffectiveRepresentationClass() {
-        return def.getEffectiveRepresentationClass();
+    public final @NonNull Optional<ArgumentDefinition> getArgumentDefinition() {
+        return publicDefinition.getArgumentDefinition();
     }
 
     /**