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%2FStatementContextBase.java;h=61244458cd561d6581535248b6f9dfdb3626b17f;hb=c24d6e2f39acbb11e22b5676bb7481ed52bec461;hp=d28dc9a458c472d70c13b7645c7e282779168e6d;hpb=6436cd3443272f3c574f65546fd26dc63f3b01c6;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index d28dc9a458..61244458cd 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -7,28 +7,30 @@ */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; -import java.util.LinkedList; - -import java.util.List; +import com.google.common.base.MoreObjects; +import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; -import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.EnumMap; import java.util.EventListener; import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; import javax.annotation.Nonnull; import org.opendaylight.yangtools.concepts.Identifiable; -import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; 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.meta.StatementSource; +import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory; +import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; @@ -43,23 +45,55 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWit public abstract class StatementContextBase, E extends EffectiveStatement> extends NamespaceStorageSupport implements StmtContext.Mutable, Identifiable { + @SuppressWarnings({ "rawtypes", "unchecked" }) + private final class SubContextBuilder extends ContextBuilder { + final int childId; + + SubContextBuilder(final int childId, final StatementDefinitionContext def, + final StatementSourceReference sourceRef) { + super(def, sourceRef); + this.childId = childId; + } + + @Override + public StatementContextBase build() { + StatementContextBase potential = substatements.get(childId); + if (potential == null) { + potential = new SubstatementContext(StatementContextBase.this, this); + substatements = substatements.put(childId, potential); + getDefinition().onStatementAdded(potential); + } + potential.resetLists(); + switch (this.getStamementSource().getStatementSource()) { + case DECLARATION: + addDeclaredSubstatement(potential); + break; + case CONTEXT: + addEffectiveSubstatement(potential); + break; + } + return potential; + } + } + /** * event listener when an item is added to model namespace */ interface OnNamespaceItemAdded extends EventListener { - - void namespaceItemAdded(StatementContextBase context, Class namespace, Object key, Object value) - throws SourceException; - + /** + * @throws SourceException + */ + void namespaceItemAdded(StatementContextBase context, Class namespace, Object key, Object value); } /** * event listener when a parsing {@link ModelProcessingPhase} is completed */ interface OnPhaseFinished extends EventListener { - - boolean phaseFinished(StatementContextBase context, ModelProcessingPhase phase) throws SourceException; - + /** + * @throws SourceException + */ + boolean phaseFinished(StatementContextBase context, ModelProcessingPhase phase); } /** @@ -68,40 +102,78 @@ public abstract class StatementContextBase, E interface ContextMutation { boolean isFinished(); - } private final StatementDefinitionContext definition; private final StatementIdentifier identifier; private final StatementSourceReference statementDeclSource; + + private Multimap phaseListeners = ImmutableMultimap.of(); + private Multimap phaseMutation = ImmutableMultimap.of(); + private Collection> declared = ImmutableList.of(); + private Collection> effective = ImmutableList.of(); + private Collection> effectOfStatement = ImmutableList.of(); + private StatementMap substatements = StatementMap.empty(); + + private SupportedByFeatures supportedByFeatures = SupportedByFeatures.UNDEFINED; + private CopyHistory copyHistory = CopyHistory.original(); + private boolean isSupportedToBuildEffective = true; + private ModelProcessingPhase completedPhase = null; + private StatementContextBase originalCtx; + private D declaredInstance; + private E effectiveInstance; private int order = 0; - private Map> substatements = new LinkedHashMap<>(); + StatementContextBase(@Nonnull final ContextBuilder builder) { + this.definition = builder.getDefinition(); + this.identifier = builder.createIdentifier(); + this.statementDeclSource = builder.getStamementSource(); + } - private Collection> declared = new ArrayList<>(); - private Collection> effective = new ArrayList<>(); - private Collection> effectOfStatement = new ArrayList<>(); + StatementContextBase(final StatementContextBase original) { + this.definition = Preconditions.checkNotNull(original.definition, + "Statement context definition cannot be null copying from: %s", original.getStatementSourceReference()); + this.identifier = Preconditions.checkNotNull(original.identifier, + "Statement context identifier cannot be null copying from: %s", original.getStatementSourceReference()); + this.statementDeclSource = Preconditions.checkNotNull(original.statementDeclSource, + "Statement context statementDeclSource cannot be null copying from: %s", + original.getStatementSourceReference()); + } + @Override public Collection> getEffectOfStatement() { return effectOfStatement; } - public void addAsEffectOfStatement(StatementContextBase ctx) { + @Override + public void addAsEffectOfStatement(final StatementContextBase ctx) { + if (effectOfStatement.isEmpty()) { + effectOfStatement = new ArrayList<>(1); + } effectOfStatement.add(ctx); } - private ModelProcessingPhase completedPhase; - - private Multimap phaseListeners = HashMultimap.create(); - private Multimap phaseMutation = HashMultimap.create(); + @Override + public void addAsEffectOfStatement(final Collection> ctxs) { + if (ctxs.isEmpty()) { + return; + } - private D declaredInstance; - private E effectiveInstance; + if (effectOfStatement.isEmpty()) { + effectOfStatement = new ArrayList<>(ctxs.size()); + } + effectOfStatement.addAll(ctxs); + } - private StatementContextBase originalCtx; - private List copyHistory; + @Override + public SupportedByFeatures getSupportedByFeatures() { + return supportedByFeatures; + } - private boolean isSupportedToBuildEffective = true; + @Override + public void setSupportedByFeatures(final boolean isSupported) { + this.supportedByFeatures = isSupported ? SupportedByFeatures.SUPPORTED : SupportedByFeatures.NOT_SUPPORTED; + } @Override public boolean isSupportedToBuildEffective() { @@ -109,23 +181,18 @@ public abstract class StatementContextBase, E } @Override - public void setIsSupportedToBuildEffective(boolean isSupportedToBuildEffective) { + public void setIsSupportedToBuildEffective(final boolean isSupportedToBuildEffective) { this.isSupportedToBuildEffective = isSupportedToBuildEffective; } @Override - public List getCopyHistory() { + public CopyHistory getCopyHistory() { return copyHistory; } @Override - public void addToCopyHistory(TypeOfCopy typeOfCopy) { - this.copyHistory.add(typeOfCopy); - } - - @Override - public void addAllToCopyHistory(List typeOfCopyList) { - this.copyHistory.addAll(typeOfCopyList); + public void appendCopyHistory(final CopyType typeOfCopy, final CopyHistory toAppend) { + copyHistory = copyHistory.append(typeOfCopy, toAppend); } @Override @@ -134,12 +201,12 @@ public abstract class StatementContextBase, E } @Override - public void setOriginalCtx(StatementContextBase originalCtx) { + public void setOriginalCtx(final StatementContextBase originalCtx) { this.originalCtx = originalCtx; } @Override - public void setOrder(int order) { + public void setOrder(final int order) { this.order = order; } @@ -154,34 +221,10 @@ public abstract class StatementContextBase, E } @Override - public void setCompletedPhase(ModelProcessingPhase completedPhase) { + public void setCompletedPhase(final ModelProcessingPhase completedPhase) { this.completedPhase = completedPhase; } - StatementContextBase(@Nonnull ContextBuilder builder) throws SourceException { - this.definition = builder.getDefinition(); - this.identifier = builder.createIdentifier(); - this.statementDeclSource = builder.getStamementSource(); - this.completedPhase = null; - initCopyHistory(); - } - - StatementContextBase(StatementContextBase original) { - this.definition = Preconditions - .checkNotNull(original.definition, "Statement context definition cannot be null"); - this.identifier = Preconditions - .checkNotNull(original.identifier, "Statement context identifier cannot be null"); - this.statementDeclSource = Preconditions.checkNotNull(original.statementDeclSource, - "Statement context statementDeclSource cannot be null"); - this.completedPhase = null; - initCopyHistory(); - } - - private void initCopyHistory() { - this.copyHistory = new LinkedList<>(); - this.copyHistory.add(TypeOfCopy.ORIGINAL); - } - /** * @return context of parent of statement */ @@ -191,6 +234,7 @@ public abstract class StatementContextBase, E /** * @return root context of statement */ + @Nonnull @Override public abstract RootStatementContext getRoot(); @@ -205,6 +249,7 @@ public abstract class StatementContextBase, E /** * @return origin of statement */ + @Nonnull @Override public StatementSource getStatementSource() { return statementDeclSource.getStatementSource(); @@ -213,6 +258,7 @@ public abstract class StatementContextBase, E /** * @return reference of statement source */ + @Nonnull @Override public StatementSourceReference getStatementSourceReference() { return statementDeclSource; @@ -226,122 +272,134 @@ public abstract class StatementContextBase, E return identifier.getArgument(); } - /** - * @return collection of declared substatements - */ - @Override - public Collection> declaredSubstatements() { - return Collections.unmodifiableCollection(declared); + private static final Collection maybeWrap(final Collection input) { + if (input instanceof ImmutableCollection) { + return input; + } + + return Collections.unmodifiableCollection(input); } - /** - * @return collection of substatements - */ + @Nonnull @Override - public Collection> substatements() { - return Collections.unmodifiableCollection(substatements.values()); + public Collection> declaredSubstatements() { + return maybeWrap(declared); } - /** - * @return collection of effective substatements - */ + @Nonnull @Override public Collection> effectiveSubstatements() { - return Collections.unmodifiableCollection(effective); + return maybeWrap(effective); } - public void removeStatementsFromEffectiveSubstatements(Collection> substatements) { - effective.removeAll(substatements); + public void removeStatementsFromEffectiveSubstatements(final Collection> substatements) { + if (!effective.isEmpty()) { + effective.removeAll(substatements); + shrinkEffective(); + } + } + + private void shrinkEffective() { + if (effective.isEmpty()) { + effective = ImmutableList.of(); + } } - public void removeStatementFromEffectiveSubstatements(StatementDefinition refineSubstatementDef) { - Iterator> iterator = effective.iterator(); + public void removeStatementFromEffectiveSubstatements(final StatementDefinition refineSubstatementDef) { + if (effective.isEmpty()) { + return; + } + + final Iterator> iterator = effective.iterator(); while (iterator.hasNext()) { - StatementContextBase next = iterator.next(); + final StatementContextBase next = iterator.next(); if (next.getPublicDefinition().equals(refineSubstatementDef)) { iterator.remove(); } } + + shrinkEffective(); } /** * adds effective statement to collection of substatements * + * @param substatement substatement * @throws IllegalStateException * if added in declared phase * @throws NullPointerException * if statement parameter is null + */ + public void addEffectiveSubstatement(final StatementContextBase substatement) { + Preconditions.checkNotNull(substatement, "StatementContextBase effective substatement cannot be null at: %s", + getStatementSourceReference()); + beforeAddEffectiveStatement(1); + effective.add(substatement); + } + + /** + * adds effective statement to collection of substatements * - * @param substatement substatement + * @param substatements substatements + * @throws IllegalStateException + * if added in declared phase + * @throws NullPointerException + * if statement parameter is null */ - public void addEffectiveSubstatement(StatementContextBase substatement) { + public void addEffectiveSubstatements(final Collection> substatements) { + if (substatements.isEmpty()) { + return; + } + + substatements.forEach(Preconditions::checkNotNull); + beforeAddEffectiveStatement(substatements.size()); + effective.addAll(substatements); + } + private void beforeAddEffectiveStatement(final int toAdd) { final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase(); Preconditions.checkState(inProgressPhase == ModelProcessingPhase.FULL_DECLARATION || inProgressPhase == ModelProcessingPhase.EFFECTIVE_MODEL, - "Effective statement cannot be added in declared phase"); + "Effective statement cannot be added in declared phase at: %s", getStatementSourceReference()); - effective.add(Preconditions.checkNotNull(substatement, - "StatementContextBase effective substatement cannot be null")); + if (effective.isEmpty()) { + effective = new ArrayList<>(toAdd); + } } /** * adds declared statement to collection of substatements * + * @param substatement substatement * @throws IllegalStateException * if added in effective phase * @throws NullPointerException * if statement parameter is null - * - * @param substatement substatement */ - public void addDeclaredSubstatement(StatementContextBase substatement) { + public void addDeclaredSubstatement(final StatementContextBase substatement) { final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase(); Preconditions.checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL, - "Declared statement cannot be added in effective phase"); + "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference()); + if (declared.isEmpty()) { + declared = new ArrayList<>(1); + } declared.add(Preconditions.checkNotNull(substatement, - "StatementContextBase declared substatement cannot be null")); + "StatementContextBase declared substatement cannot be null at: %s", getStatementSourceReference())); } /** - * builds new substatement from statement definition context and statement source reference + * builds a new substatement from statement definition context and statement source reference * * @param def definition context * @param ref source reference * * @return instance of ContextBuilder */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public ContextBuilder substatementBuilder(StatementDefinitionContext def, - StatementSourceReference ref) { - return new ContextBuilder(def, ref) { - - @Override - public StatementContextBase build() throws SourceException { - StatementContextBase potential = null; - - if (getDefinition().getPublicView() != Rfc6020Mapping.AUGMENT) { - potential = substatements.get(createIdentifier()); - } - if (potential == null) { - potential = new SubstatementContext(StatementContextBase.this, this); - substatements.put(createIdentifier(), potential); - getDefinition().onStatementAdded(potential); - } - potential.resetLists(); - switch (this.getStamementSource().getStatementSource()) { - case DECLARATION: - addDeclaredSubstatement(potential); - break; - case CONTEXT: - addEffectiveSubstatement(potential); - break; - } - return potential; - } - }; + ContextBuilder substatementBuilder(final int childId, final StatementDefinitionContext def, + final StatementSourceReference ref) { + return new SubContextBuilder(childId, def, ref); } /** @@ -386,9 +444,9 @@ public abstract class StatementContextBase, E final SourceSpecificContext sourceContext = getRoot().getSourceContext(); Preconditions.checkState(sourceContext.getInProgressPhase() != ModelProcessingPhase.EFFECTIVE_MODEL, - "Declared statements list cannot be cleared in effective phase"); + "Declared statements list cannot be cleared in effective phase at: %s", getStatementSourceReference()); - declared.clear(); + declared = ImmutableList.of(); } /** @@ -400,21 +458,33 @@ public abstract class StatementContextBase, E * @throws SourceException * when an error occured in source parsing */ - boolean tryToCompletePhase(ModelProcessingPhase phase) throws SourceException { - Iterator openMutations = phaseMutation.get(phase).iterator(); + boolean tryToCompletePhase(final ModelProcessingPhase phase) { + boolean finished = true; - while (openMutations.hasNext()) { - ContextMutation current = openMutations.next(); - if (current.isFinished()) { - openMutations.remove(); - } else { - finished = false; + final Collection openMutations = phaseMutation.get(phase); + if (!openMutations.isEmpty()) { + final Iterator it = openMutations.iterator(); + while (it.hasNext()) { + final ContextMutation current = it.next(); + if (current.isFinished()) { + it.remove(); + } else { + finished = false; + } + } + + if (openMutations.isEmpty()) { + phaseMutation.removeAll(phase); + if (phaseMutation.isEmpty()) { + phaseMutation = ImmutableMultimap.of(); + } } } - for (StatementContextBase child : declared) { + + for (final StatementContextBase child : declared) { finished &= child.tryToCompletePhase(phase); } - for (StatementContextBase child : effective) { + for (final StatementContextBase child : effective) { finished &= child.tryToCompletePhase(phase); } @@ -433,15 +503,28 @@ public abstract class StatementContextBase, E * @throws SourceException * when an error occured in source parsing */ - private void onPhaseCompleted(ModelProcessingPhase phase) throws SourceException { + private void onPhaseCompleted(final ModelProcessingPhase phase) { completedPhase = phase; - Iterator listener = phaseListeners.get(completedPhase).iterator(); + + final Collection listeners = phaseListeners.get(phase); + if (listeners.isEmpty()) { + return; + } + + final Iterator listener = listeners.iterator(); while (listener.hasNext()) { - OnPhaseFinished next = listener.next(); + final OnPhaseFinished next = listener.next(); if (next.phaseFinished(this, phase)) { listener.remove(); } } + + if (listeners.isEmpty()) { + phaseListeners.removeAll(phase); + if (phaseListeners.isEmpty()) { + phaseListeners = ImmutableMultimap.of(); + } + } } /** @@ -450,7 +533,7 @@ public abstract class StatementContextBase, E * @param ref * @throws SourceException */ - void endDeclared(StatementSourceReference ref, ModelProcessingPhase phase) throws SourceException { + void endDeclared(final StatementSourceReference ref, final ModelProcessingPhase phase) { definition().onDeclarationFinished(this, phase); } @@ -462,7 +545,7 @@ public abstract class StatementContextBase, E } @Override - protected void checkLocalNamespaceAllowed(Class> type) { + protected void checkLocalNamespaceAllowed(final Class> type) { definition().checkNamespaceAllowed(type); } @@ -472,26 +555,26 @@ public abstract class StatementContextBase, E * @throws SourceException instance of SourceException */ @Override - protected > void onNamespaceElementAdded(Class type, K key, V value) { + protected > void onNamespaceElementAdded(final Class type, final K key, final V value) { // definition().onNamespaceElementAdded(this, type, key, value); } - > void onNamespaceItemAddedAction(final Class type, K key, + > void onNamespaceItemAddedAction(final Class type, final K key, final OnNamespaceItemAdded listener) throws SourceException { - Object potential = getFromNamespace(type, key); + final Object potential = getFromNamespace(type, key); if (potential != null) { listener.namespaceItemAdded(this, type, key, potential); return; } - NamespaceBehaviour behaviour = getBehaviourRegistry().getNamespaceBehaviour(type); + final NamespaceBehaviour behaviour = getBehaviourRegistry().getNamespaceBehaviour(type); if (behaviour instanceof NamespaceBehaviourWithListeners) { - NamespaceBehaviourWithListeners casted = (NamespaceBehaviourWithListeners) behaviour; - casted.addValueListener(key, new ValueAddedListener(this) { + final NamespaceBehaviourWithListeners casted = (NamespaceBehaviourWithListeners) behaviour; + casted.addValueListener(new ValueAddedListener(this, key) { @Override - void onValueAdded(Object key, Object value) { + void onValueAdded(final Object key, final Object value) { try { listener.namespaceItemAdded(StatementContextBase.this, type, key, value); - } catch (SourceException e) { + } catch (final SourceException e) { throw Throwables.propagate(e); } } @@ -502,6 +585,7 @@ public abstract class StatementContextBase, E /** * @see StatementSupport#getPublicView() */ + @Nonnull @Override public StatementDefinition getPublicDefinition() { return definition().getPublicView(); @@ -511,19 +595,25 @@ public abstract class StatementContextBase, E * @return new {@link ModelActionBuilder} for the phase */ @Override - public ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) { + public ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) { return getRoot().getSourceContext().newInferenceAction(phase); } + private static Multimap newMultimap() { + return Multimaps.newListMultimap(new EnumMap<>(ModelProcessingPhase.class), () -> new ArrayList<>(1)); + } + /** * adds {@link OnPhaseFinished} listener for a {@link ModelProcessingPhase} end * * @throws SourceException */ - void addPhaseCompletedListener(ModelProcessingPhase phase, OnPhaseFinished listener) throws SourceException { + void addPhaseCompletedListener(final ModelProcessingPhase phase, final OnPhaseFinished listener) { - Preconditions.checkNotNull(phase, "Statement context processing phase cannot be null"); - Preconditions.checkNotNull(listener, "Statement context phase listener cannot be null"); + Preconditions.checkNotNull(phase, "Statement context processing phase cannot be null at: %s", + getStatementSourceReference()); + Preconditions.checkNotNull(listener, "Statement context phase listener cannot be null at: %s", + getStatementSourceReference()); ModelProcessingPhase finishedPhase = completedPhase; while (finishedPhase != null) { @@ -533,6 +623,10 @@ public abstract class StatementContextBase, E } finishedPhase = finishedPhase.getPreviousPhase(); } + if (phaseListeners.isEmpty()) { + phaseListeners = newMultimap(); + } + phaseListeners.put(phase, listener); } @@ -542,14 +636,19 @@ public abstract class StatementContextBase, E * @throws IllegalStateException * when the mutation was registered after phase was completed */ - void addMutation(ModelProcessingPhase phase, ContextMutation mutation) { + void addMutation(final ModelProcessingPhase phase, final ContextMutation mutation) { ModelProcessingPhase finishedPhase = completedPhase; while (finishedPhase != null) { if (phase.equals(finishedPhase)) { - throw new IllegalStateException("Mutation registered after phase was completed."); + throw new IllegalStateException("Mutation registered after phase was completed at: " + + getStatementSourceReference()); } finishedPhase = finishedPhase.getPreviousPhase(); } + + if (phaseMutation.isEmpty()) { + phaseMutation = newMultimap(); + } phaseMutation.put(phase, mutation); } @@ -564,8 +663,17 @@ public abstract class StatementContextBase, E * to be added to namespace map */ @Override - public > void addContext(Class namespace, KT key, - StmtContext stmt) { - addContextToNamespace(namespace, (K) key, stmt); + public > void addContext(final Class namespace, final KT key, + final StmtContext stmt) { + addContextToNamespace(namespace, key, stmt); + } + + @Override + public final String toString() { + return addToStringAttributes(MoreObjects.toStringHelper(this).omitNullValues()).toString(); + } + + protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { + return toStringHelper.add("definition", definition).add("id", identifier); } }