X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fstmt%2Freactor%2FBuildGlobalContext.java;h=a4c0b4446b40dbc596e114a3ce6329b983133310;hb=82af449e4ef07d80490e79484d0402b81009541e;hp=ad6d70a823c9060d454394b2460d8cc43ce4f2b3;hpb=c4dc5b33e7d24670b59cc81b65e15b37a3268608;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java index ad6d70a823..a4c0b4446b 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java @@ -7,25 +7,28 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext; - -import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; +import com.google.common.base.Verify; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Set; +import java.util.function.Predicate; 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; import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; +import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour; 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; @@ -37,11 +40,20 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace; +import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures; +import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace; +import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType; import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext.PhaseCompletionProgress; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBehaviour.Registry { + private static final Logger LOG = LoggerFactory.getLogger(BuildGlobalContext.class); private static final List PHASE_EXECUTION_ORDER = ImmutableList.builder() + .add(ModelProcessingPhase.SOURCE_PRE_LINKAGE) .add(ModelProcessingPhase.SOURCE_LINKAGE) .add(ModelProcessingPhase.STATEMENT_DEFINITION) .add(ModelProcessingPhase.FULL_DECLARATION) @@ -49,25 +61,40 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh .build(); private final Map> definitions = new HashMap<>(); - private final Map,NamespaceBehaviourWithListeners> namespaces = new HashMap<>(); - + private final Map,NamespaceBehaviourWithListeners> supportedNamespaces = new HashMap<>(); private final Map supports; private final Set sources = new HashSet<>(); - private ModelProcessingPhase currentPhase; - private ModelProcessingPhase finishedPhase; + private ModelProcessingPhase currentPhase = ModelProcessingPhase.INIT; + private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT; - public BuildGlobalContext(Map supports) { + public BuildGlobalContext(final Map supports, + final Predicate isFeatureSupported) { super(); - this.supports = supports; + this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null"); + + addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES, isFeatureSupported); } - public StatementSupportBundle getSupportsForPhase(ModelProcessingPhase currentPhase) { + public BuildGlobalContext(final Map supports, + final Map> supportedValidation, + final Predicate isFeatureSupported) { + super(); + this.supports = Preconditions.checkNotNull(supports, "BuildGlobalContext#supports cannot be null"); + + for (Entry> validationBundle : supportedValidation.entrySet()) { + addToNs(ValidationBundlesNamespace.class, validationBundle.getKey(), validationBundle.getValue()); + } + + addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES, isFeatureSupported); + } + + public StatementSupportBundle getSupportsForPhase(final ModelProcessingPhase currentPhase) { return supports.get(currentPhase); } - public void addSource(@Nonnull StatementStreamSource source) { + public void addSource(@Nonnull final StatementStreamSource source) { sources.add(new SourceSpecificContext(this,source)); } @@ -87,32 +114,45 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh } @Override - public > NamespaceBehaviourWithListeners getNamespaceBehaviour(Class type) { - NamespaceBehaviourWithListeners potential = namespaces.get(type); + public > NamespaceBehaviourWithListeners getNamespaceBehaviour(final Class type) { + NamespaceBehaviourWithListeners potential = supportedNamespaces.get(type); if (potential == null) { NamespaceBehaviour potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type); - if(potentialRaw != null) { - potential = new NamespaceBehaviourWithListeners<>(potentialRaw); - namespaces.put(type, potential); + if (potentialRaw != null) { + potential = createNamespaceContext(potentialRaw); + supportedNamespaces.put(type, potential); + } else { + throw new NamespaceNotAvailableException( + "Namespace " + type + " is not available in phase " + currentPhase); } } - if (potential != null) { - Preconditions.checkState(type.equals(potential.getIdentifier())); - - /* - * Safe cast, previous checkState checks equivalence of key from - * which type argument are derived - */ - return (NamespaceBehaviourWithListeners) potential; + + Verify.verify(type.equals(potential.getIdentifier())); + /* + * Safe cast, previous checkState checks equivalence of key from which type argument are + * derived + */ + return (NamespaceBehaviourWithListeners) potential; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private > NamespaceBehaviourWithListeners createNamespaceContext( + final NamespaceBehaviour potentialRaw) { + if (potentialRaw instanceof DerivedNamespaceBehaviour) { + VirtualNamespaceContext derivedContext = + new VirtualNamespaceContext((DerivedNamespaceBehaviour) potentialRaw); + getNamespaceBehaviour(((DerivedNamespaceBehaviour) potentialRaw).getDerivedFrom()) + .addDerivedNamespace(derivedContext); + return derivedContext; } - throw new NamespaceNotAvailableException("Namespace " + type + "is not available in phase " + currentPhase); + return new SimpleNamespaceContext<>(potentialRaw); } - public StatementDefinitionContext getStatementDefinition(QName name) { + public StatementDefinitionContext getStatementDefinition(final QName name) { StatementDefinitionContext potential = definitions.get(name); - if(potential == null) { + if (potential == null) { StatementSupport potentialRaw = supports.get(currentPhase).getStatementDefinition(name); - if(potentialRaw != null) { + if (potentialRaw != null) { potential = new StatementDefinitionContext<>(potentialRaw); definitions.put(name, potential); } @@ -121,7 +161,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh } public EffectiveModelContext build() throws SourceException, ReactorException { - for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) { + for (ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) { startPhase(phase); loadPhaseStatements(); completePhaseActions(); @@ -132,16 +172,15 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh private EffectiveModelContext transform() { Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL); - List> rootStatements = new ArrayList<>(); - for(SourceSpecificContext source : sources) { - DeclaredStatement root = source.getRoot().buildDeclared(); - rootStatements.add(root); + List> rootStatements = new ArrayList<>(sources.size()); + for (SourceSpecificContext source : sources) { + rootStatements.add(source.getRoot().buildDeclared()); } return new EffectiveModelContext(rootStatements); } public EffectiveSchemaContext buildEffective() throws SourceException, ReactorException { - for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) { + for (ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) { startPhase(phase); loadPhaseStatements(); completePhaseActions(); @@ -152,23 +191,21 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh private EffectiveSchemaContext transformEffective() { Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL); - List> rootStatements = new ArrayList<>(); - List> rootEffectiveStatements = new ArrayList<>(); + List> rootStatements = new ArrayList<>(sources.size()); + List> rootEffectiveStatements = new ArrayList<>(sources.size()); - for(SourceSpecificContext source : sources) { - DeclaredStatement root = source.getRoot().buildDeclared(); - rootStatements.add(root); - - EffectiveStatement rootEffective = source.getRoot().buildEffective(); - rootEffectiveStatements.add(rootEffective); + for (SourceSpecificContext source : sources) { + final RootStatementContext root = source.getRoot(); + rootStatements.add(root.buildDeclared()); + rootEffectiveStatements.add(root.buildEffective()); } - return new EffectiveSchemaContext(rootStatements,rootEffectiveStatements); + return new EffectiveSchemaContext(rootStatements, rootEffectiveStatements); } - private void startPhase(ModelProcessingPhase phase) { + private void startPhase(final ModelProcessingPhase phase) { Preconditions.checkState(Objects.equals(finishedPhase, phase.getPreviousPhase())); - for(SourceSpecificContext source : sources) { + for (SourceSpecificContext source : sources) { source.startPhase(phase); } currentPhase = phase; @@ -176,46 +213,90 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh private void loadPhaseStatements() throws SourceException { Preconditions.checkState(currentPhase != null); - for(SourceSpecificContext source : sources) { + for (SourceSpecificContext source : sources) { source.loadStatements(); } } + private SomeModifiersUnresolvedException addSourceExceptions(final SomeModifiersUnresolvedException buildFailure, + final List sourcesToProgress) { + boolean addedCause = false; + for (SourceSpecificContext failedSource : sourcesToProgress) { + final SourceException sourceEx = failedSource.failModifiers(currentPhase); + + // Workaround for broken logging implementations which ignore suppressed exceptions + Throwable cause = sourceEx.getCause() != null ? sourceEx.getCause() : sourceEx; + if (LOG.isDebugEnabled()) { + LOG.error("Failed to parse YANG from source {}", failedSource, sourceEx); + } else { + LOG.error("Failed to parse YANG from source {}: {}", failedSource, cause.getMessage()); + } + + final Throwable[] suppressed = sourceEx.getSuppressed(); + if (suppressed.length > 0) { + LOG.error("{} additional errors reported:", suppressed.length); + + int i = 1; + for (Throwable t : suppressed) { + // FIXME: this should be configured in the appender, really + if (LOG.isDebugEnabled()) { + LOG.error("Error {}: {}", i, t.getMessage(), t); + } else { + LOG.error("Error {}: {}", i, t.getMessage()); + } + + i++; + } + } + + if (!addedCause) { + addedCause = true; + buildFailure.initCause(sourceEx); + } else { + buildFailure.addSuppressed(sourceEx); + } + } + return buildFailure; + } + private void completePhaseActions() throws ReactorException { Preconditions.checkState(currentPhase != null); List sourcesToProgress = Lists.newArrayList(sources); try { boolean progressing = true; - while(progressing) { + while (progressing) { // We reset progressing to false. progressing = false; Iterator currentSource = sourcesToProgress.iterator(); - while(currentSource.hasNext()) { - PhaseCompletionProgress sourceProgress = currentSource.next().tryToCompletePhase(currentPhase); + while (currentSource.hasNext()) { + SourceSpecificContext nextSourceCtx = currentSource.next(); + PhaseCompletionProgress sourceProgress = nextSourceCtx.tryToCompletePhase(currentPhase); switch (sourceProgress) { case FINISHED: currentSource.remove(); + // Fallback to progress, since we were able to make progress in computation case PROGRESS: progressing = true; + break; case NO_PROGRESS: - // Noop; + // Noop + break; + default: + throw new IllegalStateException("Unsupported phase progress " + sourceProgress); } } } } catch (SourceException e) { throw Throwables.propagate(e); } - if(!sourcesToProgress.isEmpty()) { + if (!sourcesToProgress.isEmpty()) { SomeModifiersUnresolvedException buildFailure = new SomeModifiersUnresolvedException(currentPhase); - for(SourceSpecificContext failedSource : sourcesToProgress) { - SourceException sourceEx = failedSource.failModifiers(currentPhase); - buildFailure.addSuppressed(sourceEx); - } - throw buildFailure; + buildFailure = addSourceExceptions(buildFailure, sourcesToProgress); + throw buildFailure; } } - private void endPhase(ModelProcessingPhase phase) { + private void endPhase(final ModelProcessingPhase phase) { Preconditions.checkState(currentPhase == phase); finishedPhase = currentPhase; } @@ -223,5 +304,4 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh public Set getSources() { return sources; } - }