Retain DeclarationReference in DeclaredStatements
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / uses / UsesStatementSupport.java
index 807fc494060da1909ddb629e9d4235ef09c29b79..e094d9d3d8e06007cb2f0e1fe75828912e98c762 100644 (file)
@@ -7,25 +7,48 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses;
 
-import com.google.common.base.Verify;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
+
+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.Empty;
 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.DeclarationReference;
+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.model.parser.api.YangParserConfiguration;
+import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
+import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
+import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins;
 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.YangValidationBundles;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.refine.RefineEffectiveStatementImpl;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.refine.RefineTargetNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
 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;
@@ -57,14 +80,9 @@ public final class UsesStatementSupport
         .addOptional(YangStmtMapping.STATUS)
         .addOptional(YangStmtMapping.WHEN)
         .build();
-    private static final UsesStatementSupport INSTANCE = new UsesStatementSupport();
-
-    private UsesStatementSupport() {
-        super(YangStmtMapping.USES);
-    }
 
-    public static UsesStatementSupport getInstance() {
-        return INSTANCE;
+    public UsesStatementSupport(final YangParserConfiguration config) {
+        super(YangStmtMapping.USES, StatementPolicy.exactReplica(), config);
     }
 
     @Override
@@ -80,7 +98,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);
@@ -99,30 +117,73 @@ public final class UsesStatementSupport
                 copyFromSourceToTarget(sourceGrpStmtCtx, targetNodeStmtCtx, usesNode);
                 resolveUsesNode(usesNode, targetNodeStmtCtx);
                 StmtContextUtils.validateIfFeatureAndWhenOnListKeys(usesNode);
+                usesNode.addToNs(SourceGroupingNamespace.class, Empty.getInstance(), sourceGrpStmtCtx);
             }
 
             @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,
+                    "Grouping '%s' was not resolved.", groupingName);
+                throw new InferenceException("Unknown error occurred.", usesNode);
             }
         });
     }
 
     @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 DeclaredStatements.createUses(ctx.getRawArgument(), ctx.getArgument(), substatements);
     }
 
     @Override
