*/
package org.opendaylight.yangtools.yang.parser.stmt.reactor;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
-import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNull;
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.common.YangVersion;
-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.StatementSource;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
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.MutableStatement;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
-
- public enum PhaseCompletionProgress {
+final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
+ enum PhaseCompletionProgress {
NO_PROGRESS,
PROGRESS,
FINISHED
private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
private final QNameToStatementDefinitionMap qnameToStmtDefMap = new QNameToStatementDefinitionMap();
private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap();
- private final BuildGlobalContext currentContext;
- private final StatementStreamSource source;
+ private final @NonNull BuildGlobalContext globalContext;
+
+ // Freed as soon as we complete ModelProcessingPhase.EFFECTIVE_MODEL
+ private StatementStreamSource source;
/*
* "imported" namespaces in this source -- this points to RootStatementContexts of
private ModelProcessingPhase inProgressPhase;
private RootStatementContext<?, ?, ?> root;
- SourceSpecificContext(final BuildGlobalContext currentContext, final StatementStreamSource source) {
- this.currentContext = Preconditions.checkNotNull(currentContext);
- this.source = Preconditions.checkNotNull(source);
+ SourceSpecificContext(final BuildGlobalContext globalContext, final StatementStreamSource source) {
+ this.globalContext = requireNonNull(globalContext);
+ this.source = requireNonNull(source);
}
- boolean isEnabledSemanticVersioning() {
- return currentContext.isEnabledSemanticVersioning();
+ @NonNull BuildGlobalContext globalContext() {
+ return globalContext;
}
ModelProcessingPhase getInProgressPhase() {
return inProgressPhase;
}
- Optional<StatementContextBase<?, ?, ?>> lookupDeclaredChild(final StatementContextBase<?, ?, ?> current,
- final int childId) {
- if (current == null) {
- return Optional.empty();
- }
-
- // Fast path: we are entering a statement which was emitted in previous phase
- StatementContextBase<?, ?, ?> existing = current.lookupSubstatement(childId);
- while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) {
- existing = existing.lookupSubstatement(childId);
- }
-
- return Optional.ofNullable(existing);
- }
-
- StatementContextBase<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final int childId,
- final QName name, final String argument, final StatementSourceReference ref) {
- StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(getRootVersion(), name);
+ AbstractResumedStatement<?, ?, ?> createDeclaredChild(final AbstractResumedStatement<?, ?, ?> current,
+ final int childId, final QName name, final String argument, final StatementSourceReference ref) {
+ StatementDefinitionContext<?, ?, ?> def = globalContext.getStatementDefinition(getRootVersion(), name);
if (def == null) {
- def = currentContext.getModelDefinedStatementDefinition(name);
+ def = globalContext.getModelDefinedStatementDefinition(name);
if (def == null) {
final StatementSupport<?, ?, ?> extension = qnameToStmtDefMap.get(name);
if (extension != null) {
def = new StatementDefinitionContext<>(extension);
- currentContext.putModelDefinedStatementDefinition(name, def);
+ globalContext.putModelDefinedStatementDefinition(name, def);
}
}
} else if (current != null && StmtContextUtils.isUnrecognizedStatement(current)) {
* This code wraps statements encountered inside an extension so
* they do not get confused with regular statements.
*/
- def = Preconditions.checkNotNull(current.definition().getAsUnknownStatementDefinition(def),
+ def = checkNotNull(current.definition().getAsUnknownStatementDefinition(def),
"Unable to create unknown statement definition of yang statement %s in unknown statement %s", def,
current);
}
- InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name);
- if (def.hasArgument()) {
+ if (InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name)
+ .getArgumentDefinition().isPresent()) {
SourceException.throwIfNull(argument, ref, "Statement %s requires an argument", name);
} else {
SourceException.throwIf(argument != null, ref, "Statement %s does not take argument", name);
*/
if (root == null) {
root = new RootStatementContext<>(this, def, ref, argument);
- } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.getRootVersion())
+ } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.yangVersion())
&& inProgressPhase == ModelProcessingPhase.SOURCE_LINKAGE) {
- root = new RootStatementContext<>(this, def, ref, argument, root.getRootVersion(),
+ root = new RootStatementContext<>(this, def, ref, argument, root.yangVersion(),
root.getRootIdentifier());
} else {
final QName rootStatement = root.definition().getStatementName();
- final String rootArgument = root.rawStatementArgument();
+ final String rootArgument = root.rawArgument();
- Preconditions.checkState(Objects.equals(def.getStatementName(), rootStatement)
- && Objects.equals(argument, rootArgument), "Root statement was already defined as '%s %s'.",
- rootStatement, rootArgument);
+ checkState(Objects.equals(def.getStatementName(), rootStatement) && Objects.equals(argument, rootArgument),
+ "Root statement was already defined as '%s %s'.", rootStatement, rootArgument);
}
return root;
}
* @return version of root statement context
*/
YangVersion getRootVersion() {
- return root != null ? root.getRootVersion() : RootStatementContext.DEFAULT_VERSION;
- }
-
- DeclaredStatement<?> buildDeclared() {
- return root.buildDeclared();
- }
-
- EffectiveStatement<?, ?> buildEffective() {
- return root.buildEffective();
+ return root != null ? root.yangVersion() : RootStatementContext.DEFAULT_VERSION;
}
void startPhase(final ModelProcessingPhase phase) {
- @Nullable final ModelProcessingPhase previousPhase = phase.getPreviousPhase();
- Verify.verify(Objects.equals(previousPhase, finishedPhase),
+ final ModelProcessingPhase previousPhase = phase.getPreviousPhase();
+ verify(Objects.equals(previousPhase, finishedPhase),
"Phase sequencing violation: previous phase should be %s, source %s has %s", previousPhase, source,
finishedPhase);
final Collection<ModifierImpl> previousModifiers = modifiers.get(previousPhase);
- Preconditions.checkState(previousModifiers.isEmpty(),
- "Previous phase %s has unresolved modifiers %s in source %s", previousPhase, previousModifiers, source);
+ 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);
importedNamespaces = new ArrayList<>(1);
}
- Verify.verify(value instanceof RootStatementContext);
+ verify(value instanceof RootStatementContext);
importedNamespaces.add((RootStatementContext<?, ?, ?>) value);
}
}
return null;
}
- @Nullable
@Override
public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
final Map<K, V> potentialLocal = getRoot().getAllFromLocalStorage(type);
@Override
public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
final Class<N> type) {
- return currentContext.getNamespaceBehaviour(type);
+ return globalContext.getNamespaceBehaviour(type);
}
@Override
- public NamespaceStorageNode getParentNamespaceStorage() {
- return currentContext;
+ public BuildGlobalContext getParentNamespaceStorage() {
+ return globalContext;
}
- PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException {
+ PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) {
final Collection<ModifierImpl> currentPhaseModifiers = modifiers.get(phase);
boolean hasProgressed = tryToProgress(currentPhaseModifiers);
-
- Preconditions.checkNotNull(this.root, "Malformed source. Valid root element is missing.");
- final boolean phaseCompleted = root.tryToCompletePhase(phase);
+ final boolean phaseCompleted = requireNonNull(root, "Malformed source. Valid root element is missing.")
+ .tryToCompletePhase(phase);
hasProgressed |= tryToProgress(currentPhaseModifiers);
if (phaseCompleted && currentPhaseModifiers.isEmpty()) {
finishedPhase = phase;
LOG.debug("Source {} finished phase {}", source, phase);
+ if (phase == ModelProcessingPhase.EFFECTIVE_MODEL) {
+ // We have the effective model acquired, which is the final phase of source interaction.
+ LOG.trace("Releasing source {}", source);
+ source = null;
+ }
return PhaseCompletionProgress.FINISHED;
-
}
return hasProgressed ? PhaseCompletionProgress.PROGRESS : PhaseCompletionProgress.NO_PROGRESS;
return hasProgressed;
}
- ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) {
+ @NonNull ModelActionBuilder newInferenceAction(final @NonNull ModelProcessingPhase phase) {
final ModifierImpl action = new ModifierImpl();
modifiers.put(phase, action);
return action;
}
final String message = String.format("Yang model processing phase %s failed", identifier);
- final InferenceException e = new InferenceException(message, root.getStatementSourceReference(),
- exceptions.get(0));
+ final InferenceException e = new InferenceException(message, root.sourceReference(), exceptions.get(0));
exceptions.listIterator(1).forEachRemaining(e::addSuppressed);
return Optional.of(e);
}
- void loadStatements() throws SourceException {
+ void loadStatements() {
LOG.trace("Source {} loading statements for phase {}", source, inProgressPhase);
switch (inProgressPhase) {
}
private PrefixToModule preLinkagePrefixes() {
- final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap(true);
+ final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap();
final Map<String, URI> prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class);
if (prefixToNamespaceMap == null) {
//:FIXME if it is a submodule without any import, the map is null. Handle also submodules and includes...
private QNameToStatementDefinition stmtDef() {
// regular YANG statements and extension supports added
- final StatementSupportBundle supportsForPhase = currentContext.getSupportsForPhase(inProgressPhase);
+ final StatementSupportBundle supportsForPhase = globalContext.getSupportsForPhase(inProgressPhase);
qnameToStmtDefMap.putAll(supportsForPhase.getCommonDefinitions());
qnameToStmtDefMap.putAll(supportsForPhase.getDefinitionsSpecificForVersion(getRootVersion()));
}
// We need to any and all extension statements which have been declared in the context
- final Map<QName, StatementSupport<?, ?, ?>> extensions = currentContext.getAllFromNamespace(
+ final Map<QName, StatementSupport<?, ?, ?>> extensions = globalContext.getNamespace(
StatementDefinitionNamespace.class);
if (extensions != null) {
extensions.forEach((qname, support) -> {
return qnameToStmtDefMap;
}
- public Set<YangVersion> getSupportedVersions() {
- return currentContext.getSupportedVersions();
- }
-
- void addMutableStmtToSeal(final MutableStatement mutableStatement) {
- currentContext.addMutableStmtToSeal(mutableStatement);
- }
-
Collection<SourceIdentifier> getRequiredSources() {
return root.getRequiredSources();
}