<artifactId>guava</artifactId>
</dependency>
</dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!-- FIXME: remove this when odlparent provides this -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <tags>
+ <tag>
+ <name>apiNote</name>
+ <placement>a</placement>
+ <head>API Note:</head>
+ </tag>
+ <tag>
+ <name>implSpec</name>
+ <placement>a</placement>
+ <head>Implementation Requirements:</head>
+ </tag>
+ <tag>
+ <name>implNote</name>
+ <placement>a</placement>
+ <head>Implementation Note:</head>
+ </tag>
+ </tags>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
</project>
@Beta
public interface EffectiveStatementInference extends EffectiveModelContextProvider, Immutable {
/**
- * An {@code Unmodifiable} {@link List} of {@link EffectiveStatement}s, ordered in some meaningful way.
+ * An {@code Unmodifiable} {@link List} of {@link EffectiveStatement}s, ordered in some meaningful way. Precise
+ * semantics of the statement order is clarified by individual {@link EffectiveStatementInference} specializations.
*
+ * @see SchemaTreeInference
* @return A List of EffectiveStatements
*/
- @NonNull List<@NonNull EffectiveStatement<?, ?>> statementPath();
+ @NonNull List<? extends @NonNull EffectiveStatement<?, ?>> statementPath();
}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.model.api;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+
+/**
+ * An {@link EffectiveStatementInference} consisting purely of steps along the {@code schema tree} axis, so that it
+ * represents a {@code schema tree node} based on resolution of {@code absolute-schema-nodeid} as specified by
+ * <a href="https://tools.ietf.org/html/rfc7950#section-6.5">RFC7950 section 6.5</a>.
+ */
+public interface SchemaTreeInference extends EffectiveStatementInference {
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * The statement path is always composed on {@link SchemaTreeEffectiveStatement}s and contains at least one element.
+ * The path is ordered from conceptual YANG root, i.e. the first element corresponds to the first element in
+ * {@link SchemaNodeIdentifier.Absolute#firstNodeIdentifier()}.
+ */
+ @Override
+ List<@NonNull SchemaTreeEffectiveStatement<?>> statementPath();
+
+ /**
+ * Return the {@link SchemaNodeIdentifier.Absolute} which resulted in this inference.
+ *
+ * @implSpec
+ * Default implementation interprets {@link #statementPath()}'s arguments as the ordered source of
+ * {@link SchemaNodeIdentifier.Absolute} steps.
+ *
+ * @return An absolute SchemaNodeIdentifier
+ */
+ default SchemaNodeIdentifier.Absolute toSchemaNodeIdentifier() {
+ return SchemaNodeIdentifier.Absolute.of(statementPath().stream()
+ .map(SchemaTreeEffectiveStatement::argument)
+ .collect(ImmutableList.toImmutableList()));
+ }
+}
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
/**
- * A simple capture of an {@link EffectiveModelContext} and a list of paths. No further guarantees are made.
+ * A simple capture of an {@link EffectiveModelContext} and a list of {@link EffectiveStatement}s. No further guarantees
+ * are made.
+ *
+ * @param T constituent {@link EffectiveStatement} type
*/
@Beta
-public abstract class AbstractEffectiveStatementInference extends AbstractEffectiveModelContextProvider
- implements EffectiveStatementInference {
- private final @NonNull List<EffectiveStatement<?, ?>> path;
+public abstract class AbstractEffectiveStatementInference<T extends EffectiveStatement<?, ?>>
+ extends AbstractEffectiveModelContextProvider implements EffectiveStatementInference {
+ private final @NonNull List<T> path;
protected AbstractEffectiveStatementInference(final @NonNull EffectiveModelContext modelContext,
- final @NonNull ImmutableList<EffectiveStatement<?, ?>> path) {
+ final @NonNull ImmutableList<T> path) {
super(modelContext);
this.path = requireNonNull(path);
}
protected AbstractEffectiveStatementInference(final @NonNull EffectiveModelContext modelContext,
- final @NonNull List<? extends EffectiveStatement<?, ?>> path) {
+ final @NonNull List<? extends T> path) {
super(modelContext);
this.path = ImmutableList.copyOf(path);
}
@Override
- public final List<EffectiveStatement<?, ?>> statementPath() {
+ public final List<T> statementPath() {
return path;
}
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
+ return super.addToStringAttributes(helper).add("statements", path);
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.model.spi;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaTreeInference;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+
+/**
+ * Default implementation of a a {@link SchemaTreeInference}. Guaranteed to be consistent with its
+ * {@link #getEffectiveModelContext()}.
+ */
+@Beta
+@NonNullByDefault
+public final class DefaultSchemaTreeInference
+ extends AbstractEffectiveStatementInference<SchemaTreeEffectiveStatement<?>> implements SchemaTreeInference {
+ private DefaultSchemaTreeInference(final EffectiveModelContext modelContext,
+ final ImmutableList<SchemaTreeEffectiveStatement<?>> path) {
+ super(modelContext, path);
+ }
+
+ /**
+ * Create a new instance.
+ *
+ * @param modelContext Associated {@link EffectiveModelContext}
+ * @param path An absolute schema node identifier
+ * @return A new instance
+ */
+ public static DefaultSchemaTreeInference of(final EffectiveModelContext modelContext, final Absolute path) {
+ final List<QName> steps = path.getNodeIdentifiers();
+ final QName first = steps.get(0);
+ final ModuleEffectiveStatement module = modelContext.findModuleStatement(first.getModule()).orElseThrow(
+ () -> new IllegalArgumentException("No module for " + first));
+
+ final ImmutableList.Builder<SchemaTreeEffectiveStatement<?>> builder =
+ ImmutableList.builderWithExpectedSize(steps.size());
+ SchemaTreeAwareEffectiveStatement<?, ?> parent = module;
+ final Iterator<QName> it = steps.iterator();
+ while (true) {
+ final QName qname = it.next();
+ final SchemaTreeEffectiveStatement<?> found = parent.findSchemaTreeNode(qname).orElseThrow(
+ () -> new IllegalArgumentException("Cannot resolve step " + qname + " in " + builder.build()));
+ if (it.hasNext()) {
+ checkArgument(found instanceof SchemaTreeAwareEffectiveStatement, "Cannot resolve steps %s past %s",
+ steps, found);
+ parent = (SchemaTreeAwareEffectiveStatement<?, ?>) found;
+ } else {
+ break;
+ }
+ }
+
+ return new DefaultSchemaTreeInference(modelContext, builder.build());
+ }
+}
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
import org.opendaylight.yangtools.yang.model.api.EffectiveStatementInference;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.SchemaTreeInference;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.spi.AbstractEffectiveStatementInference;
+import org.opendaylight.yangtools.yang.model.spi.DefaultSchemaTreeInference;
/**
* A state tracking utility for walking {@link EffectiveModelContext}'s contents along schema/grouping namespaces. This
* {@link #statementPath()} is implementation-specific.
*/
@Beta
- public static final class Inference extends AbstractEffectiveStatementInference {
+ public static final class Inference extends AbstractEffectiveStatementInference<EffectiveStatement<?, ?>> {
private final ModuleEffectiveStatement currentModule;
private final int groupingDepth;
private final boolean clean;
public static @NonNull SchemaInferenceStack ofInference(final EffectiveStatementInference inference) {
if (inference.statementPath().isEmpty()) {
return new SchemaInferenceStack(inference.getEffectiveModelContext());
+ } else if (inference instanceof SchemaTreeInference) {
+ return ofInference((SchemaTreeInference) inference);
+ } else if (inference instanceof Inference) {
+ return ((Inference) inference).toSchemaInferenceStack();
+ } else {
+ throw new IllegalArgumentException("Unsupported Inference " + inference);
}
- checkArgument(inference instanceof Inference, "Inference %s not supported", inference);
- return ((Inference) inference).toSchemaInferenceStack();
+ }
+
+ /**
+ * Create a new stack from an {@link SchemaTreeInference}.
+ *
+ * @param inference SchemaTreeInference to use for initialization
+ * @return A new stack
+ * @throws NullPointerException if {@code inference} is null
+ * @throws IllegalArgumentException if {@code inference} cannot be resolved to a valid stack
+ */
+ public static @NonNull SchemaInferenceStack ofInference(final SchemaTreeInference inference) {
+ return of(inference.getEffectiveModelContext(), inference.toSchemaNodeIdentifier());
}
/**
return new Inference(effectiveModel, deque.descendingIterator(), currentModule, groupingDepth, clean);
}
+ /**
+ * Return an {@link SchemaTreeInference} equivalent of current state.
+ *
+ * @return An {@link SchemaTreeInference}
+ * @throws IllegalStateException if current state cannot be converted to a {@link SchemaTreeInference}
+ */
+ public @NonNull SchemaTreeInference toSchemaTreeInference() {
+ return DefaultSchemaTreeInference.of(getEffectiveModelContext(), toSchemaNodeIdentifier());
+ }
+
/**
* Convert current state into an absolute schema node identifier.
*