From 337a9eb06742549f4e6b218927c894c9c1afc7bf Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 26 Nov 2019 11:03:27 +0100 Subject: [PATCH] Rework EffectiveStatementBase statement order restoration Rather than relying on mutation of effective substatements when we are building an effective statements (and thus requiring StmtContext to be StatementContextBase), use simple filtering to implement statement ordering. This limits the scope of mutable state, explains what is going on and allows use of different StmtContext implementations. JIRA: YANGTOOLS-1042 Change-Id: I84a2517ef0ce666fbc2f2c6faa3b0d0a43eef6eb Signed-off-by: Robert Varga (cherry picked from commit 75276bc6d944ff002de8149108d60603349d49c6) --- .../stmt/reactor/StatementContextBase.java | 9 +++ .../rfc7950/stmt/EffectiveStatementBase.java | 55 ++++++++++++++++--- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index 2ed6bcdbdd..08ab75f794 100644 --- a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -321,6 +321,15 @@ public abstract class StatementContextBase, E return Collections.unmodifiableCollection(effective); } + /** + * Remove a set of statements from effective statements. + * + * @param statements statements to be removed + * @deprecated This method was used by EffectiveStatementBase to restore proper order of effects of uses statements. + * It is no longer used in that capacity and slated for removal. + */ + // FIXME: 5.0.0: remove this method + @Deprecated public void removeStatementsFromEffectiveSubstatements( final Collection> statements) { if (!effective.isEmpty()) { diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/EffectiveStatementBase.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/EffectiveStatementBase.java index 8542bbc550..e078fa2fcb 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/EffectiveStatementBase.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/EffectiveStatementBase.java @@ -14,18 +14,18 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.function.Predicate; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; 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.IdentifierNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; -import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; public abstract class EffectiveStatementBase> implements EffectiveStatement { private final @NonNull ImmutableList> substatements; @@ -36,21 +36,60 @@ public abstract class EffectiveStatementBase> * @param ctx context of statement. */ protected EffectiveStatementBase(final StmtContext ctx) { - final Collection> effectiveSubstatements = ctx.effectiveSubstatements(); final Collection> substatementsInit = new ArrayList<>(); + /* + * This dance is required to ensure that effects of 'uses' nodes are applied in the same order as + * the statements were defined -- i.e. if we have something like this: + * + * container foo { + * uses bar; + * uses baz; + * } + * + * grouping baz { + * leaf baz { + * type string; + * } + * } + * + * grouping bar { + * leaf bar { + * type string; + * } + * } + * + * The reactor would first inline 'uses baz' as that definition is the first one completely resolved and then + * inline 'uses bar'. Here we are iterating in declaration order re-inline the statements. + * + * TODO: this really should be handled by UsesStatementSupport such that 'uses baz' would have a prerequisite + * of a resolved 'uses bar'. + */ + Set> filteredStatements = null; for (final StmtContext declaredSubstatement : ctx.declaredSubstatements()) { if (declaredSubstatement.isSupportedByFeatures()) { substatementsInit.add(declaredSubstatement); - if (YangStmtMapping.USES == declaredSubstatement.getPublicDefinition()) { - final Collection> effect = - declaredSubstatement.getEffectOfStatement(); + + final Collection> effect = declaredSubstatement.getEffectOfStatement(); + if (!effect.isEmpty()) { + if (filteredStatements == null) { + filteredStatements = new HashSet<>(); + } + filteredStatements.addAll(effect); substatementsInit.addAll(effect); - ((StatementContextBase) ctx).removeStatementsFromEffectiveSubstatements(effect); } } } - substatementsInit.addAll(effectiveSubstatements); + + if (filteredStatements != null) { + for (StmtContext stmt : ctx.effectiveSubstatements()) { + if (!filteredStatements.contains(stmt)) { + substatementsInit.add(stmt); + } + } + } else { + substatementsInit.addAll(ctx.effectiveSubstatements()); + } this.substatements = ImmutableList.copyOf(initSubstatements(ctx, substatementsInit)); } -- 2.36.6