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;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.spi.AbstractEffectiveStatementInference;
/**
* Create a new stack backed by an effective model, pointing to specified schema node identified by an absolute
- * {@link SchemaPath} and its {@link SchemaPath#getPathFromRoot()}.
+ * {@link SchemaPath} and its {@link SchemaPath#getPathFromRoot()} interpreted as a schema node identifier.
*
* @param effectiveModel EffectiveModelContext to which this stack is attached
* @return A new stack
return ret;
}
+ /**
+ * Create a new stack backed by an effective model, pointing to specified schema node identified by an absolute
+ * {@link SchemaPath} and its {@link SchemaPath#getPathFromRoot()}, interpreted as a series of steps along primarily
+ * schema tree, with grouping namespace being the alternative lookup.
+ *
+ * @param effectiveModel EffectiveModelContext to which this stack is attached
+ * @return A new stack
+ * @throws NullPointerException {@code effectiveModel} is null
+ * @throws IllegalArgumentException if {@code path} cannot be resolved in the effective model or if it is not an
+ * absolute path.
+ */
+ @Deprecated
+ public static @NonNull SchemaInferenceStack ofSchemaPath(final EffectiveModelContext effectiveModel,
+ final SchemaPath path) {
+ checkArgument(path.isAbsolute(), "Cannot operate on relative path %s", path);
+ final SchemaInferenceStack ret = new SchemaInferenceStack(effectiveModel);
+
+ for (QName step : path.getPathFromRoot()) {
+ try {
+ ret.enterSchemaTree(step);
+ } catch (IllegalArgumentException schemaEx) {
+ try {
+ ret.enterGrouping(step);
+ } catch (IllegalArgumentException ex) {
+ ex.addSuppressed(schemaEx);
+ throw ex;
+ }
+ }
+ }
+
+ return ret;
+ }
+
@Override
public EffectiveModelContext getEffectiveModelContext() {
return effectiveModel;
}
/**
- * Check if the stack is in instantiated context. This indicates the stack is non-empty and there is no grouping
- * (or similar construct) present in the stack.
+ * Check if the stack is in instantiated context. This indicates the stack is non-empty and there are only screma
+ * tree statements in the stack.
*
- * @return False if the stack is empty or contains a grouping, true otherwise.
+ * @return False if the stack is empty or contains a statement which is not a {@link SchemaTreeEffectiveStatement},
+ * true otherwise.
*/
public boolean inInstantiatedContext() {
- return groupingDepth == 0 && !deque.isEmpty();
+ return groupingDepth == 0 && !deque.isEmpty()
+ && deque.stream().allMatch(SchemaTreeEffectiveStatement.class::isInstance);
+ }
+
+ /**
+ * Check if the stack is in a {@code grouping} context.
+ *
+ * @return False if the stack contains a grouping.
+ */
+ public boolean inGrouping() {
+ return groupingDepth != 0;
}
/**
* {@link #enterSchemaTree(QName)}, except it handles the use case where traversal ignores actual {@code case}
* intermediate schema tree children.
*
- * @param nodeIdentifier Node identifier of the grouping to enter
+ * @param nodeIdentifier Node identifier of the choice to enter
* @return Resolved choice
* @throws NullPointerException if {@code nodeIdentifier} is null
* @throws IllegalArgumentException if the corresponding choice cannot be found
return pushData(requireNonNull(nodeIdentifier));
}
+ /**
+ * Lookup a {@code typedef} by its node identifier and push it to the stack.
+ *
+ * @param nodeIdentifier Node identifier of the typedef to enter
+ * @return Resolved choice
+ * @throws NullPointerException if {@code nodeIdentifier} is null
+ * @throws IllegalArgumentException if the corresponding typedef cannot be found
+ */
+ public @NonNull TypedefEffectiveStatement enterTypedef(final QName nodeIdentifier) {
+ return pushTypedef(requireNonNull(nodeIdentifier));
+ }
+
/**
* Pop the current statement from the stack.
*
public @NonNull DataTreeEffectiveStatement<?> exitToDataTree() {
final EffectiveStatement<?, ?> child = exit();
checkState(child instanceof DataTreeEffectiveStatement, "Unexpected current %s", child);
- final EffectiveStatement<?, ?> parent = deque.peekFirst();
+ EffectiveStatement<?, ?> parent = deque.peekFirst();
+ while (parent instanceof ChoiceEffectiveStatement || parent instanceof CaseEffectiveStatement) {
+ deque.pollFirst();
+ parent = deque.peekFirst();
+ }
+
checkState(parent == null || parent instanceof DataTreeAwareEffectiveStatement, "Unexpected parent %s", parent);
return (DataTreeEffectiveStatement<?>) child;
}
return ret;
}
+ private @NonNull TypedefEffectiveStatement pushTypedef(final @NonNull QName nodeIdentifier) {
+ final EffectiveStatement<?, ?> parent = deque.peekFirst();
+ return parent != null ? pushTypedef(parent, nodeIdentifier) : pushFirstTypedef(nodeIdentifier);
+ }
+
+ private @NonNull TypedefEffectiveStatement pushTypedef(final @NonNull EffectiveStatement<?, ?> parent,
+ final @NonNull QName nodeIdentifier) {
+ // TODO: 8.0.0: revisit this once we have TypedefNamespace working
+ final TypedefEffectiveStatement ret = parent.streamEffectiveSubstatements(TypedefEffectiveStatement.class)
+ .filter(stmt -> nodeIdentifier.equals(stmt.argument()))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("Grouping " + nodeIdentifier + " not present"));
+ deque.push(ret);
+ return ret;
+ }
+
+ private @NonNull TypedefEffectiveStatement pushFirstTypedef(final @NonNull QName nodeIdentifier) {
+ final ModuleEffectiveStatement module = getModule(nodeIdentifier);
+ final TypedefEffectiveStatement ret = pushTypedef(module, nodeIdentifier);
+ currentModule = module;
+ return ret;
+ }
+
private @NonNull ModuleEffectiveStatement getModule(final @NonNull QName nodeIdentifier) {
final ModuleEffectiveStatement module = effectiveModel.getModuleStatements().get(nodeIdentifier.getModule());
checkArgument(module != null, "Module for %s not found", nodeIdentifier);
tmp.enterSchemaTree(((SchemaTreeEffectiveStatement<?> )stmt).argument());
} else if (stmt instanceof GroupingEffectiveStatement) {
tmp.enterGrouping(((GroupingEffectiveStatement) stmt).argument());
+ } else if (stmt instanceof TypedefEffectiveStatement) {
+ tmp.enterTypedef(((TypedefEffectiveStatement) stmt).argument());
} else {
throw new VerifyException("Unexpected statement " + stmt);
}