+++ /dev/null
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.yangtools.yang.parser.stmt.reactor;
-
-import com.google.common.base.Preconditions;
-import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.concepts.Builder;
-import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
-
-abstract class ContextBuilder<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
- implements Builder<StatementContextBase<A, D, E>> {
-
- private final StatementDefinitionContext<A, D, E> definition;
- private final StatementSourceReference stmtRef;
-
- private StatementSourceReference argRef;
- private String rawArg;
-
- ContextBuilder(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference sourceRef) {
- this.definition = Preconditions.checkNotNull(def);
- this.stmtRef = Preconditions.checkNotNull(sourceRef);
- }
-
- void setArgument(@Nonnull final String argument, @Nonnull final StatementSourceReference argumentSource) {
- SourceException.throwIf(!definition.hasArgument(), argumentSource, "Statement %s does not take argument",
- definition.getStatementName());
- this.rawArg = Preconditions.checkNotNull(argument);
- this.argRef = Preconditions.checkNotNull(argumentSource);
- }
-
- String getRawArgument() {
- return rawArg;
- }
-
- StatementSourceReference getStamementSource() {
- return stmtRef;
- }
-
- StatementSourceReference getArgumentSource() {
- return argRef;
- }
-
- StatementDefinitionContext<A, D, E> getDefinition() {
- return definition;
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws SourceException when a source-level problem is found
- */
- @Override
- public abstract StatementContextBase<A, D, E> build();
-}
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;
/**
* Root statement class for a YANG source. All statements defined in that YANG source are mapped underneath an instance
*/
private Collection<RootStatementContext<?, ?, ?>> includedContexts = ImmutableList.of();
- RootStatementContext(final ContextBuilder<A, D, E> builder, final SourceSpecificContext sourceContext) {
- super(builder);
+ RootStatementContext(final SourceSpecificContext sourceContext, final StatementDefinitionContext<A, D, E> def,
+ final StatementSourceReference ref, final String rawArgument) {
+ super(def, ref, rawArgument);
this.sourceContext = Preconditions.checkNotNull(sourceContext);
- this.argument = builder.getDefinition().parseArgumentValue(this, builder.getRawArgument());
+ this.argument = def.parseArgumentValue(this, rawArgument);
}
- RootStatementContext(final ContextBuilder<A, D, E> builder, final SourceSpecificContext sourceContext,
- final YangVersion version) {
- this(builder, sourceContext);
+ RootStatementContext(final SourceSpecificContext sourceContext, final StatementDefinitionContext<A, D, E> def,
+ final StatementSourceReference ref, final String rawArgument, final YangVersion version) {
+ this(sourceContext, def, ref, rawArgument);
this.setRootVersion(version);
}
FINISHED
}
- @SuppressWarnings({"rawtypes", "unchecked"})
- private final class RootContextBuilder extends ContextBuilder {
- RootContextBuilder(final StatementDefinitionContext def, final StatementSourceReference sourceRef) {
- super(def, sourceRef);
- }
-
- @Override
- public StatementContextBase build() {
- /*
- * If root is null or root version is other than default,
- * we need to create new root.
- */
- if (root == null) {
- root = new RootStatementContext(this, SourceSpecificContext.this);
- } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.getRootVersion())
- && inProgressPhase == ModelProcessingPhase.SOURCE_LINKAGE) {
- root = new RootStatementContext(this, SourceSpecificContext.this, root.getRootVersion());
- } else {
- final QName rootStatement = root.definition().getStatementName();
- final String rootArgument = root.rawStatementArgument();
-
- Preconditions.checkState(Objects.equals(getDefinition().getStatementName(), rootStatement)
- && Objects.equals(getRawArgument(), rootArgument),
- "Root statement was already defined as '%s %s'.", rootStatement, rootArgument);
- }
- root.resetLists();
- return root;
- }
- }
-
private static final Logger LOG = LoggerFactory.getLogger(SourceSpecificContext.class);
private static final Table<YangVersion, String, StatementSupport<?, ?, ?>> BUILTIN_TYPE_SUPPORTS =
ImmutableTable.<YangVersion, String, StatementSupport<?, ?, ?>>builder()
return inProgressPhase;
}
- ContextBuilder<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final int childId,
+ StatementContextBase<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final int childId,
QName name, final String argument, final StatementSourceReference ref) {
+ if (current != null) {
+ // Fast path: we are entering a statement which was emitted in previous phase
+ final StatementContextBase<?, ?, ?> existing = current.lookupSubstatement(childId);
+ if (existing != null) {
+ return existing;
+ }
+ }
+
// FIXME: BUG-7038: Refactor/clean up this special case
if (TYPE.equals(name)) {
SourceException.throwIfNull(argument, ref, "Type statement requires an argument");
}
StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(getRootVersion(), name);
-
if (def == null) {
final StatementSupport<?, ?, ?> extension = qNameToStmtDefMap.get(name);
if (extension != null) {
*/
final QName qName = Utils.qNameFromArgument(current, name.getLocalName());
def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition(
- new ModelDefinedStatementDefinition(qName)));
+ new ModelDefinedStatementDefinition(qName, argument != null)));
}
- Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.", name);
- final ContextBuilder<?, ?, ?> ret;
- if (current == null) {
- ret = new RootContextBuilder(def, ref);
+ InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name);
+ if (def.hasArgument()) {
+ SourceException.throwIfNull(argument, ref, "Statement %s requires an argument", name);
} else {
- ret = current.substatementBuilder(childId, def, ref);
+ SourceException.throwIf(argument != null, ref, "Statement %s does not take argument", name);
}
- if (argument != null) {
- ret.setArgument(argument, ref);
+ if (current != null) {
+ return current.createSubstatement(childId, def, ref, argument);
}
- return ret;
+ /*
+ * If root is null or root version is other than default,
+ * we need to create new root.
+ */
+ if (root == null) {
+ root = new RootStatementContext<>(this, def, ref, argument);
+ } else if (!RootStatementContext.DEFAULT_VERSION.equals(root.getRootVersion())
+ && inProgressPhase == ModelProcessingPhase.SOURCE_LINKAGE) {
+ root = new RootStatementContext<>(this, def, ref, argument, root.getRootVersion());
+ } else {
+ final QName rootStatement = root.definition().getStatementName();
+ final String rootArgument = root.rawStatementArgument();
+
+ Preconditions.checkState(Objects.equals(def.getStatementName(), rootStatement)
+ && Objects.equals(argument, rootArgument),
+ "Root statement was already defined as '%s %s'.", rootStatement, rootArgument);
+ }
+ return root;
}
RootStatementContext<?, ?, ?> getRoot() {
public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
extends NamespaceStorageSupport implements StmtContext.Mutable<A, D, E> {
- @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
*/
private Multimap<ModelProcessingPhase, OnPhaseFinished> phaseListeners = ImmutableMultimap.of();
private Multimap<ModelProcessingPhase, ContextMutation> phaseMutation = ImmutableMultimap.of();
- private Collection<StatementContextBase<?, ?, ?>> declared = ImmutableList.of();
private Collection<StatementContextBase<?, ?, ?>> effective = ImmutableList.of();
private Collection<StatementContextBase<?, ?, ?>> effectOfStatement = ImmutableList.of();
private StatementMap substatements = StatementMap.empty();
private E effectiveInstance;
private int order = 0;
- StatementContextBase(@Nonnull final ContextBuilder<A, D, E> builder) {
- this.definition = builder.getDefinition();
- this.statementDeclSource = builder.getStamementSource();
- this.rawArgument = builder.getRawArgument();
+ StatementContextBase(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
+ final String rawArgument) {
+ this.definition = Preconditions.checkNotNull(def);
+ this.statementDeclSource = Preconditions.checkNotNull(ref);
+ this.rawArgument = rawArgument;
}
StatementContextBase(final StatementContextBase<A, D, E> original) {
}
@Override
- public String rawStatementArgument() {
+ public final String rawStatementArgument() {
return rawArgument;
}
- private static final <T> Collection<T> maybeWrap(final Collection<T> input) {
- if (input instanceof ImmutableCollection) {
- return input;
- }
-
- return Collections.unmodifiableCollection(input);
- }
-
@Nonnull
@Override
public Collection<StatementContextBase<?, ?, ?>> declaredSubstatements() {
- return maybeWrap(declared);
+ return substatements.values();
}
@Nonnull
@Override
public Collection<StatementContextBase<?, ?, ?>> effectiveSubstatements() {
- return maybeWrap(effective);
+ if (effective instanceof ImmutableCollection) {
+ return effective;
+ }
+
+ return Collections.unmodifiableCollection(effective);
}
public void removeStatementsFromEffectiveSubstatements(final Collection<StatementContextBase<?, ?, ?>> substatements) {
}
/**
- * adds declared statement to collection of substatements
+ * Create a new substatement at the specified offset.
*
- * @param substatement substatement
- * @throws IllegalStateException
- * if added in effective phase
- * @throws NullPointerException
- * if statement parameter is null
+ * @param offset Substatement offset
+ * @param def definition context
+ * @param ref source reference
+ * @param argument statement argument
+ * @return A new substatement
*/
- public void addDeclaredSubstatement(final StatementContextBase<?, ?, ?> substatement) {
-
+ final <CA, CD extends DeclaredStatement<CA>, CE extends EffectiveStatement<CA, CD>> StatementContextBase<CA, CD, CE>
+ createSubstatement(final int offset, final StatementDefinitionContext<CA, CD, CE> def,
+ final StatementSourceReference ref, final String argument) {
final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
Preconditions.checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
"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 at: %s", getStatementSourceReference()));
+ final StatementContextBase<CA, CD, CE> ret = new SubstatementContext<>(this, def, ref, argument);
+ substatements = substatements.put(offset, ret);
+ def.onStatementAdded(ret);
+ return ret;
}
/**
- * builds a new substatement from statement definition context and statement source reference
+ * Lookup substatement by its offset in this statement.
*
- * @param def definition context
- * @param ref source reference
- *
- * @return instance of ContextBuilder
+ * @param offset Substatement offset
+ * @return Substatement, or null if substatement does not exist.
*/
- ContextBuilder<?, ?, ?> substatementBuilder(final int childId, final StatementDefinitionContext<?, ?, ?> def,
- final StatementSourceReference ref) {
- return new SubContextBuilder(childId, def, ref);
+ final StatementContextBase<?, ?, ?> lookupSubstatement(final int offset) {
+ return substatements.get(offset);
}
/**
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 at: %s", getStatementSourceReference());
-
- declared = ImmutableList.of();
- }
-
/**
* tries to execute current {@link ModelProcessingPhase} of source parsing
*
}
}
- for (final StatementContextBase<?, ?, ?> child : declared) {
+ for (final StatementContextBase<?, ?, ?> child : substatements.values()) {
finished &= child.tryToCompletePhase(phase);
}
for (final StatementContextBase<?, ?, ?> child : effective) {
}
/**
- * occurs on end of {@link ModelProcessingPhase} of source parsing
+ * 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
+ * when an error occurred in source parsing
*/
private void onPhaseCompleted(final ModelProcessingPhase phase) {
completedPhase = phase;
package org.opendaylight.yangtools.yang.parser.stmt.reactor;
import com.google.common.base.Preconditions;
+import com.google.common.base.Verify;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
private final ModelProcessingPhase phase;
private final SourceSpecificContext ctx;
- private StatementContextBase<?, ?, ?> parent;
- private ContextBuilder<?, ?, ?> current;
+ private StatementContextBase<?, ?, ?> current;
- public StatementContextWriter(final SourceSpecificContext ctx, final ModelProcessingPhase phase) {
+ StatementContextWriter(final SourceSpecificContext ctx, final ModelProcessingPhase phase) {
this.ctx = Preconditions.checkNotNull(ctx);
this.phase = Preconditions.checkNotNull(phase);
}
@Override
public void startStatement(final int childId, @Nonnull final QName name, final String argument,
@Nonnull final StatementSourceReference ref) {
- deferredCreate();
- current = ctx.createDeclaredChild(parent, childId, name, argument, ref);
+ current = Verify.verifyNotNull(ctx.createDeclaredChild(current, childId, name, argument, ref));
}
@Override
public void endStatement(@Nonnull final StatementSourceReference ref) {
- deferredCreate();
- Preconditions.checkState(parent != null);
- parent.endDeclared(ref,phase);
- parent = parent.getParentContext();
+ Preconditions.checkState(current != null);
+ current.endDeclared(ref, phase);
+ current = current.getParentContext();
}
@Nonnull
public ModelProcessingPhase getPhase() {
return phase;
}
-
- private void deferredCreate() {
- if (current != null) {
- parent = current.build();
- current = null;
- }
- }
}
package org.opendaylight.yangtools.yang.parser.stmt.reactor;
import com.google.common.base.Preconditions;
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.ImmutableList;
+import java.util.AbstractCollection;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.function.Consumer;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
/**
- * Simple integer-to-StatementContextBase map optimized for size and restricted in scope of operations.
+ * Simple integer-to-StatementContextBase map optimized for size and restricted in scope of operations. It does not
+ * implement {@link java.util.Map} for simplicity's sake.
*
* @author Robert Varga
*/
StatementMap put(final int index, final StatementContextBase<?, ?, ?> object) {
return index == 0 ? new Singleton(object) : new Regular(index, object);
}
+
+ @Override
+ Collection<StatementContextBase<?, ?, ?>> values() {
+ return ImmutableList.of();
+ }
}
private static final class Regular extends StatementMap {
elements[index] = Preconditions.checkNotNull(object);
return this;
}
+
+ @Override
+ Collection<StatementContextBase<?, ?, ?>> values() {
+ return new RegularAsCollection<>(elements);
+ }
+ }
+
+ private static final class RegularAsCollection<T> extends AbstractCollection<T> {
+ private final T[] elements;
+
+ RegularAsCollection(final T[] elements) {
+ this.elements = Preconditions.checkNotNull(elements);
+ }
+
+ @Override
+ public void forEach(final Consumer<? super T> action) {
+ for (T e : elements) {
+ if (e != null) {
+ action.accept(e);
+ }
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ // This has a single-use and when it is instantiated, we know to have at least two items
+ return false;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return new AbstractIterator<T>() {
+ private int nextOffset = 0;
+
+ @Override
+ protected T computeNext() {
+ while (nextOffset < elements.length) {
+ final T ret = elements[nextOffset++];
+ if (ret != null) {
+ return ret;
+ }
+ }
+
+ return endOfData();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ // Optimized for non-sparse case
+ int nulls = 0;
+ for (T e : elements) {
+ if (e == null) {
+ nulls++;
+ }
+ }
+
+ return elements.length - nulls;
+ }
}
+
private static final class Singleton extends StatementMap {
private final StatementContextBase<?, ?, ?> object;
Preconditions.checkArgument(index != 0);
return new Regular(this.object, index, object);
}
+
+ @Override
+ Collection<StatementContextBase<?, ?, ?>> values() {
+ return ImmutableList.of(object);
+ }
}
private static final StatementMap EMPTY = new Empty();
return EMPTY;
}
- abstract StatementContextBase<?, ?, ?> get(int index);
+ /**
+ * Return the statement context at specified index.
+ *
+ * @param index Element index, must be non-negative
+ * @return Requested element or null if there is no element at that index
+ */
+ abstract @Nullable StatementContextBase<?, ?, ?> get(int index);
+
+ /**
+ * Add a statement at specified index.
+ *
+ * @param index Element index, must be non-negative
+ * @param object Object to store
+ * @return New statement map
+ * @throws IllegalArgumentException if the index is already occupied
+ */
abstract @Nonnull StatementMap put(int index, @Nonnull StatementContextBase<?, ?, ?> object);
+
+ /**
+ * Return a read-only view of the elements in this map. Unlike other maps, this view does not detect concurrent
+ * modification. Iteration is performed in order of increasing offset. In face of concurrent modification, number
+ * of elements returned through iteration may not match the size reported via {@link Collection#size()}.
+ *
+ * @return Read-only view of available statements.
+ */
+ abstract @Nonnull Collection<StatementContextBase<?, ?, ?>> values();
}
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.AugmentToChoiceNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
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.rfc6020.Utils;
private volatile SchemaPath schemaPath;
- SubstatementContext(final StatementContextBase<?, ?, ?> parent, final ContextBuilder<A, D, E> builder) {
- super(builder);
+ SubstatementContext(final StatementContextBase<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
+ final StatementSourceReference ref, final String rawArgument) {
+ super(def, ref, rawArgument);
this.parent = Preconditions.checkNotNull(parent, "Parent must not be null");
- this.argument = builder.getDefinition().parseArgumentValue(this, builder.getRawArgument());
+ this.argument = def.parseArgumentValue(this, rawArgument);
}
@SuppressWarnings("unchecked")
}
@Deprecated
- public ModelDefinedStatementDefinition(final QName qname) {
- this(qname, qname, false);
+ public ModelDefinedStatementDefinition(final QName qname, final boolean hasArgument) {
+ this(qname, hasArgument ? qname : null, false);
}
@Nonnull
}
}
- br:opendaylight;
+ br:opendaylight awesome;
}
}
argument test;
}
- riu:test-extension {
+ riu:test-extension test {
container cont {
description
"This is just a plain text";
type br:my-decimal-type;
}
- br:opendaylight;
+ br:opendaylight awesome;
}
}
type br:my-decimal-type;
}
- br:opendaylight;
+ br:opendaylight awesome;
}
}
type br:my-decimal-type;
}
- br:opendaylight;
+ br:opendaylight awesome;
}
}
type br:my-decimal-type;
}
- br:opendaylight;
+ br:opendaylight awesome;
}
}