Move search methods to NormalizedNodeContext 89/71789/14
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 30 Apr 2018 19:22:19 +0000 (21:22 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 2 Aug 2018 09:59:10 +0000 (09:59 +0000)
When we know we have a NormalizedNodeContext we can forgo bouncing
through the navigator to get a target node context. This simplifies
things a bit when we want to implement more complex logic.

This is not exactly extensible way of operation, but we know we will
only be evaluating on our context.

Change-Id: Ib8bea239f3193c54d3eacab903c75f9d43aee4e2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/NormalizedNodeContext.java
yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/NormalizedNodeContextSupport.java
yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/NormalizedNodeNavigator.java

index 8b04b4355a6b4c4c0b86818509510161d4a04053..8f1101414fa40ca1309dc34749f3b7ae0b6e45a3 100644 (file)
@@ -8,16 +8,28 @@
 package org.opendaylight.yangtools.yang.data.jaxen;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Verify.verify;
 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 com.google.common.collect.Iterators;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
 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.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+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.util.DataSchemaContextNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -28,7 +40,7 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  * traversing upwards the NormalizedNode tree.
  */
 @NonNullByDefault
-final class NormalizedNodeContext extends Context implements Function<NormalizedNode<?, ?>, NormalizedNodeContext> {
+final class NormalizedNodeContext extends Context {
     private static final long serialVersionUID = 1L;
     private final @Nullable NormalizedNodeContext parent;
     private final DataSchemaContextNode<?> schema;
@@ -65,8 +77,7 @@ final class NormalizedNodeContext extends Context implements Function<Normalized
         return schema;
     }
 
-    @Override
-    public NormalizedNodeContext apply(final NormalizedNode<?, ?> input) {
+    NormalizedNodeContext createChild(final NormalizedNode<?, ?> input) {
         DataSchemaContextNode<?> childSchema = schema.getChild(input.getIdentifier());
         if (childSchema == null) {
             /* This feels very much like a hack: but solves lookup of child nodes with predicates.
@@ -86,4 +97,63 @@ final class NormalizedNodeContext extends Context implements Function<Normalized
         checkArgument(childSchema != null, "Failed to find schema for child %s", input);
         return new NormalizedNodeContext(getContextSupport(), childSchema, input, this);
     }
+
+    Optional<NormalizedNodeContext> findChild(final PathArgument arg) {
+        return node instanceof DataContainerNode ? ((DataContainerNode<?>)node).getChild(arg).map(this::createChild)
+                : Optional.empty();
+    }
+
+    Optional<NormalizedNodeContext> findDescendant(final YangInstanceIdentifier path) {
+        if (path.isEmpty()) {
+            return Optional.of(this);
+        }
+
+        NormalizedNodeContext ctxWalk = this;
+        NormalizedNode<?, ?> dataWalk = node;
+        for (PathArgument arg : path.getPathArguments()) {
+            checkArgument(dataWalk instanceof DataContainerNode, "Path %s refers beyond node %s", path, dataWalk);
+
+            final Optional<DataContainerChild<? extends @Nullable PathArgument, ?>> optChild =
+                    ((DataContainerNode)dataWalk).getChild(arg);
+            if (!optChild.isPresent()) {
+                return Optional.empty();
+            }
+
+            dataWalk = optChild.get();
+            ctxWalk = createChild(dataWalk);
+        }
+
+        return Optional.of(ctxWalk.createChild(dataWalk));
+    }
+
+    Iterator<NormalizedNodeContext> iterateChildren(final DataContainerNode<?> data) {
+        return Iterators.transform(((DataContainerNode<?>) node).getValue().iterator(), this::createChild);
+    }
+
+    @Nullable Iterator<NormalizedNodeContext> iterateChildrenNamed(final DataContainerNode<?> data, final QName qname) {
+        final NodeIdentifier arg = new NodeIdentifier(qname);
+        final Optional<DataContainerChild<? extends @Nullable PathArgument, ?>> maybeChild = data.getChild(arg);
+        if (!maybeChild.isPresent()) {
+            return null;
+        }
+
+        final NormalizedNode<?, ?> child = maybeChild.get();
+        final Collection<? extends NormalizedNode<?, ?>> collection;
+
+        // The child may be a structural node
+        if (child instanceof MapNode) {
+            collection = ((MapNode)child).getValue();
+        } else if (child instanceof LeafSetNode) {
+            collection = ((LeafSetNode<?>)child).getValue();
+        } else {
+            return Iterators.singletonIterator(createChild(child));
+        }
+
+        return Iterators.transform(collection.iterator(), this::createChild);
+    }
+
+    static NormalizedNodeContext cast(@Nullable Context context) {
+        verify(context instanceof NormalizedNodeContext);
+        return (@NonNull NormalizedNodeContext) context;
+    }
 }
index 67c7376b54cc1ebcf044ff54be0520f6a6fa88f1..8edb5170c61ebdf5c023d74231413c207af5e95d 100644 (file)
@@ -43,7 +43,7 @@ final class NormalizedNodeContextSupport extends ContextSupport {
         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 = result.apply(node.get());
+            result = result.createChild(node.get());
         }
         return result;
     }
index 2781edbdf9f17d867f188e0b28fa6f5290a9c583..714d6b96d49789da5d8bb7df950dd7f7205672ee 100644 (file)
@@ -15,12 +15,10 @@ import com.google.common.collect.Iterators;
 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 org.jaxen.DefaultNavigator;
 import org.jaxen.NamedAccessNavigator;
@@ -31,12 +29,9 @@ import org.jaxen.saxpath.SAXPathException;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 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;
 
 /**
@@ -216,11 +211,7 @@ final class NormalizedNodeNavigator extends DefaultNavigator implements NamedAcc
     public Iterator<NormalizedNodeContext> getChildAxisIterator(final Object contextNode) {
         final NormalizedNodeContext ctx = cast(contextNode);
         final NormalizedNode<?, ?> node = ctx.getNode();
-        if (node instanceof DataContainerNode) {
-            return Iterators.transform(((DataContainerNode<?>) node).getValue().iterator(), ctx);
-        }
-
-        return null;
+        return node instanceof DataContainerNode ? ctx.iterateChildren((DataContainerNode<?>) node) : null;
     }
 
     @Override
@@ -228,30 +219,9 @@ final class NormalizedNodeNavigator extends DefaultNavigator implements NamedAcc
             final String namespacePrefix, final String namespaceURI) {
         final NormalizedNodeContext ctx = cast(contextNode);
         final NormalizedNode<?, ?> node = ctx.getNode();
-        if (!(node instanceof DataContainerNode)) {
-            return null;
-        }
-
-        final QName qname = resolveQName(node, namespacePrefix, localName);
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        final Optional<NormalizedNode<?, ?>> maybeChild = ((DataContainerNode)node).getChild(new NodeIdentifier(qname));
-        if (!maybeChild.isPresent()) {
-            return null;
-        }
-
-        final NormalizedNode<?, ?> child = maybeChild.get();
-        final Collection<? extends NormalizedNode<?, ?>> collection;
-
-        // The child may be a structural node
-        if (child instanceof MapNode) {
-            collection = ((MapNode)child).getValue();
-        } else if (child instanceof LeafSetNode) {
-            collection = ((LeafSetNode<?>)child).getValue();
-        } else {
-            return Iterators.singletonIterator(ctx.apply(child));
-        }
-
-        return Iterators.transform(collection.iterator(), ctx);
+        return node instanceof DataContainerNode
+                ? ctx.iterateChildrenNamed((DataContainerNode<?>)node, resolveQName(node, namespacePrefix, localName))
+                        : null;
     }
 
     @Override