-    protected SubstatementValidator getSubstatementValidator() {
-        return SUBSTATEMENT_VALIDATOR;
+    protected UsesStatement attachDeclarationReference(final UsesStatement stmt, final DeclarationReference reference) {
+        return DeclaredStatementDecorators.decorateUses(stmt, reference);
+    }
+
+    @Override
+    protected UsesEffectiveStatement createEffective(final Current<QName, UsesStatement> stmt,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        final EffectiveStatement<?, ?> source =
+            verifyNotNull(stmt.getFromNamespace(SourceGroupingNamespace.class, Empty.getInstance())).buildEffective();
+        verify(source instanceof GroupingDefinition, "Unexpected source %s", source);
+        final GroupingDefinition sourceGrouping = (GroupingDefinition) source;
+
+        final int flags = EffectiveStatementMixins.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);
     }
 
     /**
@@ -137,6 +198,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) {
@@ -146,67 +209,55 @@ public final class UsesStatementSupport
         final QNameModule newQNameModule = getNewQNameModule(targetCtx, sourceGrpStmtCtx);
 
         for (final Mutable<?, ?, ?> original : declared) {
-            if (original.isSupportedByFeatures()) {
-                copyStatement(original, targetCtx, newQNameModule, buffer);
+            if (original.isSupportedByFeatures() && shouldCopy(original)) {
+                original.copyAsChildOf(targetCtx, CopyType.ADDED_BY_USES, newQNameModule).ifPresent(buffer::add);
             }
         }
 
         for (final Mutable<?, ?, ?> original : effective) {
-            copyStatement(original, targetCtx, newQNameModule, buffer);
+            if (shouldCopy(original)) {
+                original.copyAsChildOf(targetCtx, CopyType.ADDED_BY_USES, newQNameModule).ifPresent(buffer::add);
+            }
         }
 
         targetCtx.addEffectiveSubstatements(buffer);
         usesNode.addAsEffectOfStatement(buffer);
     }
 
-    // Note: do not put CopyPolicy.DECLARED_COPY, we treat non-presence as such
-    private static final ImmutableMap<StatementDefinition, CopyPolicy> GROUPING_TO_TARGET_POLICY =
-            ImmutableMap.<StatementDefinition, CopyPolicy>builder()
-                // FIXME: YANGTOOLS-652: this map looks very much like InferredStatementContext.REUSED_DEF_SET
-                // a grouping's type/typedef statements are fully defined at the grouping, we want the same effective
-                // statement
-                .put(YangStmtMapping.TYPE, CopyPolicy.CONTEXT_INDEPENDENT)
-                .put(YangStmtMapping.TYPEDEF, CopyPolicy.CONTEXT_INDEPENDENT)
-
-                // We do not want to propagate description/reference/status statements, as they are the source
-                // grouping's documentation, not target statement's
-                .put(YangStmtMapping.DESCRIPTION, CopyPolicy.IGNORE)
-                .put(YangStmtMapping.REFERENCE, CopyPolicy.IGNORE)
-                .put(YangStmtMapping.STATUS, CopyPolicy.IGNORE)
-
-                // Do not propagate uses, as their effects have been accounted for in effective statements
-                // FIXME: YANGTOOLS-652: this check is different from InferredStatementContext. Why is that? We should
-                //                       express a common condition in our own implementation of applyCopyPolicy() --
-                //                       most notably reactor performs the equivalent of CopyPolicy.CONTEXT_INDEPENDENT.
-                // FIXME: YANGTOOLS-694: note that if the above is true, why are we propagating grouping statements?
-                .put(YangStmtMapping.USES, CopyPolicy.IGNORE)
-                .build();
-
-    private static void copyStatement(final Mutable<?, ?, ?> original,
-            final StatementContextBase<?, ?, ?> targetCtx, final QNameModule targetModule,
-            final Collection<Mutable<?, ?, ?>> buffer) {
-
-        // FIXME: YANGTOOLS-694: This method needs to be adjusted to account for RFC7950,
-        //                       https://tools.ietf.org/html/rfc7950#section-7.13, which states that:
+    private static boolean shouldCopy(final StmtContext<?, ?, ?> stmt) {
+        // https://tools.ietf.org/html/rfc7950#section-7.13:
         //
         //        The effect of a "uses" reference to a grouping is that the nodes
         //        defined by the grouping are copied into the current schema tree and
         //        are then updated according to the "refine" and "augment" statements.
         //
-        //                       This means that the statement that is about to be copied (and can be subjected to
-        //                       buildEffective() I think) is actually a SchemaTreeEffectiveStatement -- i.e. if it
-        //                       is not a SchemaTreeEffectiveStatement, it just cannot be added to target's tree and
-        //                       hence it should not be copied.
-        final CopyPolicy policy = GROUPING_TO_TARGET_POLICY.get(original.getPublicDefinition());
-        if (policy == null) {
-            original.copyAsChildOf(targetCtx, CopyType.ADDED_BY_USES, targetModule).ifPresent(buffer::add);
-        } else if (policy == CopyPolicy.CONTEXT_INDEPENDENT) {
-            buffer.add(original);
-        } else if (policy == CopyPolicy.IGNORE) {
-            // No-op
-        } else {
-            throw new IllegalStateException("Unhandled policy " + policy);
+        // 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.publicDefinition().getEffectiveRepresentationClass())) {
+            return true;
         }
+
+        // As per https://tools.ietf.org/html/rfc7950#section-7.13.2:
+        //
+        //        o  Any node can get refined extensions, if the extension allows
+        //           refinement.  See Section 7.19 for details.
+        //
+        // and https://tools.ietf.org/html/rfc7950#section-7.19:
+        //
+        //        An extension can allow refinement (see Section 7.13.2) and deviations
+        //        (Section 7.20.3.2), but the mechanism for how this is defined is
+        //        outside the scope of this specification.
+        //
+        // This is actively used out there (tailf-common.yang's tailf:action), which is incorrect, though. They do
+        // publish a bunch of metadata (through tailf-meta-extension.yang), but fail to publish a key aspect of the
+        // statement: it attaches to schema tree namespace (just as RFC7950 action does). Such an extension would
+        // automatically result in the extension being picked up by the above check and everybody would live happily
+        // ever after.
+        //
+        // We do not live in that world yet, hence we do the following and keep our fingers crossed.
+        // FIXME: YANGTOOLS-403: this should not be necessary once we implement the above (although tests will complain)
+        return StmtContextUtils.isUnknownStatement(stmt);
     }
 
     private static QNameModule getNewQNameModule(final StmtContext<?, ?, ?> targetCtx,
@@ -214,12 +265,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();
         }
@@ -227,11 +278,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);
             }
         }
@@ -241,33 +293,40 @@ public final class UsesStatementSupport
         /*
          * In case of Yang 1.1, checks whether features are supported.
          */
