X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FSourceSpecificContext.java;h=3206e0020f16a1ccb96ede5cb6bbce7dac2ae4f2;hb=256d2ca913643ae8d06053f6fb631f209d7eca64;hp=10fc62fe8f2b9c97dda593dd69ffea4d67f67b70;hpb=c92cf0a8da5dc50ca2e4acd142b963674c2ad76c;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java index 10fc62fe8f..3206e0020f 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java @@ -11,8 +11,9 @@ import com.google.common.base.Preconditions; import com.google.common.base.Verify; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +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; @@ -66,6 +67,7 @@ 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.LeafrefSpecificationRfc7950Support; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -77,43 +79,19 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh FINISHED } - @SuppressWarnings({"rawtypes", "unchecked"}) - private final class RootContextBuilder extends ContextBuilder { - RootContextBuilder(final StatementDefinitionContext def, final StatementSourceReference sourceRef) { - super(def, sourceRef); - } - - @Override - public StatementContextBase build() { - /* - * If root is null or root version is other than default, - * we need to create new root. - */ - if (root == null) { - root = new RootStatementContext(this, SourceSpecificContext.this); - } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.getRootVersion()) - && inProgressPhase == ModelProcessingPhase.SOURCE_LINKAGE) { - root = new RootStatementContext(this, SourceSpecificContext.this, root.getRootVersion()); - } else { - Preconditions.checkState(root.getIdentifier().equals(createIdentifier()), - "Root statement was already defined as %s.", root.getIdentifier()); - } - root.resetLists(); - return root; - } - } - private static final Logger LOG = LoggerFactory.getLogger(SourceSpecificContext.class); - private static final Map> BUILTIN_TYPE_SUPPORTS = - ImmutableMap.>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(); + private static final Table> BUILTIN_TYPE_SUPPORTS = + ImmutableTable.>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, TypeUtils.INSTANCE_IDENTIFIER, new InstanceIdentifierSpecificationImpl.Definition()) + .build(); + private static final QName TYPE = YangStmtMapping.TYPE.getStatementName(); private final Multimap modifiers = HashMultimap.create(); @@ -145,8 +123,16 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh return inProgressPhase; } - ContextBuilder createDeclaredChild(final StatementContextBase current, final int childId, + StatementContextBase createDeclaredChild(final StatementContextBase current, final int childId, QName name, final String argument, final StatementSourceReference ref) { + if (current != null) { + // Fast path: we are entering a statement which was emitted in previous phase + final StatementContextBase existing = current.lookupSubstatement(childId); + if (existing != null) { + return existing; + } + } + // FIXME: BUG-7038: Refactor/clean up this special case if (TYPE.equals(name)) { SourceException.throwIfNull(argument, ref, "Type statement requires an argument"); @@ -158,14 +144,13 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } 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()); + def = resolveTypeBodyStmts(name.getLocalName(), getRootVersion()); } } else if (current != null && current.definition().getRepresentingClass().equals(UnknownStatementImpl.class)) { /* @@ -178,22 +163,38 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh */ final QName qName = Utils.qNameFromArgument(current, name.getLocalName()); def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition( - new ModelDefinedStatementDefinition(qName))); + new ModelDefinedStatementDefinition(qName, argument != null))); } - Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.", name); - final ContextBuilder ret; - if (current == null) { - ret = new RootContextBuilder(def, ref); + InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name); + if (def.hasArgument()) { + SourceException.throwIfNull(argument, ref, "Statement %s requires an argument", name); } else { - ret = current.substatementBuilder(childId, def, ref); + SourceException.throwIf(argument != null, ref, "Statement %s does not take argument", name); } - if (argument != null) { - ret.setArgument(argument, ref); + if (current != null) { + return current.createSubstatement(childId, def, ref, argument); } - return ret; + /* + * If root is null or root version is other than default, + * we need to create new root. + */ + if (root == null) { + root = new RootStatementContext<>(this, def, ref, argument); + } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.getRootVersion()) + && inProgressPhase == ModelProcessingPhase.SOURCE_LINKAGE) { + root = new RootStatementContext<>(this, def, ref, argument, root.getRootVersion()); + } else { + final QName rootStatement = root.definition().getStatementName(); + final String rootArgument = root.rawStatementArgument(); + + Preconditions.checkState(Objects.equals(def.getStatementName(), rootStatement) + && Objects.equals(argument, rootArgument), + "Root statement was already defined as '%s %s'.", rootStatement, rootArgument); + } + return root; } RootStatementContext getRoot() { @@ -219,8 +220,15 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh void startPhase(final ModelProcessingPhase phase) { @Nullable final ModelProcessingPhase previousPhase = phase.getPreviousPhase(); - Preconditions.checkState(Objects.equals(previousPhase, finishedPhase)); - Preconditions.checkState(modifiers.get(previousPhase).isEmpty()); + Verify.verify(Objects.equals(previousPhase, finishedPhase), + "Phase sequencing violation: previous phase should be %s, source %s has %s", previousPhase, source, + finishedPhase); + + final Collection previousModifiers = modifiers.get(previousPhase); + Preconditions.checkState(previousModifiers.isEmpty(), + "Previous phase %s has unresolved modifiers %s in source %s", + previousPhase, previousModifiers, source); + inProgressPhase = phase; LOG.debug("Source {} started phase {}", source, phase); } @@ -381,8 +389,14 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } } - private static StatementDefinitionContext resolveTypeBodyStmts(final String typeArgument) { - final StatementSupport support = BUILTIN_TYPE_SUPPORTS.get(typeArgument); + 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); }