Migrate coerceStatementArgument() callers
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / uses / UsesStatementSupport.java
index b4da726f0d3589756212243faee8a2b05dc4b90b..a6e0b075d5ea2b43ba7fc745dfab94dcfaf27c58 100644 (file)
@@ -8,24 +8,38 @@
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses;
 
 import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.RefineEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.refine.RefineEffectiveStatementImpl;
 import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
@@ -45,7 +59,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class UsesStatementSupport
-        extends AbstractQNameStatementSupport<UsesStatement, UsesEffectiveStatement> {
+        extends BaseQNameStatementSupport<UsesStatement, UsesEffectiveStatement> {
     private static final Logger LOG = LoggerFactory.getLogger(UsesStatementSupport.class);
     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
         .USES)
@@ -80,7 +94,7 @@ public final class UsesStatementSupport
         super.onFullDefinitionDeclared(usesNode);
 
         final ModelActionBuilder usesAction = usesNode.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
-        final QName groupingName = usesNode.getStatementArgument();
+        final QName groupingName = usesNode.argument();
 
         final Prerequisite<StmtContext<?, ?, ?>> sourceGroupingPre = usesAction.requiresCtx(usesNode,
                 GroupingNamespace.class, groupingName, ModelProcessingPhase.EFFECTIVE_MODEL);
@@ -103,26 +117,68 @@ public final class UsesStatementSupport
 
             @Override
             public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
-                InferenceException.throwIf(failed.contains(sourceGroupingPre),
-                        usesNode.getStatementSourceReference(), "Grouping '%s' was not resolved.", groupingName);
-                throw new InferenceException("Unknown error occurred.", usesNode.getStatementSourceReference());
+                InferenceException.throwIf(failed.contains(sourceGroupingPre), usesNode.sourceReference(),
+                    "Grouping '%s' was not resolved.", groupingName);
+                throw new InferenceException("Unknown error occurred.", usesNode.sourceReference());
             }
         });
     }
 
     @Override
