Centralize substatement validators
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / module / ModuleStatementSupport.java
index 65ada4e4e091d1f6ec8bc14cdadca1c73f853ff1..9026d06136669c8a40397fee8914dc1bff137c87 100644 (file)
@@ -8,12 +8,11 @@
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.module;
 
 import static com.google.common.base.Verify.verify;
-import static java.util.Objects.requireNonNull;
+import static com.google.common.base.Verify.verifyNotNull;
 import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -21,13 +20,16 @@ import java.util.Map;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.openconfig.model.api.OpenConfigStatements;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.common.UnqualifiedQName;
+import org.opendaylight.yangtools.yang.common.XMLNamespace;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Submodule;
 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.stmt.ModuleEffectiveStatement;
@@ -37,11 +39,15 @@ import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.SubstatementIndexingException;
+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.SubstatementIndexingException;
+import org.opendaylight.yangtools.yang.parser.api.ImportResolutionMode;
+import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
 import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CommonStmtCtx;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionModuleNamespace;
@@ -64,82 +70,80 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 @Beta
 public final class ModuleStatementSupport
-        extends BaseStatementSupport<UnqualifiedQName, ModuleStatement, ModuleEffectiveStatement> {
-    private static final @NonNull ModuleStatementSupport RFC6020_INSTANCE = new ModuleStatementSupport(
-        SubstatementValidator.builder(YangStmtMapping.MODULE)
-            .addAny(YangStmtMapping.ANYXML)
-            .addAny(YangStmtMapping.AUGMENT)
-            .addAny(YangStmtMapping.CHOICE)
-            .addOptional(YangStmtMapping.CONTACT)
-            .addAny(YangStmtMapping.CONTAINER)
-            .addOptional(YangStmtMapping.DESCRIPTION)
-            .addAny(YangStmtMapping.DEVIATION)
-            .addAny(YangStmtMapping.EXTENSION)
-            .addAny(YangStmtMapping.FEATURE)
-            .addAny(YangStmtMapping.GROUPING)
-            .addAny(YangStmtMapping.IDENTITY)
-            .addAny(YangStmtMapping.IMPORT)
-            .addAny(YangStmtMapping.INCLUDE)
-            .addAny(YangStmtMapping.LEAF)
-            .addAny(YangStmtMapping.LEAF_LIST)
-            .addAny(YangStmtMapping.LIST)
-            .addMandatory(YangStmtMapping.NAMESPACE)
-            .addAny(YangStmtMapping.NOTIFICATION)
-            .addOptional(YangStmtMapping.ORGANIZATION)
-            .addMandatory(YangStmtMapping.PREFIX)
-            .addOptional(YangStmtMapping.REFERENCE)
-            .addAny(YangStmtMapping.REVISION)
-            .addAny(YangStmtMapping.RPC)
-            .addAny(YangStmtMapping.TYPEDEF)
-            .addAny(YangStmtMapping.USES)
-            .addOptional(YangStmtMapping.YANG_VERSION)
-            .addOptional(OpenConfigStatements.OPENCONFIG_VERSION)
-            .build());
-    private static final @NonNull ModuleStatementSupport RFC7950_INSTANCE = new ModuleStatementSupport(
-        SubstatementValidator.builder(YangStmtMapping.MODULE)
-            .addAny(YangStmtMapping.ANYDATA)
-            .addAny(YangStmtMapping.ANYXML)
-            .addAny(YangStmtMapping.AUGMENT)
-            .addAny(YangStmtMapping.CHOICE)
-            .addOptional(YangStmtMapping.CONTACT)
-            .addAny(YangStmtMapping.CONTAINER)
-            .addOptional(YangStmtMapping.DESCRIPTION)
-            .addAny(YangStmtMapping.DEVIATION)
-            .addAny(YangStmtMapping.EXTENSION)
-            .addAny(YangStmtMapping.FEATURE)
-            .addAny(YangStmtMapping.GROUPING)
-            .addAny(YangStmtMapping.IDENTITY)
-            .addAny(YangStmtMapping.IMPORT)
-            .addAny(YangStmtMapping.INCLUDE)
-            .addAny(YangStmtMapping.LEAF)
-            .addAny(YangStmtMapping.LEAF_LIST)
-            .addAny(YangStmtMapping.LIST)
-            .addMandatory(YangStmtMapping.NAMESPACE)
-            .addAny(YangStmtMapping.NOTIFICATION)
-            .addOptional(YangStmtMapping.ORGANIZATION)
-            .addMandatory(YangStmtMapping.PREFIX)
-            .addOptional(YangStmtMapping.REFERENCE)
-            .addAny(YangStmtMapping.REVISION)
-            .addAny(YangStmtMapping.RPC)
-            .addAny(YangStmtMapping.TYPEDEF)
-            .addAny(YangStmtMapping.USES)
-            .addMandatory(YangStmtMapping.YANG_VERSION)
-            .addOptional(OpenConfigStatements.OPENCONFIG_VERSION)
-            .build());
-
-    private final SubstatementValidator validator;
-
-    private ModuleStatementSupport(final SubstatementValidator validator) {
-        super(YangStmtMapping.MODULE, CopyPolicy.REJECT);
-        this.validator = requireNonNull(validator);
+        extends AbstractStatementSupport<UnqualifiedQName, ModuleStatement, ModuleEffectiveStatement> {
+    private static final SubstatementValidator RFC6020_VALIDATOR = SubstatementValidator.builder(YangStmtMapping.MODULE)
+        .addAny(YangStmtMapping.ANYXML)
+        .addAny(YangStmtMapping.AUGMENT)
+        .addAny(YangStmtMapping.CHOICE)
+        .addOptional(YangStmtMapping.CONTACT)
+        .addAny(YangStmtMapping.CONTAINER)
+        .addOptional(YangStmtMapping.DESCRIPTION)
+        .addAny(YangStmtMapping.DEVIATION)
+        .addAny(YangStmtMapping.EXTENSION)
+        .addAny(YangStmtMapping.FEATURE)
+        .addAny(YangStmtMapping.GROUPING)
+        .addAny(YangStmtMapping.IDENTITY)
+        .addAny(YangStmtMapping.IMPORT)
+        .addAny(YangStmtMapping.INCLUDE)
+        .addAny(YangStmtMapping.LEAF)
+        .addAny(YangStmtMapping.LEAF_LIST)
+        .addAny(YangStmtMapping.LIST)
+        .addMandatory(YangStmtMapping.NAMESPACE)
+        .addAny(YangStmtMapping.NOTIFICATION)
+        .addOptional(YangStmtMapping.ORGANIZATION)
+        .addMandatory(YangStmtMapping.PREFIX)
+        .addOptional(YangStmtMapping.REFERENCE)
+        .addAny(YangStmtMapping.REVISION)
+        .addAny(YangStmtMapping.RPC)
+        .addAny(YangStmtMapping.TYPEDEF)
+        .addAny(YangStmtMapping.USES)
+        .addOptional(YangStmtMapping.YANG_VERSION)
+        .addOptional(OpenConfigStatements.OPENCONFIG_VERSION)
+        .build();
+    private static final SubstatementValidator RFC7950_VALIDATOR = SubstatementValidator.builder(YangStmtMapping.MODULE)
+        .addAny(YangStmtMapping.ANYDATA)
+        .addAny(YangStmtMapping.ANYXML)
+        .addAny(YangStmtMapping.AUGMENT)
+        .addAny(YangStmtMapping.CHOICE)
+        .addOptional(YangStmtMapping.CONTACT)
+        .addAny(YangStmtMapping.CONTAINER)
+        .addOptional(YangStmtMapping.DESCRIPTION)
+        .addAny(YangStmtMapping.DEVIATION)
+        .addAny(YangStmtMapping.EXTENSION)
+        .addAny(YangStmtMapping.FEATURE)
+        .addAny(YangStmtMapping.GROUPING)
+        .addAny(YangStmtMapping.IDENTITY)
+        .addAny(YangStmtMapping.IMPORT)
+        .addAny(YangStmtMapping.INCLUDE)
+        .addAny(YangStmtMapping.LEAF)
+        .addAny(YangStmtMapping.LEAF_LIST)
+        .addAny(YangStmtMapping.LIST)
+        .addMandatory(YangStmtMapping.NAMESPACE)
+        .addAny(YangStmtMapping.NOTIFICATION)
+        .addOptional(YangStmtMapping.ORGANIZATION)
+        .addMandatory(YangStmtMapping.PREFIX)
+        .addOptional(YangStmtMapping.REFERENCE)
+        .addAny(YangStmtMapping.REVISION)
+        .addAny(YangStmtMapping.RPC)
+        .addAny(YangStmtMapping.TYPEDEF)
+        .addAny(YangStmtMapping.USES)
+        .addMandatory(YangStmtMapping.YANG_VERSION)
+        .addOptional(OpenConfigStatements.OPENCONFIG_VERSION)
+        .build();
+
+    private final boolean semanticVersioning;
+
+    private ModuleStatementSupport(final YangParserConfiguration config, final SubstatementValidator validator) {
+        super(YangStmtMapping.MODULE, StatementPolicy.reject(), config, validator);
+        semanticVersioning = config.importResolutionMode() == ImportResolutionMode.OPENCONFIG_SEMVER;
     }
 
-    public static @NonNull ModuleStatementSupport rfc6020Instance() {
-        return RFC6020_INSTANCE;
+    public static @NonNull ModuleStatementSupport rfc6020Instance(final YangParserConfiguration config) {
+        return new ModuleStatementSupport(config, RFC6020_VALIDATOR);
     }
 
-    public static @NonNull ModuleStatementSupport rfc7950Instance() {
-        return RFC7950_INSTANCE;
+    public static @NonNull ModuleStatementSupport rfc7950Instance(final YangParserConfiguration config) {
+        return new ModuleStatementSupport(config, RFC7950_VALIDATOR);
     }
 
     @Override
@@ -155,7 +159,7 @@ public final class ModuleStatementSupport
     public void onPreLinkageDeclared(final Mutable<UnqualifiedQName, ModuleStatement, ModuleEffectiveStatement> stmt) {
         final String moduleName = stmt.getRawArgument();
 
-        final URI moduleNs = SourceException.throwIfNull(
+        final XMLNamespace moduleNs = SourceException.throwIfNull(
             firstAttributeOf(stmt.declaredSubstatements(), NamespaceStatement.class), stmt,
             "Namespace of the module [%s] is missing", moduleName);
         stmt.addToNs(ModuleNameToNamespace.class, moduleName, moduleNs);
@@ -176,7 +180,7 @@ public final class ModuleStatementSupport
 
     @Override
     public void onLinkageDeclared(final Mutable<UnqualifiedQName, ModuleStatement, ModuleEffectiveStatement> stmt) {
-        final URI moduleNs = SourceException.throwIfNull(
+        final XMLNamespace moduleNs = SourceException.throwIfNull(
             firstAttributeOf(stmt.declaredSubstatements(), NamespaceStatement.class), stmt,
             "Namespace of the module [%s] is missing", stmt.argument());
 
@@ -200,6 +204,7 @@ public final class ModuleStatementSupport
             firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class), stmt,
             "Prefix of the module [%s] is missing", stmt.argument());
 
+        stmt.addToNs(QNameModuleNamespace.class, Empty.getInstance(), qNameModule);
         stmt.addToNs(PrefixToModule.class, modulePrefix, qNameModule);
         stmt.addToNs(ModuleNameToModuleQName.class, moduleName, qNameModule);
         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule);
@@ -207,16 +212,11 @@ public final class ModuleStatementSupport
         stmt.addToNs(ModuleQNameToModuleName.class, qNameModule, moduleName);
         stmt.addToNs(ImportPrefixToModuleCtx.class, modulePrefix, stmt);
 
-        if (stmt.isEnabledSemanticVersioning()) {
+        if (semanticVersioning) {
             addToSemVerModuleNamespace(stmt, moduleIdentifier);
         }
     }
 
-    @Override
-    protected SubstatementValidator getSubstatementValidator() {
-        return validator;
-    }
-
     @Override
     protected ImmutableList<? extends EffectiveStatement<?, ?>> buildEffectiveSubstatements(
             final Current<UnqualifiedQName, ModuleStatement> stmt,
@@ -247,12 +247,16 @@ public final class ModuleStatementSupport
     @Override
     protected ModuleStatement createDeclared(final StmtContext<UnqualifiedQName, ModuleStatement, ?> ctx,
             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        return new ModuleStatementImpl(ctx.getRawArgument(), ctx.getArgument(), substatements);
+        if (substatements.isEmpty()) {
+            throw noNamespace(ctx);
+        }
+        return DeclaredStatements.createModule(ctx.getRawArgument(), ctx.getArgument(), substatements);
     }
 
     @Override
-    protected ModuleStatement createEmptyDeclared(final StmtContext<UnqualifiedQName, ModuleStatement, ?> ctx) {
-        throw noNamespace(ctx);
+    protected ModuleStatement attachDeclarationReference(final ModuleStatement stmt,
+            final DeclarationReference reference) {
+        return DeclaredStatementDecorators.decorateModule(stmt, reference);
     }
 
     @Override
@@ -269,15 +273,17 @@ public final class ModuleStatementSupport
             submodules.add((Submodule) submodule);
         }
 
+        final QNameModule qnameModule = verifyNotNull(stmt.namespaceItem(QNameModuleNamespace.class,
+            Empty.getInstance()));
         try {
-            return new ModuleEffectiveStatementImpl(stmt, substatements, submodules);
+            return new ModuleEffectiveStatementImpl(stmt, substatements, submodules, qnameModule);
         } catch (SubstatementIndexingException e) {
             throw new SourceException(e.getMessage(), stmt, e);
         }
     }
 
     private static Collection<StmtContext<?, ?, ?>> submoduleContexts(final Current<?, ?> stmt) {
-        final Map<String, StmtContext<?, ?, ?>> submodules = stmt.getAllFromCurrentStmtCtxNamespace(
+        final Map<String, StmtContext<?, ?, ?>> submodules = stmt.localNamespacePortion(
             IncludedSubmoduleNameToModuleCtx.class);
         return submodules == null ? List.of() : submodules.values();
     }