*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
+import java.util.HashSet;
+import java.util.Set;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
.add(Rfc6020Mapping.STATUS, 0, 1)
.build();
- protected ExtensionStatementImpl(StmtContext<QName, ExtensionStatement,?> context) {
+ protected ExtensionStatementImpl(final StmtContext<QName, ExtensionStatement,?> context) {
super(context);
}
public static class Definition extends AbstractStatementSupport<QName,ExtensionStatement,EffectiveStatement<QName,ExtensionStatement>> {
+ private static final ThreadLocal<Set<StmtContext<?, ?, ?>>> BUILDING = new ThreadLocal<>();
public Definition() {
super(Rfc6020Mapping.EXTENSION);
}
@Override
- public QName parseArgumentValue(StmtContext<?,?,?> ctx, String value) {
+ public QName parseArgumentValue(final StmtContext<?,?,?> ctx, final String value) {
return Utils.qNameFromArgument(ctx, value);
}
@Override
- public ExtensionStatement createDeclared(StmtContext<QName, ExtensionStatement,?> ctx) {
+ public ExtensionStatement createDeclared(final StmtContext<QName, ExtensionStatement,?> ctx) {
return new ExtensionStatementImpl(ctx);
}
@Override
- public EffectiveStatement<QName,ExtensionStatement> createEffective(StmtContext<QName,ExtensionStatement,EffectiveStatement<QName,ExtensionStatement>> ctx) {
- return new ExtensionEffectiveStatementImpl(ctx);
+ public EffectiveStatement<QName,ExtensionStatement> createEffective(
+ final StmtContext<QName,ExtensionStatement, EffectiveStatement<QName,ExtensionStatement>> ctx) {
+ Set<StmtContext<?, ?, ?>> building = BUILDING.get();
+ if (building == null) {
+ building = new HashSet<>();
+ BUILDING.set(building);
+ }
+
+ SourceException.throwIf(building.contains(ctx), ctx.getStatementSourceReference(),
+ "Extension %s references itself", ctx.getStatementArgument());
+
+ building.add(ctx);
+ try {
+ return new ExtensionEffectiveStatementImpl(ctx);
+ } finally {
+ building.remove(ctx);
+ if (building.isEmpty()) {
+ BUILDING.remove();
+ }
+ }
}
@Override
}
@Override
- public void onFullDefinitionDeclared(StmtContext.Mutable<QName, ExtensionStatement,
- EffectiveStatement<QName, ExtensionStatement>> stmt) throws SourceException {
+ public void onFullDefinitionDeclared(final StmtContext.Mutable<QName, ExtensionStatement,
+ EffectiveStatement<QName, ExtensionStatement>> stmt) {
super.onFullDefinitionDeclared(stmt);
SUBSTATEMENT_VALIDATOR.validate(stmt);
}
private final String reference;
private final Status status;
- AbstractEffectiveDocumentedNode(final StmtContext<A, D, ?> ctx) {
- this(ctx, true);
- }
-
/**
* Constructor.
*
* @param ctx
* context of statement.
- * @param buildUnknownSubstatements
- * if it is false, the unknown substatements are omitted from
- * build of effective substatements till the call of either
- * effectiveSubstatements or getOmittedUnknownSubstatements
- * method of EffectiveStatementBase class. The main purpose of
- * this is to allow the build of recursive extension definitions.
*/
- AbstractEffectiveDocumentedNode(final StmtContext<A, D, ?> ctx, boolean buildUnknownSubstatements) {
- super(ctx, buildUnknownSubstatements);
+ protected AbstractEffectiveDocumentedNode(final StmtContext<A, D, ?> ctx) {
+ super(ctx);
DescriptionEffectiveStatementImpl descStmt = firstEffective(DescriptionEffectiveStatementImpl.class);
if (descStmt != null) {
featuresInit.add((FeatureDefinition) effectiveStatement);
}
if (effectiveStatement instanceof ExtensionEffectiveStatementImpl) {
- ExtensionEffectiveStatementImpl extensionDefinition = (ExtensionEffectiveStatementImpl) effectiveStatement;
- extensionDefinition.initUnknownSchemaNodes();
- extensionNodesInit
- .add(extensionDefinition);
+ extensionNodesInit.add((ExtensionEffectiveStatementImpl) effectiveStatement);
}
if (effectiveStatement instanceof DataSchemaNode) {
DataSchemaNode dataSchemaNode = (DataSchemaNode) effectiveStatement;
private final A argument;
private final D declaredInstance;
- public DeclaredEffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
- this(ctx, true);
- }
-
/**
* Constructor.
*
* @param ctx
* context of statement.
- * @param buildUnknownSubstatements
- * if it is false, the unknown substatements are omitted from
- * build of effective substatements till the call of either
- * effectiveSubstatements or getOmittedUnknownSubstatements
- * method of EffectiveStatementBase class. The main purpose of
- * this is to allow the build of recursive extension definitions.
*/
- protected DeclaredEffectiveStatementBase(StmtContext<A, D, ?> ctx, final boolean buildUnknownSubstatements) {
- super(ctx, buildUnknownSubstatements);
+ protected DeclaredEffectiveStatementBase(StmtContext<A, D, ?> ctx) {
+ super(ctx);
this.argument = ctx.getStatementArgument();
this.statementSource = ctx.getStatementSource();
public final D getDeclared() {
return declaredInstance;
}
-}
\ No newline at end of file
+}
};
private final List<? extends EffectiveStatement<?, ?>> substatements;
- private final List<StatementContextBase<?, ?, ?>> unknownSubstatementsToBuild;
-
- protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
- this(ctx, true);
- }
/**
* Constructor.
*
* @param ctx
* context of statement.
- * @param buildUnknownSubstatements
- * if it is false, the unknown substatements are omitted from
- * build of effective substatements till the call of either
- * effectiveSubstatements or getOmittedUnknownSubstatements
- * method. The main purpose of this is to allow the build of
- * recursive extension definitions.
*/
- protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx, boolean buildUnknownSubstatements) {
-
+ protected EffectiveStatementBase(final StmtContext<A, D, ?> ctx) {
final Collection<StatementContextBase<?, ?, ?>> effectiveSubstatements = ctx.effectiveSubstatements();
final Collection<StatementContextBase<?, ?, ?>> substatementsInit = new ArrayList<>();
}
substatementsInit.addAll(effectiveSubstatements);
- Collection<StatementContextBase<?, ?, ?>> substatementsToBuild = Collections2.filter(substatementsInit,
- IS_SUPPORTED_TO_BUILD_EFFECTIVE);
- if (!buildUnknownSubstatements) {
- this.unknownSubstatementsToBuild = ImmutableList.copyOf(Collections2.filter(substatementsToBuild,
- IS_UNKNOWN_STATEMENT_CONTEXT));
- substatementsToBuild = Collections2.filter(substatementsToBuild,
- Predicates.not(IS_UNKNOWN_STATEMENT_CONTEXT));
- } else {
- this.unknownSubstatementsToBuild = ImmutableList.of();
- }
-
- this.substatements = ImmutableList.copyOf(Collections2.transform(substatementsToBuild,
- StmtContextUtils.buildEffective()));
- }
-
- Collection<EffectiveStatement<?, ?>> getOmittedUnknownSubstatements() {
- return Collections2.transform(unknownSubstatementsToBuild,
- StmtContextUtils.buildEffective());
+ this.substatements = ImmutableList.copyOf(Collections2.transform(Collections2.filter(substatementsInit,
+ IS_SUPPORTED_TO_BUILD_EFFECTIVE), StmtContextUtils.buildEffective()));
}
@Override
@Override
public final Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
- if (unknownSubstatementsToBuild.isEmpty()) {
- return substatements;
- } else {
- return ImmutableList.copyOf(Iterables.concat(substatements, getOmittedUnknownSubstatements()));
- }
+ return substatements;
}
protected final <S extends EffectiveStatement<?, ?>> S firstEffective(final Class<S> type) {
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.Objects;
import org.opendaylight.yangtools.yang.common.QName;
private final String argument;
private final SchemaPath schemaPath;
- private List<UnknownSchemaNode> unknownNodes;
+ private final List<UnknownSchemaNode> unknownNodes;
private final boolean yin;
public ExtensionEffectiveStatementImpl(
final StmtContext<QName, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>> ctx) {
- super(ctx, false);
+ super(ctx);
this.qname = ctx.getStatementArgument();
this.schemaPath = ctx.getSchemaPath().get();
+ final List<UnknownSchemaNode> unknownNodesInit = new ArrayList<>();
+ for (EffectiveStatement<?, ?> unknownNode : effectiveSubstatements()) {
+ if (unknownNode instanceof UnknownSchemaNode) {
+ unknownNodesInit.add((UnknownSchemaNode) unknownNode);
+ }
+ }
+ this.unknownNodes = ImmutableList.copyOf(unknownNodesInit);
+
// initFields
ArgumentEffectiveStatementImpl argumentSubstatement = firstEffective(ArgumentEffectiveStatementImpl.class);
if (argumentSubstatement != null) {
}
}
- void initUnknownSchemaNodes() {
- if (unknownNodes != null) {
- return;
- }
-
- Collection<EffectiveStatement<?, ?>> buildedUnknownNodes = getOmittedUnknownSubstatements();
- List<UnknownSchemaNode> unknownNodesInit = new ArrayList<>();
- for (EffectiveStatement<?, ?> unknownNode : buildedUnknownNodes) {
- if (unknownNode instanceof UnknownSchemaNode) {
- unknownNodesInit.add((UnknownSchemaNode) unknownNode);
- }
- }
- this.unknownNodes = ImmutableList.copyOf(unknownNodesInit);
- }
-
@Override
public QName getQName() {
return qname;
@Override
public List<UnknownSchemaNode> getUnknownSchemaNodes() {
- if(unknownNodes == null) {
- initUnknownSchemaNodes();
- }
return unknownNodes;
}
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
public class Bug4456Test {
- @Test
+ @Test(expected=SourceException.class)
public void test() throws IOException, URISyntaxException, SourceException, ReactorException {
SchemaContext schema = StmtTestUtils.parseYangSources("/bugs/bug4456");
assertNotNull(schema);