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=59a22343e13743e8d9531faf92dea4059bc94adb;hb=32438a2739795793f393c872a76a43444db7b46a;hp=43692ff0dae32f1bee0b7469e0c2ae761d854cae;hpb=ed4fee64bc9bdb4005d11aa35355e9367065998f;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 43692ff0da..59a22343e1 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 @@ -17,9 +17,11 @@ import java.util.Collections; import java.util.EventListener; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; 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; @@ -30,282 +32,459 @@ 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.StorageNodeType; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace; +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.SourceException; import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.ValueAddedListener; -public abstract class StatementContextBase, E extends EffectiveStatement> extends - NamespaceStorageSupport implements StmtContext.Mutable, Identifiable { +public abstract class StatementContextBase, E extends EffectiveStatement> + extends NamespaceStorageSupport implements StmtContext.Mutable, Identifiable { - interface OnNamespaceItemAdded extends EventListener{ + /** + * 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; + void namespaceItemAdded(StatementContextBase context, Class namespace, Object key, Object value) + throws SourceException; } - interface OnPhaseFinished extends EventListener{ + /** + * event listener when a parsing {@link ModelProcessingPhase} is completed + */ + interface OnPhaseFinished extends EventListener { - void phaseFinished(StatementContextBase context, ModelProcessingPhase phase) throws SourceException; + boolean phaseFinished(StatementContextBase context, ModelProcessingPhase phase) throws SourceException; } + /** + * interface for all mutations within an {@link ModelActionBuilder.InferenceAction} + */ interface ContextMutation { boolean isFinished(); } - abstract static class ContextBuilder, E extends EffectiveStatement> { + private final StatementDefinitionContext definition; + private final StatementIdentifier identifier; + private final StatementSourceReference statementDeclSource; + private int order = 0; - private final StatementDefinitionContext definition; - private final StatementSourceReference stmtRef; - private String rawArg; - private StatementSourceReference argRef; + private final Map> substatements = new LinkedHashMap<>(); - public ContextBuilder(StatementDefinitionContext def, StatementSourceReference sourceRef) { - this.definition = def; - this.stmtRef = sourceRef; - } + private final Collection> declared = new ArrayList<>(); + private final Collection> effective = new ArrayList<>(); + private final Collection> effectOfStatement = new ArrayList<>(); - public void setArgument(@Nonnull String argument, @Nonnull StatementSourceReference argumentSource) { - Preconditions.checkArgument(definition.hasArgument(), "Statement does not take argument."); - this.rawArg = Preconditions.checkNotNull(argument); - this.argRef = Preconditions.checkNotNull(argumentSource); - } + @Override + public Collection> getEffectOfStatement() { + return effectOfStatement; + } - public String getRawArgument() { - return rawArg; - } + @Override + public void addAsEffectOfStatement(final StatementContextBase ctx) { + effectOfStatement.add(ctx); + } - public StatementSourceReference getStamementSource() { - return stmtRef; - } + private ModelProcessingPhase completedPhase; - public StatementSourceReference getArgumentSource() { - return argRef; - } + private final Multimap phaseListeners = HashMultimap.create(); + private final Multimap phaseMutation = HashMultimap.create(); - public StatementDefinitionContext getDefinition() { - return definition; - } + private D declaredInstance; + private E effectiveInstance; - public StatementIdentifier getIdentifier() { - return new StatementIdentifier(definition.getStatementName(), rawArg); - } + private StatementContextBase originalCtx; + private final List copyHistory = new ArrayList<>(1); - public abstract StatementContextBase build() throws SourceException; + private boolean isSupportedToBuildEffective = true; + @Override + public boolean isSupportedToBuildEffective() { + return isSupportedToBuildEffective; } - private final StatementDefinitionContext definition; - private final StatementIdentifier identifier; - private final StatementSourceReference statementDeclSource; + @Override + public void setIsSupportedToBuildEffective(final boolean isSupportedToBuildEffective) { + this.isSupportedToBuildEffective = isSupportedToBuildEffective; + } - private Map > substatements = new LinkedHashMap<>(); + @Override + public List getCopyHistory() { + return copyHistory; + } - private Collection> declared = new ArrayList<>(); - private Collection> effective = new ArrayList<>(); + @Override + public void addToCopyHistory(final TypeOfCopy typeOfCopy) { + this.copyHistory.add(typeOfCopy); + } - private ModelProcessingPhase completedPhase; + @Override + public void addAllToCopyHistory(final List typeOfCopyList) { + this.copyHistory.addAll(typeOfCopyList); + } - private Multimap phaseListeners = HashMultimap.create(); - private Multimap phaseMutation = HashMultimap.create(); + @Override + public StatementContextBase getOriginalCtx() { + return originalCtx; + } - private D declaredInstance; - private E effectiveInstance; + @Override + public void setOriginalCtx(final StatementContextBase originalCtx) { + this.originalCtx = originalCtx; + } + + @Override + public void setOrder(final int order) { + this.order = order; + } + @Override + public int getOrder() { + return order; + } - StatementContextBase(@Nonnull ContextBuilder builder) throws SourceException { + @Override + public ModelProcessingPhase getCompletedPhase() { + return completedPhase; + } + + @Override + public void setCompletedPhase(final ModelProcessingPhase completedPhase) { + this.completedPhase = completedPhase; + } + + StatementContextBase(@Nonnull final ContextBuilder builder) throws SourceException { this.definition = builder.getDefinition(); - this.identifier = builder.getIdentifier(); + this.identifier = builder.createIdentifier(); this.statementDeclSource = builder.getStamementSource(); this.completedPhase = null; + this.copyHistory.add(TypeOfCopy.ORIGINAL); } - StatementContextBase(StatementContextBase original) { - this.definition = original.definition; - this.identifier = original.identifier; - this.statementDeclSource = original.statementDeclSource; + StatementContextBase(final 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; + this.copyHistory.add(TypeOfCopy.ORIGINAL); } + /** + * @return context of parent of statement + */ @Override public abstract StatementContextBase getParentContext(); + /** + * @return root context of statement + */ @Override public abstract RootStatementContext getRoot(); - + /** + * @return statement identifier + */ @Override public StatementIdentifier getIdentifier() { return identifier; } + /** + * @return origin of statement + */ @Override public StatementSource getStatementSource() { return statementDeclSource.getStatementSource(); } + /** + * @return reference of statement source + */ @Override public StatementSourceReference getStatementSourceReference() { return statementDeclSource; } + /** + * @return raw statement argument string + */ @Override public String rawStatementArgument() { return identifier.getArgument(); } + /** + * @return collection of declared substatements + */ @Override public Collection> declaredSubstatements() { return Collections.unmodifiableCollection(declared); } + /** + * @return collection of substatements + */ + @Override + public Collection> substatements() { + return Collections.unmodifiableCollection(substatements.values()); + } + + /** + * @return collection of effective substatements + */ @Override public Collection> effectiveSubstatements() { return Collections.unmodifiableCollection(effective); } - public void addEffectiveSubstatement(StatementContextBase substatement){ - effective.add(substatement); + public void removeStatementsFromEffectiveSubstatements(final Collection> substatements) { + effective.removeAll(substatements); } - public void addDeclaredSubstatement(StatementContextBase substatement){ - declared.add(substatement); + public void removeStatementFromEffectiveSubstatements(final StatementDefinition refineSubstatementDef) { + Iterator> iterator = effective.iterator(); + while (iterator.hasNext()) { + StatementContextBase next = iterator.next(); + if (next.getPublicDefinition().equals(refineSubstatementDef)) { + iterator.remove(); + } + } + } + + /** + * adds effective statement to collection of substatements + * + * @throws IllegalStateException + * if added in declared phase + * @throws NullPointerException + * if statement parameter is null + * + * @param substatement substatement + */ + public void addEffectiveSubstatement(final StatementContextBase substatement) { + + 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.add(Preconditions.checkNotNull(substatement, + "StatementContextBase effective substatement cannot be null")); } + /** + * adds declared statement to collection of substatements + * + * @throws IllegalStateException + * if added in effective phase + * @throws NullPointerException + * if statement parameter is null + * + * @param substatement 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.add(Preconditions.checkNotNull(substatement, + "StatementContextBase declared substatement cannot be null")); + } + + /** + * builds 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) { + public ContextBuilder substatementBuilder(final StatementDefinitionContext def, + final StatementSourceReference ref) { return new ContextBuilder(def, ref) { @Override public StatementContextBase build() throws SourceException { - StatementContextBase potential = substatements.get(getIdentifier()); - if(potential == null) { + StatementContextBase potential = null; + + StatementDefinition stmtDef = getDefinition().getPublicView(); + if (stmtDef != Rfc6020Mapping.AUGMENT && stmtDef != Rfc6020Mapping.DEVIATION) { + potential = substatements.get(createIdentifier()); + } + if (potential == null) { potential = new SubstatementContext(StatementContextBase.this, this); - substatements.put(getIdentifier(), potential); + substatements.put(createIdentifier(), potential); + getDefinition().onStatementAdded(potential); } potential.resetLists(); switch (this.getStamementSource().getStatementSource()) { - case DECLARATION: - declared.add(potential); - break; - case CONTEXT: - effective.add(potential); - break; + case DECLARATION: + addDeclaredSubstatement(potential); + break; + case CONTEXT: + addEffectiveSubstatement(potential); + break; } return potential; } }; } - - + /** + * @return local namespace behaviour type {@link NamespaceBehaviour} + */ @Override public StorageNodeType getStorageNodeType() { return StorageNodeType.STATEMENT_LOCAL; } + /** + * builds {@link DeclaredStatement} for statement context + */ @Override public D buildDeclared() { - Preconditions.checkArgument(completedPhase == ModelProcessingPhase.FULL_DECLARATION || completedPhase == ModelProcessingPhase.EFFECTIVE_MODEL); + Preconditions.checkArgument(completedPhase == ModelProcessingPhase.FULL_DECLARATION + || completedPhase == ModelProcessingPhase.EFFECTIVE_MODEL); if (declaredInstance == null) { declaredInstance = definition().getFactory().createDeclared(this); } return declaredInstance; } + /** + * builds {@link EffectiveStatement} for statement context + */ @Override public E buildEffective() { - Preconditions.checkArgument(completedPhase == ModelProcessingPhase.EFFECTIVE_MODEL); if (effectiveInstance == null) { effectiveInstance = definition().getFactory().createEffective(this); } return effectiveInstance; } - + /** + * clears collection of declared substatements + * + * @throws IllegalStateException + * if invoked in effective build phase + */ void resetLists() { + + final SourceSpecificContext sourceContext = getRoot().getSourceContext(); + Preconditions.checkState(sourceContext.getInProgressPhase() != ModelProcessingPhase.EFFECTIVE_MODEL, + "Declared statements list cannot be cleared in effective phase"); + declared.clear(); } - boolean tryToCompletePhase(ModelProcessingPhase phase) throws SourceException { - if(phase.equals(completedPhase)) { - return true; - } + /** + * tries to execute current {@link ModelProcessingPhase} of source parsing + * + * @param phase + * to be executed (completed) + * @return if phase was successfully completed + * @throws SourceException + * when an error occured in source parsing + */ + boolean tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException { Iterator openMutations = phaseMutation.get(phase).iterator(); boolean finished = true; - while(openMutations.hasNext()) { + while (openMutations.hasNext()) { ContextMutation current = openMutations.next(); - if(current.isFinished()) { + if (current.isFinished()) { openMutations.remove(); } else { finished = false; } } - for(StatementContextBase child: declared) { + for (StatementContextBase child : declared) { finished &= child.tryToCompletePhase(phase); } - for(StatementContextBase child: effective) { + for (StatementContextBase child : effective) { finished &= child.tryToCompletePhase(phase); } - if(finished) { + + if (finished) { onPhaseCompleted(phase); return true; } return false; } - - private void onPhaseCompleted(ModelProcessingPhase phase) throws SourceException { + /** + * occurs on end of {@link ModelProcessingPhase} of source parsing + * + * @param phase + * that was to be completed (finished) + * @throws SourceException + * when an error occured in source parsing + */ + private void onPhaseCompleted(final ModelProcessingPhase phase) throws SourceException { completedPhase = phase; Iterator listener = phaseListeners.get(completedPhase).iterator(); - while(listener.hasNext()) { - listener.next().phaseFinished(this, phase); - listener.remove(); + while (listener.hasNext()) { + OnPhaseFinished next = listener.next(); + if (next.phaseFinished(this, phase)) { + listener.remove(); + } } } /** - * * Ends declared section of current node. * * @param ref * @throws SourceException - * */ - void endDeclared(StatementSourceReference ref,ModelProcessingPhase phase) throws SourceException { - definition().onDeclarationFinished(this,phase); + void endDeclared(final StatementSourceReference ref, final ModelProcessingPhase phase) throws SourceException { + definition().onDeclarationFinished(this, phase); } + /** + * @return statement definition + */ protected final StatementDefinitionContext definition() { return definition; } @Override - protected void checkLocalNamespaceAllowed(Class> type) { + protected void checkLocalNamespaceAllowed(final Class> type) { definition().checkNamespaceAllowed(type); } + /** + * occurs when an item is added to model namespace + * + * @throws SourceException instance of SourceException + */ @Override - protected > void onNamespaceElementAdded(Class type, K key, V value) { - //definition().onNamespaceElementAdded(this, type, key, 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, final OnNamespaceItemAdded listener) throws SourceException { + > void onNamespaceItemAddedAction(final Class type, final K key, + final OnNamespaceItemAdded listener) throws SourceException { Object potential = getFromNamespace(type, key); - if(potential != null) { + if (potential != null) { listener.namespaceItemAdded(this, type, key, potential); return; } - NamespaceBehaviour behaviour = getBehaviourRegistry().getNamespaceBehaviour(type); - if(behaviour instanceof NamespaceBehaviourWithListeners) { - NamespaceBehaviourWithListeners casted = (NamespaceBehaviourWithListeners) behaviour; - casted.addValueListener(key, new ValueAddedListener(this) { + NamespaceBehaviour behaviour = getBehaviourRegistry().getNamespaceBehaviour(type); + if (behaviour instanceof NamespaceBehaviourWithListeners) { + 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) { @@ -316,20 +495,35 @@ public abstract class StatementContextBase, E } } + /** + * @see StatementSupport#getPublicView() + */ @Override public StatementDefinition getPublicDefinition() { return definition().getPublicView(); } + /** + * @return new {@link ModelActionBuilder} for the phase + */ @Override - public ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) { + public ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) { return getRoot().getSourceContext().newInferenceAction(phase); } - void addPhaseCompletedListener(ModelProcessingPhase phase, OnPhaseFinished listener) throws SourceException { + /** + * adds {@link OnPhaseFinished} listener for a {@link ModelProcessingPhase} end + * + * @throws SourceException + */ + void addPhaseCompletedListener(final ModelProcessingPhase phase, final OnPhaseFinished listener) throws SourceException { + + Preconditions.checkNotNull(phase, "Statement context processing phase cannot be null"); + Preconditions.checkNotNull(listener, "Statement context phase listener cannot be null"); + ModelProcessingPhase finishedPhase = completedPhase; while (finishedPhase != null) { - if(phase.equals(finishedPhase)) { + if (phase.equals(finishedPhase)) { listener.phaseFinished(this, finishedPhase); return; } @@ -338,10 +532,16 @@ public abstract class StatementContextBase, E phaseListeners.put(phase, listener); } - void addMutation(ModelProcessingPhase phase, ContextMutation mutation) { + /** + * adds {@link ContextMutation} to {@link ModelProcessingPhase} + * + * @throws IllegalStateException + * when the mutation was registered after phase was completed + */ + void addMutation(final ModelProcessingPhase phase, final ContextMutation mutation) { ModelProcessingPhase finishedPhase = completedPhase; while (finishedPhase != null) { - if(phase.equals(finishedPhase)) { + if (phase.equals(finishedPhase)) { throw new IllegalStateException("Mutation registered after phase was completed."); } finishedPhase = finishedPhase.getPreviousPhase(); @@ -349,9 +549,19 @@ public abstract class StatementContextBase, E phaseMutation.put(phase, mutation); } + /** + * adds statement to namespace map with the key + * + * @param namespace + * {@link StatementNamespace} child that determines namespace to be added to + * @param key + * of type according to namespace class specification + * @param stmt + * 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, (K) key, stmt); } }