-        return !YangVersion.VERSION_1_1.equals(subStmtCtx.getRootVersion()) || subStmtCtx.isSupportedByFeatures();
+        return !YangVersion.VERSION_1_1.equals(subStmtCtx.yangVersion()) || subStmtCtx.isSupportedByFeatures();
     }
 
     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,
             "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(),
-            "Refine target node %s not found.", refineArgument);
+        InferenceException.throwIf(!optRefineTargetCtx.isPresent(), subStmtCtx, "Refine target node %s not found.",
+            refineArgument);
 
+        // FIXME: This communicates the looked-up target node to RefineStatementSupport.buildEffective(). We should do
+        //        this trick through a shared namespace or similar reactor-agnostic meeting place. It really feels like
+        //        an inference action RefineStatementSupport should be doing.
         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());
-            subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
-            return;
+                + "Refine has been skipped. At line: {}", subStmtCtx.argument(),
+                subStmtCtx.coerceParentContext().argument(), refineTargetNodeCtx.argument(),
+                subStmtCtx.sourceReference());
+        } else {
+            verify(refineTargetNodeCtx instanceof StatementContextBase);
+            addOrReplaceNodes(subStmtCtx, (StatementContextBase<?, ?, ?>) refineTargetNodeCtx);
         }
 
-        Verify.verify(refineTargetNodeCtx instanceof StatementContextBase);
-        addOrReplaceNodes(subStmtCtx, (StatementContextBase<?, ?, ?>) refineTargetNodeCtx);
-        subStmtCtx.addAsEffectOfStatement(refineTargetNodeCtx);
+        // Target is a prerequisite for the 'refine', hence if the target is not supported, the refine is not supported
+        // as well. Otherwise add a pointer to the target into refine's local namespace.
+        if (refineTargetNodeCtx.isSupportedToBuildEffective()) {
+            subStmtCtx.addToNs(RefineTargetNamespace.class, Empty.getInstance(), refineTargetNodeCtx);
+        } else {
+            subStmtCtx.setIsSupportedToBuildEffective(false);
+        }
     }
 
     private static void addOrReplaceNodes(final Mutable<?, ?, ?> subStmtCtx,
@@ -282,23 +341,21 @@ 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,
                 "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);
-        } else {
+        if (!isAllowedToAddByRefine(refineSubstatementDef)) {
             refineTargetNodeCtx.removeStatementFromEffectiveSubstatements(refineSubstatementDef);
-            refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx);
         }
+        refineTargetNodeCtx.addEffectiveSubstatement(refineSubstatementCtx.replicaAsChildOf(refineTargetNodeCtx));
     }
 
+    // FIXME: clarify this and inline into single caller
     private static boolean isAllowedToAddByRefine(final StatementDefinition publicDefinition) {
         return YangStmtMapping.MUST.equals(publicDefinition);
     }
@@ -308,16 +365,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());
     }
 }