-    public UsesStatement createDeclared(final StmtContext<QName, UsesStatement, ?> ctx) {
-        return new UsesStatementImpl(ctx);
+    protected SubstatementValidator getSubstatementValidator() {
+        return SUBSTATEMENT_VALIDATOR;
     }
 
     @Override
-    public UsesEffectiveStatement createEffective(final StmtContext<QName, UsesStatement, UsesEffectiveStatement> ctx) {
-        return new UsesEffectiveStatementImpl(ctx);
+    protected UsesStatement createDeclared(final StmtContext<QName, UsesStatement, ?> ctx,
+            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+        return new RegularUsesStatement(ctx.getRawArgument(), ctx.getArgument(), substatements);
     }
 
     @Override
-    protected SubstatementValidator getSubstatementValidator() {
-        return SUBSTATEMENT_VALIDATOR;
+    protected UsesStatement createEmptyDeclared(final StmtContext<QName, UsesStatement, ?> ctx) {
+        return new EmptyUsesStatement(ctx.getRawArgument(), ctx.getArgument());
+    }
+
+    @Override
+    protected UsesEffectiveStatement createEffective(final Current<QName, UsesStatement> stmt,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        final GroupingDefinition sourceGrouping = getSourceGrouping(stmt);
+        final int flags = historyAndStatusFlags(stmt.history(), substatements);
+        final QName argument = stmt.getArgument();
+        final UsesStatement declared = stmt.declared();
+
+        if (substatements.isEmpty()) {
+            return argument.equals(declared.argument())
+                ? new EmptyLocalUsesEffectiveStatement(declared, sourceGrouping, flags)
+                        : new SimpleCopiedUsesEffectiveStatement(declared, argument, sourceGrouping, flags);
+        }
+
+        if (declared.argument().equals(argument)) {
+            return new RegularLocalUsesEffectiveStatement(declared, sourceGrouping, flags, substatements);
+        }
+        if (findFirstStatement(substatements, RefineEffectiveStatement.class) == null) {
+            return new SimpleCopiedUsesEffectiveStatement(declared, argument, sourceGrouping, flags, substatements);
+        }
+        return new FullCopiedUsesEffectiveStatement(declared, argument, sourceGrouping, flags, substatements);
+    }
+
+    static @NonNull ImmutableMap<Descendant, SchemaNode> indexRefines(
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        final Map<Descendant, SchemaNode> refines = new LinkedHashMap<>();
+
+        for (EffectiveStatement<?, ?> effectiveStatement : substatements) {
+            if (effectiveStatement instanceof RefineEffectiveStatementImpl) {
+                final RefineEffectiveStatementImpl refineStmt = (RefineEffectiveStatementImpl) effectiveStatement;
+                refines.put(refineStmt.argument(), refineStmt.getRefineTargetNode());
+            }
+        }
+
+        return ImmutableMap.copyOf(refines);
+    }
+
+    private static GroupingDefinition getSourceGrouping(final Current<QName, ?> stmt) {
+        return (GroupingDefinition) stmt.getFromNamespace(GroupingNamespace.class, stmt.getArgument()).buildEffective();
     }
 
     /**
@@ -137,6 +193,8 @@ public final class UsesStatementSupport
      * @throws SourceException
      *             instance of SourceException
      */
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static void copyFromSourceToTarget(final Mutable<?, ?, ?> sourceGrpStmtCtx,
             final StatementContextBase<?, ?, ?> targetCtx,
             final Mutable<QName, UsesStatement, UsesEffectiveStatement> usesNode) {
@@ -161,7 +219,6 @@ public final class UsesStatementSupport
         usesNode.addAsEffectOfStatement(buffer);
     }
 
-
     private static boolean shouldCopy(final StmtContext<?, ?, ?> stmt) {
         // https://tools.ietf.org/html/rfc7950#section-7.13:
         //
@@ -172,7 +229,7 @@ public final class UsesStatementSupport
         // This means that the statement that is about to be copied (and can be subjected to buildEffective() I think)
         // is actually a SchemaTreeEffectiveStatement
         if (SchemaTreeEffectiveStatement.class.isAssignableFrom(
-                stmt.getPublicDefinition().getEffectiveRepresentationClass())) {
+                stmt.publicDefinition().getEffectiveRepresentationClass())) {
             return true;
         }
 
@@ -203,12 +260,12 @@ public final class UsesStatementSupport
         if (targetCtx.getParentContext() == null) {
             return targetCtx.getFromNamespace(ModuleCtxToModuleQName.class, targetCtx);
         }
-        if (targetCtx.getPublicDefinition() == YangStmtMapping.AUGMENT) {
+        if (targetCtx.publicDefinition() == YangStmtMapping.AUGMENT) {
             return StmtContextUtils.getRootModuleQName(targetCtx);
         }
 
-        final Object targetStmtArgument = targetCtx.getStatementArgument();
-        final Object sourceStmtArgument = stmtContext.getStatementArgument();
+        final Object targetStmtArgument = targetCtx.argument();
+        final Object sourceStmtArgument = stmtContext.argument();
         if (targetStmtArgument instanceof QName && sourceStmtArgument instanceof QName) {
             return ((QName) targetStmtArgument).getModule();
         }
@@ -216,11 +273,12 @@ public final class UsesStatementSupport
         return null;
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static void resolveUsesNode(final Mutable<QName, UsesStatement, UsesEffectiveStatement> usesNode,
             final StmtContext<?, ?, ?> targetNodeStmtCtx) {
         for (final Mutable<?, ?, ?> subStmtCtx : usesNode.mutableDeclaredSubstatements()) {
-            if (StmtContextUtils.producesDeclared(subStmtCtx, RefineStatement.class)
-                    && areFeaturesSupported(subStmtCtx)) {
+            if (subStmtCtx.producesDeclared(RefineStatement.class) && areFeaturesSupported(subStmtCtx)) {
                 performRefine(subStmtCtx, targetNodeStmtCtx);
             }
         }
@@ -234,22 +292,21 @@ public final class UsesStatementSupport
     }
 
     private static void performRefine(final Mutable<?, ?, ?> subStmtCtx, final StmtContext<?, ?, ?> usesParentCtx) {
-        final Object refineArgument = subStmtCtx.getStatementArgument();
-        InferenceException.throwIf(!(refineArgument instanceof SchemaNodeIdentifier),
-            subStmtCtx.getStatementSourceReference(),
+        final Object refineArgument = subStmtCtx.argument();
+        InferenceException.throwIf(!(refineArgument instanceof SchemaNodeIdentifier), subStmtCtx.sourceReference(),
             "Invalid refine argument %s. It must be instance of SchemaNodeIdentifier.", refineArgument);
 
-        final Optional<StmtContext<?, ?, ?>> optRefineTargetCtx = ChildSchemaNodeNamespace.findNode(
+        final Optional<StmtContext<?, ?, ?>> optRefineTargetCtx = SchemaTreeNamespace.findNode(
             usesParentCtx, (SchemaNodeIdentifier) refineArgument);
-        InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx.getStatementSourceReference(),
+        InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx.sourceReference(),
             "Refine target node %s not found.", refineArgument);
 
         final StmtContext<?, ?, ?> refineTargetNodeCtx = optRefineTargetCtx.get();
         if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) {
             LOG.trace("Refine node '{}' in uses '{}' has target node unknown statement '{}'. "
-                + "Refine has been skipped. At line: {}", subStmtCtx.getStatementArgument(),
-                subStmtCtx.coerceParentContext().getStatementArgument(),
-                refineTargetNodeCtx.getStatementArgument(), subStmtCtx.getStatementSourceReference());
+                + "Refine has been skipped. At line: {}", subStmtCtx.argument(),
+                subStmtCtx.coerceParentContext().argument(), refineTargetNodeCtx.argument(),
+                subStmtCtx.sourceReference());
             subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
             return;
         }
@@ -271,14 +328,13 @@ public final class UsesStatementSupport
     private static void addOrReplaceNode(final Mutable<?, ?, ?> refineSubstatementCtx,
             final StatementContextBase<?, ?, ?> refineTargetNodeCtx) {
 
-        final StatementDefinition refineSubstatementDef = refineSubstatementCtx.getPublicDefinition();
+        final StatementDefinition refineSubstatementDef = refineSubstatementCtx.publicDefinition();
 
         SourceException.throwIf(!isSupportedRefineTarget(refineSubstatementCtx, refineTargetNodeCtx),
-                refineSubstatementCtx.getStatementSourceReference(),
+                refineSubstatementCtx.sourceReference(),
                 "Error in module '%s' in the refine of uses '%s': can not perform refine of '%s' for the target '%s'.",
-                refineSubstatementCtx.getRoot().getStatementArgument(),
-                refineSubstatementCtx.coerceParentContext().getStatementArgument(),
-                refineSubstatementCtx.getPublicDefinition(), refineTargetNodeCtx.getPublicDefinition());
+                refineSubstatementCtx.getRoot().rawArgument(), refineSubstatementCtx.coerceParentContext().argument(),
+                refineSubstatementCtx.publicDefinition(), refineTargetNodeCtx.publicDefinition());
 
         if (isAllowedToAddByRefine(refineSubstatementDef)) {
             refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
@@ -297,16 +353,16 @@ public final class UsesStatementSupport
                 ValidationBundlesNamespace.class, ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS);
 
         return supportedRefineSubstatements == null || supportedRefineSubstatements.isEmpty()
-                || supportedRefineSubstatements.contains(refineSubstatementCtx.getPublicDefinition())
+                || supportedRefineSubstatements.contains(refineSubstatementCtx.publicDefinition())
                 || StmtContextUtils.isUnknownStatement(refineSubstatementCtx);
     }
 
     private static boolean isSupportedRefineTarget(final StmtContext<?, ?, ?> refineSubstatementCtx,
             final StmtContext<?, ?, ?> refineTargetNodeCtx) {
         final Collection<?> supportedRefineTargets = YangValidationBundles.SUPPORTED_REFINE_TARGETS.get(
-            refineSubstatementCtx.getPublicDefinition());
+            refineSubstatementCtx.publicDefinition());
 
         return supportedRefineTargets == null || supportedRefineTargets.isEmpty()
-                || supportedRefineTargets.contains(refineTargetNodeCtx.getPublicDefinition());
+                || supportedRefineTargets.contains(refineTargetNodeCtx.publicDefinition());
     }
 }