*/
package org.opendaylight.yangtools.rfc8040.parser;
+import static com.google.common.base.Verify.verifyNotNull;
+
import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.rfc8040.model.api.YangDataEffectiveStatement;
import org.opendaylight.yangtools.rfc8040.model.api.YangDataStatement;
import org.opendaylight.yangtools.rfc8040.model.api.YangDataStatements;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.common.QName;
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.parser.spi.meta.AbstractDeclaredStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithRawStringArgument.WithSubstatements;
+import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStringStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.MissingSubstatementException;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
@Beta
-public final class YangDataStatementSupport extends AbstractStatementSupport<String, YangDataStatement,
- EffectiveStatement<String, YangDataStatement>> {
+public final class YangDataStatementSupport
+ extends AbstractStringStatementSupport<YangDataStatement, YangDataEffectiveStatement> {
/**
* Declared statement representation of 'yang-data' extension defined in
* <a href="https://tools.ietf.org/html/rfc8040#section-8">RFC 8040</a>.
*/
- private static final class Declared extends AbstractDeclaredStatement<String> implements YangDataStatement {
- Declared(final StmtContext<String, YangDataStatement, ?> ctx) {
- super(ctx);
- }
-
- @Override
- public String getArgument() {
- return argument();
+ private static final class Declared extends WithSubstatements implements YangDataStatement {
+ Declared(final String rawArgument, final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+ super(rawArgument, substatements);
}
}
- private static final YangDataStatementSupport INSTANCE = new YangDataStatementSupport(YangDataStatements.YANG_DATA);
-
- private final SubstatementValidator validator;
+ private final SubstatementValidator declaredValidator;
- private YangDataStatementSupport(final StatementDefinition definition) {
- super(definition);
- validator = SubstatementValidator.builder(definition)
+ public YangDataStatementSupport(final YangParserConfiguration config) {
+ super(YangDataStatements.YANG_DATA, StatementPolicy.reject(), config);
+ declaredValidator = SubstatementValidator.builder(YangDataStatements.YANG_DATA)
.addMandatory(YangStmtMapping.CONTAINER)
.addOptional(YangStmtMapping.USES)
.build();
}
- public static YangDataStatementSupport getInstance() {
- return INSTANCE;
- }
-
@Override
- protected SubstatementValidator getSubstatementValidator() {
- return validator;
+ public void onStatementAdded(final Mutable<String, YangDataStatement, YangDataEffectiveStatement> ctx) {
+ // as per https://tools.ietf.org/html/rfc8040#section-8,
+ // yang-data is ignored unless it appears as a top-level statement
+ if (ctx.coerceParentContext().getParentContext() != null) {
+ ctx.setIsSupportedToBuildEffective(false);
+ }
}
@Override
- public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
- return value;
+ public void onFullDefinitionDeclared(final Mutable<String, YangDataStatement, YangDataEffectiveStatement> ctx) {
+ // Parse and populate our argument to be picked up when we build the effecitve statement
+ final String argument = SourceException.throwIfNull(ctx.argument(), ctx, "yang-data requires an argument");
+ final QName qname = StmtContextUtils.parseIdentifier(ctx, argument);
+ ctx.addToNs(YangDataArgumentNamespace.class, Empty.getInstance(), qname);
}
@Override
- public YangDataStatement createDeclared(final StmtContext<String, YangDataStatement, ?> ctx) {
- return new Declared(ctx);
+ public boolean isIgnoringIfFeatures() {
+ return true;
}
@Override
- public EffectiveStatement<String, YangDataStatement> createEffective(final StmtContext<String,
- YangDataStatement, EffectiveStatement<String, YangDataStatement>> ctx) {
- // in case of yang-data node we need to perform substatement validation at the point when we have
- // effective substatement contexts already available - if the node has only a uses statement declared in it,
- // one top-level container node may very well be added to the yang-data as an effective statement
- validator.validate(ctx);
- return new YangDataEffectiveStatementImpl(ctx);
+ public boolean isIgnoringConfig() {
+ return true;
}
@Override
- public void onFullDefinitionDeclared(final Mutable<String, YangDataStatement,
- EffectiveStatement<String, YangDataStatement>> ctx) {
- // as per https://tools.ietf.org/html/rfc8040#section-8,
- // yang-data is ignored unless it appears as a top-level statement
- if (ctx.coerceParentContext().getParentContext() != null) {
- ctx.setIsSupportedToBuildEffective(false);
- }
+ protected SubstatementValidator getSubstatementValidator() {
+ return declaredValidator;
}
@Override
- public boolean isIgnoringIfFeatures() {
- return true;
+ protected YangDataStatement createDeclared(@NonNull final StmtContext<String, YangDataStatement, ?> ctx,
+ final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+ return new Declared(ctx.getRawArgument(), substatements);
}
@Override
- public boolean isIgnoringConfig() {
- return true;
+ protected YangDataEffectiveStatement createEffective(final Current<String, YangDataStatement> stmt,
+ final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+ // So now we need to deal with effective validation. The requirement is that:
+ // It MUST contain data definition statements
+ // that result in exactly one container data node definition.
+ final long dataDefs = substatements.stream().filter(DataTreeEffectiveStatement.class::isInstance).count();
+ if (dataDefs == 0) {
+ throw new MissingSubstatementException("yang-data requires exactly one container", stmt.sourceReference());
+ }
+ if (dataDefs > 1) {
+ throw new InvalidSubstatementException(stmt,
+ "yang-data requires exactly one data definition node, found %s", dataDefs);
+ }
+
+ return new YangDataEffectiveStatementImpl(stmt, substatements,
+ verifyNotNull(stmt.namespaceItem(YangDataArgumentNamespace.class, Empty.getInstance())));
}
-}
\ No newline at end of file
+}