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=64351b8818efafe5e5ba4ea85b4c9c2261ecd774;hb=ea32c2c6fac2ebe9d0e30c9c4e5279c5ef0d2314;hp=b2d56f8f77e145b7c0834e7507258e0d0d74f5a2;hpb=2f4d0df2556a810996193ea21ebe58021e9f89a0;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 b2d56f8f77..64351b8818 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 @@ -9,17 +9,26 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor; import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import javax.annotation.Nullable; 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.model.api.ModuleIdentifier; 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.model.api.meta.StatementDefinition; +import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement; +import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.ImportedNamespaceContext; import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; @@ -27,12 +36,29 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType; +import org.opendaylight.yangtools.yang.parser.spi.meta.QNameCacheNamespace; +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.source.BelongsToPrefixToModuleIdentifier; +import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier; +import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName; import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; +import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModuleMap; import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; +import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinitionMap; 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.reactor.StatementContextBase.ContextBuilder; +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.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; public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable { @@ -47,40 +73,79 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh private final Collection importedNamespaces = new ArrayList<>(); private final Multimap modifiers = HashMultimap.create(); - private RootStatementContext root; + private RootStatementContext root; private ModelProcessingPhase inProgressPhase; - private ModelProcessingPhase finishedPhase; + private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT; + private final QNameToStatementDefinitionMap qNameToStmtDefMap = new QNameToStatementDefinitionMap(); + private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap(); - SourceSpecificContext(BuildGlobalContext currentContext,StatementStreamSource source) { + SourceSpecificContext(final BuildGlobalContext currentContext, final StatementStreamSource source) { this.source = source; this.currentContext = currentContext; } - StatementDefinitionContext getDefinition(QName name) { + ModelProcessingPhase getInProgressPhase() { + return inProgressPhase; + } + + StatementDefinitionContext getDefinition(final QName name) { return currentContext.getStatementDefinition(name); } - ContextBuilder createDeclaredChild(StatementContextBase current, QName name, StatementSourceReference ref) { - StatementDefinitionContext def = getDefinition(name); - Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.",name); - if(current == null) { - return createDeclaredRoot(def,ref); + ContextBuilder createDeclaredChild(final StatementContextBase current, final QName name, final StatementSourceReference ref) { + StatementDefinitionContext def = getDefinition(name); + + if (def == null) { + //unknown-stmts (from import, include or local-scope) + if (qNameToStmtDefMap.get(name) != null) { + final StatementContextBase extension = (StatementContextBase) currentContext + .getAllFromNamespace(ExtensionNamespace.class).get(name); + if (extension != null) { + final QName arg = (QName) extension.getStatementArgument(); + final QName qName = current.getFromNamespace(QNameCacheNamespace.class, + QName.create(arg, extension.getIdentifier().getArgument())); + + def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition( + getNewStatementDefinition(qName))); + } else { + throw new IllegalArgumentException("Not found unknown statement: " + name); + } + } else { + // type-body-stmts + def = resolveTypeBodyStmts(name.getLocalName()); + } + } + else if (current != null && current.definition().getRepresentingClass().equals(UnknownStatementImpl.class)) { + QName qName = Utils.qNameFromArgument(current, name.getLocalName()); + + def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition + (getNewStatementDefinition(qName))); + } + + Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.", name); + if (current == null) { + return createDeclaredRoot(def, ref); } - return current.substatementBuilder(def,ref); + return current.substatementBuilder(def, ref); + } + + // FIXME: This should be populated differently + StatementDefinition getNewStatementDefinition(final QName qName) { + return new ModelDefinedStatementDefinition(qName); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - private ContextBuilder createDeclaredRoot(StatementDefinitionContext def, StatementSourceReference ref) { - return new ContextBuilder(def,ref) { + @SuppressWarnings({"rawtypes", "unchecked"}) + private ContextBuilder createDeclaredRoot(final StatementDefinitionContext def, final StatementSourceReference ref) { + return new ContextBuilder(def, ref) { @Override public StatementContextBase build() throws SourceException { - if(root == null) { + if (root == null) { root = new RootStatementContext(this, SourceSpecificContext.this); } else { - Preconditions.checkState(root.getIdentifier().equals(getIdentifier()), "Root statement was already defined."); + Preconditions.checkState(root.getIdentifier().equals(createIdentifier()), "Root statement was already defined as %s.", root.getIdentifier()); } root.resetLists(); return root; @@ -89,7 +154,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh }; } - RootStatementContext getRoot() { + RootStatementContext getRoot() { return root; } @@ -97,11 +162,11 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh return root.buildDeclared(); } - EffectiveStatement build() { + EffectiveStatement buildEffective() { return root.buildEffective(); } - void startPhase(ModelProcessingPhase phase) { + void startPhase(final ModelProcessingPhase phase) { @Nullable ModelProcessingPhase previousPhase = phase.getPreviousPhase(); Preconditions.checkState(Objects.equals(previousPhase, finishedPhase)); Preconditions.checkState(modifiers.get(previousPhase).isEmpty()); @@ -109,8 +174,8 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } @Override - public > void addToLocalStorage(Class type, K key, V value) { - if(ImportedNamespaceContext.class.isAssignableFrom(type)) { + public > void addToLocalStorage(final Class type, final K key, final V value) { + if (ImportedNamespaceContext.class.isAssignableFrom(type)) { importedNamespaces.add((NamespaceStorageNode) value); } getRoot().addToLocalStorage(type, key, value); @@ -122,14 +187,33 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } @Override - public > V getFromLocalStorage(Class type, K key) { + public > V getFromLocalStorage(final Class type, final K key) { final V potentialLocal = getRoot().getFromLocalStorage(type, key); - if(potentialLocal != null) { + if (potentialLocal != null) { return potentialLocal; } - for(NamespaceStorageNode importedSource : importedNamespaces) { + for (NamespaceStorageNode importedSource : importedNamespaces) { V potential = importedSource.getFromLocalStorage(type, key); - if(potential != null) { + if (potential != null) { + return potential; + } + } + return null; + } + + @Nullable + @Override + public > Map getAllFromLocalStorage(final Class type) { + final Map potentialLocal = getRoot().getAllFromLocalStorage(type); + + if (potentialLocal != null) { + return potentialLocal; + } + + for (final NamespaceStorageNode importedSource : importedNamespaces) { + final Map potential = importedSource.getAllFromLocalStorage(type); + + if (potential != null) { return potential; } } @@ -137,7 +221,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh } @Override - public > NamespaceBehaviour getNamespaceBehaviour(Class type) { + public > NamespaceBehaviour getNamespaceBehaviour(final Class type) { return currentContext.getNamespaceBehaviour(type); } @@ -146,28 +230,43 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh return currentContext; } - PhaseCompletionProgress tryToCompletePhase(ModelProcessingPhase phase) throws SourceException { + PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException { Collection currentPhaseModifiers = modifiers.get(phase); - Iterator modifier = currentPhaseModifiers.iterator(); - boolean hasProgressed = false; - while(modifier.hasNext()) { - if(modifier.next().isApplied()) { - modifier.remove(); - hasProgressed = true; - } - } - if(root.tryToCompletePhase(phase) && currentPhaseModifiers.isEmpty()) { + + boolean hasProgressed = tryToProgress(currentPhaseModifiers); + + boolean phaseCompleted = root.tryToCompletePhase(phase); + + hasProgressed = (tryToProgress(currentPhaseModifiers) | hasProgressed); + + if (phaseCompleted && (currentPhaseModifiers.isEmpty())) { finishedPhase = phase; return PhaseCompletionProgress.FINISHED; } - if(hasProgressed) { + if (hasProgressed) { return PhaseCompletionProgress.PROGRESS; } return PhaseCompletionProgress.NO_PROGRESS; } - ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) { + + private static boolean tryToProgress(final Collection currentPhaseModifiers) { + + Iterator modifier = currentPhaseModifiers.iterator(); + boolean hasProgressed = false; + while (modifier.hasNext()) { + if (modifier.next().tryApply()) { + modifier.remove(); + hasProgressed = true; + } + } + + return hasProgressed; + + } + + ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) { ModifierImpl action = new ModifierImpl(phase); modifiers.put(phase, action); return action; @@ -179,43 +278,107 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh + finishedPhase + "]"; } - SourceException failModifiers(ModelProcessingPhase identifier) { - InferenceException sourceEx = new InferenceException("Fail to infer source relationships", root.getStatementSourceReference()); - - - for(ModifierImpl mod : modifiers.get(identifier)) { + SourceException failModifiers(final ModelProcessingPhase identifier) { + final List exceptions = new ArrayList<>(); + for (ModifierImpl mod : modifiers.get(identifier)) { try { mod.failModifier(); } catch (SourceException e) { - sourceEx.addSuppressed(e); + exceptions.add(e); } } - return sourceEx; + + final String message = String.format("Yang model processing phase %s failed", identifier); + if (exceptions.isEmpty()) { + return new InferenceException(message, root.getStatementSourceReference()); + } + + final InferenceException e = new InferenceException(message, root.getStatementSourceReference(), + exceptions.get(0)); + final Iterator it = exceptions.listIterator(1); + while (it.hasNext()) { + e.addSuppressed(it.next()); + } + + return e; } void loadStatements() throws SourceException { switch (inProgressPhase) { - case SOURCE_LINKAGE: - source.writeLinkage(new StatementContextWriter(this, inProgressPhase),stmtDef()); - break; - case STATEMENT_DEFINITION: - source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes()); - case FULL_DECLARATION: - source.writeFull(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes()); + case SOURCE_LINKAGE: + source.writeLinkage(new StatementContextWriter(this, inProgressPhase), stmtDef()); + break; + case STATEMENT_DEFINITION: + source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes()); + break; + case FULL_DECLARATION: + source.writeFull(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes()); + break; + default: + break; + } + } - default: - break; + private static StatementDefinitionContext resolveTypeBodyStmts(final String typeArgument) { + switch (typeArgument) { + case TypeUtils.DECIMAL64: + return new StatementDefinitionContext<>(new Decimal64SpecificationImpl.Definition()); + case TypeUtils.UNION: + return new StatementDefinitionContext<>(new UnionSpecificationImpl.Definition()); + case TypeUtils.ENUMERATION: + return new StatementDefinitionContext<>(new EnumSpecificationImpl.Definition()); + case TypeUtils.LEAF_REF: + return new StatementDefinitionContext<>(new LeafrefSpecificationImpl.Definition()); + case TypeUtils.BITS: + return new StatementDefinitionContext<>(new BitsSpecificationImpl.Definition()); + case TypeUtils.IDENTITY_REF: + return new StatementDefinitionContext<>(new IdentityRefSpecificationImpl.Definition()); + case TypeUtils.INSTANCE_IDENTIFIER: + return new StatementDefinitionContext<>(new InstanceIdentifierSpecificationImpl.Definition()); + default: + return null; } } private PrefixToModule prefixes() { - // TODO Auto-generated method stub - return null; + final Map allPrefixes = getRoot().getAllFromNamespace(ImpPrefixToModuleIdentifier + .class); + final Map belongsToPrefixes = getRoot().getAllFromNamespace + (BelongsToPrefixToModuleIdentifier.class); + if (belongsToPrefixes != null) + allPrefixes.putAll(belongsToPrefixes); + + for (Entry stringModuleIdentifierEntry : allPrefixes.entrySet()) { + final QNameModule namespace = getRoot().getFromNamespace(ModuleIdentifierToModuleQName.class, + stringModuleIdentifierEntry.getValue()); + prefixToModuleMap.put(stringModuleIdentifierEntry.getKey(), namespace); + } + return prefixToModuleMap; } private QNameToStatementDefinition stmtDef() { - // TODO Auto-generated method stub - return null; - } + //regular YANG statements added + ImmutableMap> definitions = currentContext.getSupportsForPhase( + inProgressPhase).getDefinitions(); + for (Map.Entry> entry : definitions.entrySet()) { + qNameToStmtDefMap.put(entry.getKey(), entry.getValue()); + } + //extensions added + if (inProgressPhase.equals(ModelProcessingPhase.FULL_DECLARATION)) { + Map>> extensions = currentContext + .getAllFromNamespace(ExtensionNamespace.class); + if (extensions != null) { + for (Map.Entry>> extension : extensions + .entrySet()) { + qNameToStmtDefMap + .put((extension.getKey()), + (StatementDefinition) ((StatementContextBase) extension + .getValue()).definition() + .getFactory()); + } + } + } + return qNameToStmtDefMap; + } }