import static java.util.Objects.requireNonNull;
-import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathDocument;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+@NonNullByDefault
final class JaxenDocument implements XPathDocument {
+ private final DataSchemaContextNode<?> schema;
private final NormalizedNode<?, ?> root;
private final SchemaContext context;
- JaxenDocument(final JaxenSchemaContext context, final NormalizedNode<?, ?> root) {
+ JaxenDocument(final SchemaContext context, final DataSchemaContextTree tree,
+ final NormalizedNode<?, ?> root) {
this.root = requireNonNull(root);
- this.context = context.getSchemaContext();
+ this.context = requireNonNull(context);
+ this.schema = requireNonNull(tree.getRoot().getChild(root.getIdentifier()));
}
- @Nonnull
@Override
public NormalizedNode<?, ?> getRootNode() {
return root;
}
- @Nonnull
SchemaContext getSchemaContext() {
return context;
}
+
+ DataSchemaContextNode<?> getSchema() {
+ return schema;
+ }
}
import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathDocument;
import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathExpression;
import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathSchemaContext;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
final class JaxenSchemaContext implements XPathSchemaContext {
- // Will be needed for compileExpression()
+ private final DataSchemaContextTree tree;
private final SchemaContext context;
JaxenSchemaContext(final SchemaContext context) {
this.context = requireNonNull(context);
+ this.tree = DataSchemaContextTree.from(context);
}
@Nonnull
@Nonnull
@Override
public XPathDocument createDocument(@Nonnull final NormalizedNode<?, ?> documentRoot) {
- return new JaxenDocument(this, documentRoot);
- }
-
- @Nonnull
- SchemaContext getSchemaContext() {
- return context;
+ return new JaxenDocument(context, tree, documentRoot);
}
}
*/
package org.opendaylight.yangtools.yang.data.jaxen;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.jaxen.Context;
import org.jaxen.ContextSupport;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
/**
* Context wrapper around a {@link NormalizedNode} for use with Jaxen. It tracks the parent node for purposes of
* traversing upwards the NormalizedNode tree.
*/
+@NonNullByDefault
final class NormalizedNodeContext extends Context implements Function<NormalizedNode<?, ?>, NormalizedNodeContext> {
private static final long serialVersionUID = 1L;
- private final NormalizedNodeContext parent;
+ private final @Nullable NormalizedNodeContext parent;
+ private final DataSchemaContextNode<?> schema;
private final NormalizedNode<?, ?> node;
- NormalizedNodeContext(@Nonnull final ContextSupport contextSupport, @Nonnull final NormalizedNode<?, ?> node,
- @Nullable final NormalizedNodeContext parent) {
+ private NormalizedNodeContext(final ContextSupport contextSupport, final DataSchemaContextNode<?> schema,
+ final NormalizedNode<?, ?> node, final @Nullable NormalizedNodeContext parent) {
super(contextSupport);
+ this.schema = requireNonNull(schema);
this.node = requireNonNull(node);
this.parent = parent;
setNodeSet(ImmutableList.of(this));
}
- @Nonnull NormalizedNode<?, ?> getNode() {
+ static NormalizedNodeContext forRoot(final NormalizedNodeContextSupport contextSupport) {
+ final JaxenDocument document = contextSupport.getNavigator().getDocument();
+ return new NormalizedNodeContext(contextSupport, document.getSchema(), document.getRootNode(), null);
+ }
+
+ NormalizedNode<?, ?> getNode() {
return node;
}
return parent;
}
- @Nonnull YangInstanceIdentifier getPath() {
+ YangInstanceIdentifier getPath() {
return (parent == null ? YangInstanceIdentifier.EMPTY : parent.getPath()).node(node.getIdentifier());
}
+ DataSchemaContextNode<?> getSchema() {
+ return schema;
+ }
+
@Override
public NormalizedNodeContext apply(final NormalizedNode<?, ?> input) {
- return new NormalizedNodeContext(getContextSupport(), input, this);
+ DataSchemaContextNode<?> childSchema = schema.getChild(input.getIdentifier());
+ if (childSchema == null) {
+ /* This feels very much like a hack: but solves lookup of child nodes with predicates.
+ *
+ * What is happening is that a Map context gets queried for its children, which results in contexts being
+ * backed by UnorderedMapMixinContextNode, which requires us to unmask it.
+ *
+ * When the predicate is being evaluated, each child is queried for its child -- but since it is protected,
+ * we cannot find it.
+ */
+ final DataSchemaNode mySchema = schema.getDataSchemaNode();
+ if (mySchema instanceof ListSchemaNode) {
+ childSchema = verifyNotNull(schema.getChild(mySchema.getQName())).getChild(input.getIdentifier());
+ }
+ }
+
+ checkArgument(childSchema != null, "Failed to find schema for child %s", input);
+ return new NormalizedNodeContext(getContextSupport(), childSchema, input, this);
}
}
private NormalizedNodeContextSupport(final ConverterNamespaceContext context,
final NormalizedNodeNavigator navigator) {
super(context, YangFunctionContext.getInstance(), new SimpleVariableContext(), navigator);
- this.root = new NormalizedNodeContext(this, navigator.getRootNode(), null);
+ this.root = NormalizedNodeContext.forRoot(this);
}
static NormalizedNodeContextSupport create(final JaxenDocument document,
for (PathArgument arg : path.getPathArguments()) {
final Optional<NormalizedNode<?, ?>> node = NormalizedNodes.getDirectChild(result.getNode(), arg);
checkArgument(node.isPresent(), "Node %s has no child %s", result.getNode(), arg);
- result = new NormalizedNodeContext(this, node.get(), result);
+ result = result.apply(node.get());
}
-
return result;
}
- SchemaContext getSchemaContext() {
- return getNavigator().getSchemaContext();
- }
-
@Override
public NormalizedNodeNavigator getNavigator() {
return (NormalizedNodeNavigator) super.getNavigator();
}
+
+ SchemaContext getSchemaContext() {
+ return getNavigator().getDocument().getSchemaContext();
+ }
}
import com.google.common.collect.UnmodifiableIterator;
import com.google.common.io.BaseEncoding;
import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
-import javax.annotation.Nonnull;
import org.jaxen.DefaultNavigator;
import org.jaxen.NamedAccessNavigator;
import org.jaxen.Navigator;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
/**
* A {@link Navigator} implementation for YANG XPaths instantiated on a particular root {@link NormalizedNode}.
return null;
}
- // The child may be a structural node
final NormalizedNode<?, ?> child = maybeChild.get();
+ final Collection<? extends NormalizedNode<?, ?>> collection;
+
+ // The child may be a structural node
if (child instanceof MapNode) {
- return Iterators.transform(((MapNode)child).getValue().iterator(), ctx);
- }
- if (child instanceof LeafSetNode) {
- return Iterators.transform(((LeafSetNode<?>)child).getValue().iterator(), ctx);
+ collection = ((MapNode)child).getValue();
+ } else if (child instanceof LeafSetNode) {
+ collection = ((LeafSetNode<?>)child).getValue();
+ } else {
+ return Iterators.singletonIterator(ctx.apply(child));
}
- return Iterators.singletonIterator(ctx.apply(child));
+ return Iterators.transform(collection.iterator(), ctx);
}
@Override
return cast(contextNode).getParent();
}
- NormalizedNode<?, ?> getRootNode() {
- return document.getRootNode();
- }
-
- @Nonnull
- SchemaContext getSchemaContext() {
- return document.getSchemaContext();
+ JaxenDocument getDocument() {
+ return document;
}
private static final class NormalizedNodeContextIterator extends UnmodifiableIterator<NormalizedNodeContext> {
import com.google.common.base.Splitter;
import com.google.common.base.Verify;
import java.util.AbstractMap.SimpleImmutableEntry;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import org.jaxen.Function;
import org.jaxen.FunctionCallException;
import org.jaxen.FunctionContext;
-import org.jaxen.JaxenRuntimeException;
import org.jaxen.UnresolvableException;
-import org.jaxen.UnsupportedAxisException;
import org.jaxen.XPathFunctionContext;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.ModuleImport;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.util.RegexUtils;
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
/**
* A {@link FunctionContext} which contains also YANG-specific functions current(), re-match(), deref(),
Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
- final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
- final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
- currentNodeContext);
+ final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(currentNodeContext);
final TypeDefinition<?> nodeType = correspondingSchemaNode.getType();
if (!(nodeType instanceof BitsTypeDefinition)) {
Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
- final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
- final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
- currentNodeContext);
+ final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(currentNodeContext);
final Object nodeValue = currentNodeContext.getNode().getValue();
final TypeDefinition<?> type = correspondingSchemaNode.getType();
}
if (type instanceof LeafrefTypeDefinition) {
final RevisionAwareXPath xpath = ((LeafrefTypeDefinition) type).getPathStatement();
- return getNodeReferencedByLeafref(xpath, currentNodeContext, schemaContext, correspondingSchemaNode,
- nodeValue);
+ return getNodeReferencedByLeafref(xpath, currentNodeContext, getSchemaContext(currentNodeContext),
+ correspondingSchemaNode, nodeValue);
}
return null;
}
// derived-from(node-set nodes, string identity) function as per https://tools.ietf.org/html/rfc7950#section-10.4.1
private static boolean derivedFrom(final Context context, final List<?> args) throws FunctionCallException {
- final Entry<IdentitySchemaNode, IdentitySchemaNode> ids = commonDerivedFrom("derived-from", context, args);
+ final Entry<IdentitySchemaNode, IdentitySchemaNode> ids = commonDerivedFrom("derived-from", context, args);
return ids != null && isAncestorOf(ids.getKey(), ids.getValue());
}
Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
- final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
- final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
- currentNodeContext);
+ final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(currentNodeContext);
+ final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
return correspondingSchemaNode.getType() instanceof IdentityrefTypeDefinition
&& currentNodeContext.getNode().getValue() instanceof QName ? new SimpleImmutableEntry<>(
getIdentitySchemaNodeFromString((String) args.get(0), schemaContext, correspondingSchemaNode),
Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
- final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
- final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
- currentNodeContext);
+ final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(currentNodeContext);
final TypeDefinition<?> nodeType = correspondingSchemaNode.getType();
if (!(nodeType instanceof EnumTypeDefinition)) {
private static NormalizedNode<?, ?> getNodeReferencedByInstanceIdentifier(final YangInstanceIdentifier path,
final NormalizedNodeContext currentNodeContext) {
final NormalizedNodeNavigator navigator = (NormalizedNodeNavigator) currentNodeContext.getNavigator();
- final NormalizedNode<?, ?> rootNode = navigator.getRootNode();
+ final NormalizedNode<?, ?> rootNode = navigator.getDocument().getRootNode();
final List<PathArgument> pathArguments = path.getPathArguments();
if (pathArguments.get(0).getNodeType().equals(rootNode.getNodeType())) {
final List<PathArgument> relPath = pathArguments.subList(1, pathArguments.size());
xpath.toString(), schemaContext, correspondingSchemaNode, currentNodeContext);
final List<PathArgument> pathArguments = builder.build();
final NormalizedNodeNavigator navigator = (NormalizedNodeNavigator) currentNodeContext.getNavigator();
- final NormalizedNode<?, ?> rootNode = navigator.getRootNode();
+ final NormalizedNode<?, ?> rootNode = navigator.getDocument().getRootNode();
if (pathArguments.get(0).getNodeType().equals(rootNode.getNodeType())) {
final List<PathArgument> relPath = pathArguments.subList(1, pathArguments.size());
final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(rootNode, relPath);
return ((NormalizedNodeContextSupport) contextSupport).getSchemaContext();
}
- private static TypedDataSchemaNode getCorrespondingTypedSchemaNode(final SchemaContext schemaContext,
- final NormalizedNodeContext currentNodeContext) {
- Iterator<NormalizedNodeContext> ancestorOrSelfAxisIterator;
- try {
- ancestorOrSelfAxisIterator = currentNodeContext.getContextSupport().getNavigator()
- .getAncestorOrSelfAxisIterator(currentNodeContext);
- } catch (UnsupportedAxisException ex) {
- throw new JaxenRuntimeException(ex);
- }
-
- final Deque<QName> schemaPathToCurrentNode = new ArrayDeque<>();
- while (ancestorOrSelfAxisIterator.hasNext()) {
- final NormalizedNode<?, ?> nextNode = ancestorOrSelfAxisIterator.next().getNode();
- if (!(nextNode instanceof MapNode) && !(nextNode instanceof LeafSetNode)
- && !(nextNode instanceof AugmentationNode)) {
- schemaPathToCurrentNode.addFirst(nextNode.getNodeType());
- }
- }
-
- final SchemaNode schemaNode = SchemaContextUtil.findNodeInSchemaContext(schemaContext, schemaPathToCurrentNode);
-
- Preconditions.checkNotNull(schemaNode, "Node %s does not have a corresponding SchemaNode in the SchemaContext.",
- currentNodeContext.getNode());
+ private static TypedDataSchemaNode getCorrespondingTypedSchemaNode(final NormalizedNodeContext currentNodeContext) {
+ final DataSchemaNode schemaNode = currentNodeContext.getSchema().getDataSchemaNode();
Preconditions.checkState(schemaNode instanceof TypedDataSchemaNode, "Node %s must be a leaf or a leaf-list.",
currentNodeContext.getNode());
return (TypedDataSchemaNode) schemaNode;