return getPublicView().isArgumentYinElement();
}
+ @Override
+ public boolean hasArgumentSpecificSupports() {
+ // Most of statement supports don't have any argument specific
+ // supports, so return 'false'.
+ return false;
+ }
+
+ @Override
+ public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
+ // Most of statement supports don't have any argument specific
+ // supports, so return null.
+ return null;
+ }
+
/**
* Returns corresponding substatement validator of a statement support
*
package org.opendaylight.yangtools.yang.parser.spi.meta;
import java.util.Optional;
+import javax.annotation.Nullable;
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;
* @throws SourceException when an inconsistency is detected.
*/
void onFullDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt);
+
+ /**
+ * Returns true if this support has argument specific supports.
+ */
+ boolean hasArgumentSpecificSupports();
+
+ /**
+ * If this support has argument specific supports, the method returns
+ * support specific for given argument (e.g. type statement support need to
+ * be specialized based on its argument), otherwise returns null.
+ *
+ * @param argument
+ * argument of statement
+ * @return statement support specific for supplied argument or null
+ */
+ @Nullable
+ StatementSupport<?, ?, ?> getSupportSpecificForArgument(String argument);
}
\ No newline at end of file
import com.google.common.base.Verify;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Multimap;
-import com.google.common.collect.Table;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
-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.source.SourceException;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.BitsSpecificationImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Decimal64SpecificationImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.EnumSpecificationImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.IdentityRefSpecificationImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.InstanceIdentifierSpecificationImpl;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.LeafrefSpecificationImpl;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.ModelDefinedStatementDefinition;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnionSpecificationImpl;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.IdentityrefSpecificationRfc7950Support;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.LeafrefSpecificationRfc7950Support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
private static final Logger LOG = LoggerFactory.getLogger(SourceSpecificContext.class);
- private static final Table<YangVersion, String, StatementSupport<?, ?, ?>> BUILTIN_TYPE_SUPPORTS =
- ImmutableTable.<YangVersion, String, StatementSupport<?, ?, ?>>builder()
- .put(YangVersion.VERSION_1, TypeUtils.DECIMAL64, new Decimal64SpecificationImpl.Definition())
- .put(YangVersion.VERSION_1, TypeUtils.UNION, new UnionSpecificationImpl.Definition())
- .put(YangVersion.VERSION_1, TypeUtils.ENUMERATION, new EnumSpecificationImpl.Definition())
- .put(YangVersion.VERSION_1, TypeUtils.LEAF_REF, new LeafrefSpecificationImpl.Definition())
- .put(YangVersion.VERSION_1_1, TypeUtils.LEAF_REF, new LeafrefSpecificationRfc7950Support())
- .put(YangVersion.VERSION_1, TypeUtils.BITS, new BitsSpecificationImpl.Definition())
- .put(YangVersion.VERSION_1, TypeUtils.IDENTITY_REF, new IdentityRefSpecificationImpl.Definition())
- .put(YangVersion.VERSION_1_1, TypeUtils.IDENTITY_REF, new IdentityrefSpecificationRfc7950Support())
- .put(YangVersion.VERSION_1, TypeUtils.INSTANCE_IDENTIFIER, new InstanceIdentifierSpecificationImpl.Definition())
- .build();
-
- private static final QName TYPE = YangStmtMapping.TYPE.getStatementName();
-
private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
private final QNameToStatementDefinitionMap qNameToStmtDefMap = new QNameToStatementDefinitionMap();
private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap();
}
StatementContextBase<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final int childId,
- QName name, final String argument, final StatementSourceReference ref) {
+ final QName name, final String argument, final StatementSourceReference ref) {
if (current != null) {
// Fast path: we are entering a statement which was emitted in previous phase
StatementContextBase<?, ?, ?> existing = current.lookupSubstatement(childId);
}
}
- // FIXME: BUG-7038: Refactor/clean up this special case
- if (TYPE.equals(name)) {
- SourceException.throwIfNull(argument, ref, "Type statement requires an argument");
- if (TypeUtils.isYangTypeBodyStmtString(argument)) {
- name = QName.create(YangConstants.RFC6020_YIN_MODULE, argument);
- } else {
- name = QName.create(YangConstants.RFC6020_YIN_MODULE, TYPE.getLocalName());
- }
- }
-
StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(getRootVersion(), name);
if (def == null) {
final StatementSupport<?, ?, ?> extension = qNameToStmtDefMap.get(name);
if (extension != null) {
def = new StatementDefinitionContext<>(extension);
- } else {
- // type-body-stmts
- def = resolveTypeBodyStmts(name.getLocalName(), getRootVersion());
}
} else if (current != null && current.definition().getRepresentingClass().equals(UnknownStatementImpl.class)) {
/*
SourceException.throwIf(argument != null, ref, "Statement %s does not take argument", name);
}
+ /*
+ * If the current statement definition has argument specific
+ * sub-definitions, get argument specific sub-definition based on given
+ * argument (e.g. type statement need to be specialized based on its
+ * argument).
+ */
+ if (def.hasArgumentSpecificSubDefinitions()) {
+ def = def.getSubDefinitionSpecificForArgument(argument);
+ }
+
if (current != null) {
return current.createSubstatement(childId, def, ref, argument);
}
}
}
- private static StatementDefinitionContext<?, ?, ?> resolveTypeBodyStmts(final String typeArgument,
- final YangVersion version) {
- StatementSupport<?, ?, ?> support = BUILTIN_TYPE_SUPPORTS.get(version, typeArgument);
-
- if (support == null) {
- support = BUILTIN_TYPE_SUPPORTS.get(YangVersion.VERSION_1, typeArgument);
- }
-
- return support == null ? null : new StatementDefinitionContext<>(support);
- }
-
private PrefixToModule preLinkagePrefixes() {
final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap(true);
final Map<String, URI> prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class);
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Preconditions;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Optional;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
public class StatementDefinitionContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> {
private final StatementSupport<A, D, E> support;
+ private final Map<String, StatementDefinitionContext<?, ?, ?>> argumentSpecificSubDefinitions;
public StatementDefinitionContext(final StatementSupport<A, D, E> support) {
this.support = Preconditions.checkNotNull(support);
+ this.argumentSpecificSubDefinitions = support.hasArgumentSpecificSupports() ? new HashMap<>() : null;
}
public StatementFactory<A,D,E> getFactory() {
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
return toStringHelper.add("statement", getStatementName());
}
+
+ @Nonnull
+ public StatementDefinitionContext<?, ?, ?> getSubDefinitionSpecificForArgument(final String argument) {
+ if (!hasArgumentSpecificSubDefinitions()) {
+ return this;
+ }
+
+ StatementDefinitionContext<?, ?, ?> potential = argumentSpecificSubDefinitions.get(argument);
+ if (potential == null) {
+ final StatementSupport<?, ?, ?> argumentSpecificSupport = support.getSupportSpecificForArgument(argument);
+ potential = argumentSpecificSupport != null ? new StatementDefinitionContext<>(argumentSpecificSupport)
+ : this;
+ argumentSpecificSubDefinitions.put(argument, potential);
+ }
+
+ return potential;
+ }
+
+ public boolean hasArgumentSpecificSubDefinitions() {
+ return support.hasArgumentSpecificSupports();
+ }
}
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableMap;
import java.util.Collection;
+import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
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.source.SourceException;
extends
AbstractStatementSupport<String, TypeStatement, EffectiveStatement<String, TypeStatement>> {
+ private static final Map<String, StatementSupport<?, ?, ?>> ARGUMENT_SPECIFIC_SUPPORTS = ImmutableMap
+ .<String, StatementSupport<?, ?, ?>> builder()
+ .put(TypeUtils.DECIMAL64, new Decimal64SpecificationImpl.Definition())
+ .put(TypeUtils.UNION, new UnionSpecificationImpl.Definition())
+ .put(TypeUtils.ENUMERATION, new EnumSpecificationImpl.Definition())
+ .put(TypeUtils.LEAF_REF, new LeafrefSpecificationImpl.Definition())
+ .put(TypeUtils.BITS, new BitsSpecificationImpl.Definition())
+ .put(TypeUtils.IDENTITY_REF, new IdentityRefSpecificationImpl.Definition())
+ .put(TypeUtils.INSTANCE_IDENTIFIER, new InstanceIdentifierSpecificationImpl.Definition()).build();
+
public Definition() {
super(YangStmtMapping.TYPE);
}
protected SubstatementValidator getSubstatementValidator() {
return SUBSTATEMENT_VALIDATOR;
}
+
+ @Override
+ public boolean hasArgumentSpecificSupports() {
+ return !ARGUMENT_SPECIFIC_SUPPORTS.isEmpty();
+ }
+
+ @Override
+ public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
+ return ARGUMENT_SPECIFIC_SUPPORTS.get(argument);
+ }
}
@Nonnull
import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.RefineStatementRfc7950Support;
import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.RpcStatementRfc7950Support;
import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.SubmoduleStatementRfc7950Support;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc7950.TypeStatementRfc7950Support;
public final class YangInferencePipeline {
public static final Set<YangVersion> SUPPORTED_VERSIONS = Sets.immutableEnumSet(VERSION_1, VERSION_1_1);
.addSupport(global(IdentityNamespace.class))
.addSupport(new DefaultStatementImpl.Definition())
.addSupport(new StatusStatementImpl.Definition())
- .addSupport(new TypeStatementImpl.Definition())
+ .addVersionSpecificSupport(VERSION_1, new TypeStatementImpl.Definition())
+ .addVersionSpecificSupport(VERSION_1_1, new TypeStatementRfc7950Support())
.addSupport(new UnitsStatementImpl.Definition())
.addSupport(new RequireInstanceStatementImpl.Definition())
.addVersionSpecificSupport(VERSION_1, new BitStatementImpl.Definition())
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeStatementImpl;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
+
+/**
+ * Class providing necessary support for processing YANG 1.1 Type statement.
+ */
+@Beta
+public final class TypeStatementRfc7950Support extends TypeStatementImpl.Definition {
+ private static final Map<String, StatementSupport<?, ?, ?>> ARGUMENT_SPECIFIC_SUPPORTS = ImmutableMap
+ .<String, StatementSupport<?, ?, ?>> builder()
+ .put(TypeUtils.LEAF_REF, new LeafrefSpecificationRfc7950Support())
+ .put(TypeUtils.IDENTITY_REF, new IdentityrefSpecificationRfc7950Support()).build();
+
+ @Override
+ public boolean hasArgumentSpecificSupports() {
+ return !ARGUMENT_SPECIFIC_SUPPORTS.isEmpty() || super.hasArgumentSpecificSupports();
+ }
+
+ @Override
+ public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
+ final StatementSupport<?, ?, ?> potential = ARGUMENT_SPECIFIC_SUPPORTS.get(argument);
+ return potential != null ? potential : super.getSupportSpecificForArgument(argument);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yangtools.yang.stmt;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+
+public class Bug7038Test {
+ @Test
+ public void unknownNodeTest() throws Exception {
+ final SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug7038");
+ assertNotNull(context);
+ assertEquals(1, context.getUnknownSchemaNodes().size());
+ }
+
+ @Test
+ public void testYang11() throws Exception {
+ final SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug7038/yang11");
+ assertNotNull(context);
+ }
+
+ @Test
+ public void testYang10() throws Exception {
+ try {
+ StmtTestUtils.parseYangSources("/bugs/bug7038/yang10");
+ } catch (final SomeModifiersUnresolvedException e) {
+ assertTrue(e.getCause().getMessage().startsWith("REQUIRE_INSTANCE is not valid for TYPE"));
+ }
+ }
+}
--- /dev/null
+module bar {
+ namespace bar;
+ prefix bar;
+
+ import foo { prefix decimal64; revision-date 1970-01-01; }
+
+ decimal64:decimal64 decimal64;
+}
--- /dev/null
+module foo {
+ namespace foo;
+ prefix foo;
+
+ extension decimal64 {
+ argument arg;
+ }
+}
--- /dev/null
+module foo {
+ namespace foo;
+ prefix foo;
+ yang-version 1;
+
+ container root {
+ leaf my-leafref {
+ type leafref {
+ path "../target";
+ require-instance false;
+ }
+ }
+ leaf target {
+ type string;
+ }
+ }
+}
--- /dev/null
+module foo {
+ namespace foo;
+ prefix foo;
+ yang-version 1.1;
+
+ container root {
+ leaf my-leafref {
+ type leafref {
+ path "../target";
+ require-instance false;
+ }
+ }
+ leaf target {
+ type string;
+ }
+ }
+}