Introduce YangInstanceIdentifier.getAncestor() 92/26892/4
authorRobert Varga <rovarga@cisco.com>
Sun, 13 Sep 2015 16:57:58 +0000 (18:57 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 14 Sep 2015 16:45:05 +0000 (16:45 +0000)
We have callsites which want to create a truncated
YangInstanceIdentifier and open-code instantiation. This is not
efficient, as those users do not have an understanding of the
implementation details, thus they have to resort to Iterables.limit()
and similar -- which forces copying of path arguments and untrusted
instantiation of YangInstanceIdentifier.

This patch introduces getAncestor(int), which performs this operation
with explicit knowledge of a particular implementation, resulting in
as much reuse as possible: for FixedYangInstanceIdentifier it uses a
subList(), for StackedYangInstanceIdentifier we return either a
direct/indirect parent, or use FixedYangInstanceIdentifier's version.

Change-Id: I355200199ac9791bb6d027fcdfa2a1162208a627
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/FixedYangInstanceIdentifier.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/StackedYangInstanceIdentifier.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java

index df9c0842f03130f29e51129f960a812d6f69e23e..47561ffcb4c4355ec9e50e18ae72a8136e816493 100644 (file)
@@ -53,6 +53,21 @@ final class FixedYangInstanceIdentifier extends YangInstanceIdentifier implement
         return ret;
     }
 
+    @Override
+    public YangInstanceIdentifier getAncestor(final int depth) {
+        Preconditions.checkArgument(depth >= 0, "Negative depth is not allowed");
+        Preconditions.checkArgument(depth <= path.size(), "Depth %s exceeds maximum depth %s", depth, path.size());
+
+        if (depth == path.size()) {
+            return this;
+        }
+        if (depth == path.size() - 1) {
+            // Use the parent cache
+            return getParent();
+        }
+        return YangInstanceIdentifier.create(path.subList(0, depth));
+    }
+
     @Override
     public List<PathArgument> getPathArguments() {
         return path;
index 6b1b58a38a2d4b86721bce366a19f8cdbcb70148..3b6a634b6f9efdfeed64a4884202e72f0fcc5d5b 100644 (file)
@@ -56,6 +56,38 @@ final class StackedYangInstanceIdentifier extends YangInstanceIdentifier impleme
         return parent;
     }
 
+    @Override
+    public YangInstanceIdentifier getAncestor(final int depth) {
+        Preconditions.checkArgument(depth >= 0, "Steps cannot be negative");
+
+        // Calculate how far up our FixedYangInstanceIdentifier ancestor is
+        int stackedDepth = 1;
+        YangInstanceIdentifier wlk = getParent();
+        while (wlk instanceof StackedYangInstanceIdentifier) {
+            wlk = wlk.getParent();
+            stackedDepth++;
+        }
+
+        // Guaranteed to come from FixedYangInstanceIdentifier
+        final int fixedDepth = wlk.getPathArguments().size();
+        if (fixedDepth >= depth) {
+            return wlk.getAncestor(depth);
+        }
+
+        // Calculate our depth and check argument
+        final int ourDepth = stackedDepth + fixedDepth;
+        Preconditions.checkArgument(depth <= ourDepth, "Depth %s exceeds maximum depth %s", depth, ourDepth);
+
+        // Requested depth is covered by the stack, traverse up for specified number of steps
+        final int toWalk = ourDepth - depth;
+        YangInstanceIdentifier result = this;
+        for (int i = 0; i < toWalk; ++i) {
+            result = result.getParent();
+        }
+
+        return result;
+    }
+
     @Override
     public boolean isEmpty() {
         return false;
index 849f7f08432c6772d5f361419f0e141379f1c52a..781891e2bb3256d75ba49d4b3ee9cdbc36a543c4 100644 (file)
@@ -114,10 +114,19 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
      * Return the conceptual parent {@link YangInstanceIdentifier}, which has
      * one item less in {@link #getPathArguments()}.
      *
-     * @return Parent {@link YangInstanceIdentifier}, or null if this is object is {@link #EMPTY}.
+     * @return Parent {@link YangInstanceIdentifier}, or null if this object is {@link #EMPTY}.
      */
     @Nullable public abstract YangInstanceIdentifier getParent();
 
+    /**
+     * Return the ancestor {@link YangInstanceIdentifier} with a particular depth, e.g. number of path arguments.
+     *
+     * @param depth Ancestor depth
+     * @return Ancestor {@link YangInstanceIdentifier}
+     * @throws IllegalArgumentException if the specified depth is negative or is greater than the depth of this object.
+     */
+   @Nonnull public abstract YangInstanceIdentifier getAncestor(int depth);
+
     /**
      * Returns an ordered iteration of path arguments.
      *