*/
package org.opendaylight.yangtools.yang.parser.stmt.reactor;
-import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
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.CopyType;
+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.NamespaceStorageNode;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.source.IncludedModuleContext;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
private final A argument;
private YangVersion version;
+ private Collection<ModuleIdentifier> requiredModules = ImmutableSet.of();
+ private ModuleIdentifier identifier;
/**
* References to RootStatementContext of submodules which are included in this source.
final StatementSourceReference ref, final String rawArgument) {
super(def, ref, rawArgument);
this.sourceContext = Preconditions.checkNotNull(sourceContext);
- this.argument = def.parseArgumentValue(this, rawArgument);
+ this.argument = def.parseArgumentValue(this, rawStatementArgument());
}
RootStatementContext(final SourceSpecificContext sourceContext, final StatementDefinitionContext<A, D, E> def,
- final StatementSourceReference ref, final String rawArgument, final YangVersion version) {
+ final StatementSourceReference ref, final String rawArgument, final YangVersion version,
+ final ModuleIdentifier identifier) {
this(sourceContext, def, ref, rawArgument);
this.setRootVersion(version);
- }
-
- RootStatementContext(final RootStatementContext<A, D, E> original, final QNameModule newQNameModule,
- final CopyType typeOfCopy) {
- super(original);
-
- sourceContext = Preconditions.checkNotNull(original.sourceContext);
- this.argument = original.argument;
-
- final Collection<StatementContextBase<?, ?, ?>> declared = original.declaredSubstatements();
- final Collection<StatementContextBase<?, ?, ?>> effective = original.effectiveSubstatements();
- final Collection<StatementContextBase<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
-
- for (final StatementContextBase<?, ?, ?> stmtContext : declared) {
- if (StmtContextUtils.areFeaturesSupported(stmtContext)) {
- buffer.add(stmtContext.createCopy(newQNameModule, this, typeOfCopy));
- }
- }
- for (final StmtContext<?, ?, ?> stmtContext : effective) {
- buffer.add(stmtContext.createCopy(newQNameModule, this, typeOfCopy));
- }
-
- addEffectiveSubstatements(buffer);
+ this.setRootIdentifier(identifier);
}
/**
return argument;
}
- /**
- * @return copy of this considering {@link CopyType} (augment, uses)
- *
- * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException instance of SourceException
- */
@Override
- public StatementContextBase<?, ?, ?> createCopy(final StatementContextBase<?, ?, ?> newParent,
+ public StatementContextBase<A, D, E> createCopy(final StatementContextBase<?, ?, ?> newParent,
final CopyType typeOfCopy) {
- return createCopy(null, newParent, typeOfCopy);
+ throw new UnsupportedOperationException("Root context cannot be copied");
}
- /**
- * @return copy of this considering {@link CopyType} (augment, uses)
- *
- * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException instance of SourceException
- */
@Override
public StatementContextBase<A, D, E> createCopy(final QNameModule newQNameModule,
final StatementContextBase<?, ?, ?> newParent, final CopyType typeOfCopy) {
- final RootStatementContext<A, D, E> copy = new RootStatementContext<>(this, newQNameModule, typeOfCopy);
-
- copy.appendCopyHistory(typeOfCopy, this.getCopyHistory());
-
- if (this.getOriginalCtx() != null) {
- copy.setOriginalCtx(this.getOriginalCtx());
- } else {
- copy.setOriginalCtx(this);
- }
- definition().onStatementAdded(copy);
- return copy;
+ throw new UnsupportedOperationException("Root context cannot be copied");
}
@Nonnull
return Optional.of(SchemaPath.ROOT);
}
- /**
- * @return true
- */
@Override
- public boolean isRootContext() {
+ public boolean isConfiguration() {
return true;
}
@Override
- public boolean isConfiguration() {
- return true;
+ public boolean isInYangDataExtensionBody() {
+ return false;
}
@Override
}
@Override
- public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(final Class<N> type, final K key,
+ public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
final V value) {
if (IncludedModuleContext.class.isAssignableFrom(type)) {
if (includedContexts.isEmpty()) {
Verify.verify(value instanceof RootStatementContext);
includedContexts.add((RootStatementContext<?, ?, ?>) value);
}
- super.addToLocalStorage(type, key, value);
+ return super.putToLocalStorage(type, key, value);
}
+ @Nullable
@Override
public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
+ return getFromLocalStorage(type, key, new HashSet<>());
+ }
+
+ /*
+ * We need to track already checked RootStatementContexts due to possible
+ * circular chains of includes between submodules
+ */
+ @Nullable
+ private <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key,
+ final HashSet<RootStatementContext<?, ?, ?>> alreadyChecked) {
final V potentialLocal = super.getFromLocalStorage(type, key);
if (potentialLocal != null) {
return potentialLocal;
}
- for (final NamespaceStorageNode includedSource : includedContexts) {
- final V potential = includedSource.getFromLocalStorage(type, key);
+
+ alreadyChecked.add(this);
+ for (final RootStatementContext<?, ?, ?> includedSource : includedContexts) {
+ if (alreadyChecked.contains(includedSource)) {
+ continue;
+ }
+ final V potential = includedSource.getFromLocalStorage(type, key, alreadyChecked);
if (potential != null) {
return potential;
}
@Nullable
@Override
public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
+ return getAllFromLocalStorage(type, new HashSet<>());
+ }
+
+ /*
+ * We need to track already checked RootStatementContexts due to possible
+ * circular chains of includes between submodules
+ */
+ @Nullable
+ private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type,
+ final HashSet<RootStatementContext<?, ?, ?>> alreadyChecked) {
final Map<K, V> potentialLocal = super.getAllFromLocalStorage(type);
if (potentialLocal != null) {
return potentialLocal;
}
- for (final NamespaceStorageNode includedSource : includedContexts) {
- final Map<K, V> potential = includedSource.getAllFromLocalStorage(type);
+
+ alreadyChecked.add(this);
+ for (final RootStatementContext<?, ?, ?> includedSource : includedContexts) {
+ if (alreadyChecked.contains(includedSource)) {
+ continue;
+ }
+ final Map<K, V> potential = includedSource.getAllFromLocalStorage(type, alreadyChecked);
if (potential != null) {
return potential;
}
this.version);
this.version = Preconditions.checkNotNull(version);
}
+
+ @Override
+ public void addMutableStmtToSeal(final MutableStatement mutableStatement) {
+ sourceContext.addMutableStmtToSeal(mutableStatement);
+ }
+
+ @Override
+ public void addRequiredModule(final ModuleIdentifier dependency) {
+ Preconditions.checkState(sourceContext.getInProgressPhase() == ModelProcessingPhase.SOURCE_PRE_LINKAGE,
+ "Add required module is allowed only in ModelProcessingPhase.SOURCE_PRE_LINKAGE phase");
+ if (requiredModules.isEmpty()) {
+ requiredModules = new HashSet<>();
+ }
+ requiredModules.add(dependency);
+ }
+
+ Collection<ModuleIdentifier> getRequiredModules() {
+ return ImmutableSet.copyOf(requiredModules);
+ }
+
+ @Override
+ public void setRootIdentifier(final ModuleIdentifier identifier) {
+ Preconditions.checkNotNull(identifier);
+ this.identifier = identifier;
+ }
+
+ ModuleIdentifier getRootIdentifier() {
+ return identifier;
+ }
}