Speed up getModifiedChild() 56/21956/2
authorRobert Varga <rovarga@cisco.com>
Wed, 20 May 2015 19:44:29 +0000 (21:44 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Fri, 5 Jun 2015 12:59:24 +0000 (14:59 +0200)
As it turns out, the original implementation transformed all children
before performing a lookup. Methods involved in that conversion can be
easily applied to transform a single child, so address the FIXME by
first performing a lookup and then running transformation, if
appropriate.

Change-Id: I11a87a69ce3e8552926017c51db7d4899af74a2a
Signed-off-by: Robert Varga <rovarga@cisco.com>
(cherry picked from commit 73262077092195b800edbeb89f0eeb80006d621b)

yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractDataTreeCandidateNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractModifiedNodeBasedCandidateNode.java

index 64930c7e129b20b3adf3d3d4ca9f69827c8f1e71..4d67080a9870d2c57eb6792b6dd4afba675271e9 100644 (file)
@@ -22,25 +22,56 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
 
 abstract class AbstractDataTreeCandidateNode implements DataTreeCandidateNode {
-    private static final Function<NormalizedNode<?, ?>, DataTreeCandidateNode> TO_DELETED_NODES = new Function<NormalizedNode<?, ?>, DataTreeCandidateNode>() {
+    private static final Function<NormalizedNode<?, ?>, DataTreeCandidateNode> TO_DELETED_NODE = new Function<NormalizedNode<?, ?>, DataTreeCandidateNode>() {
         @Override
         public DataTreeCandidateNode apply(final NormalizedNode<?, ?> input) {
             return AbstractRecursiveCandidateNode.deleteNode(input);
         }
-    };    private static final Function<NormalizedNode<?, ?>, DataTreeCandidateNode> TO_WRITTEN_NODES = new Function<NormalizedNode<?, ?>, DataTreeCandidateNode>() {
+    };
+    private static final Function<NormalizedNode<?, ?>, DataTreeCandidateNode> TO_WRITTEN_NODE = new Function<NormalizedNode<?, ?>, DataTreeCandidateNode>() {
         @Override
         public DataTreeCandidateNode apply(final NormalizedNode<?, ?> input) {
             return AbstractRecursiveCandidateNode.writeNode(input);
         }
     };
 
+    private static Optional<NormalizedNode<?, ?>> getChild(final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> container, final PathArgument identifier) {
+        if (container != null) {
+            return container.getChild(identifier);
+        } else {
+            return Optional.absent();
+        }
+    }
+
+    static DataTreeCandidateNode deltaChild(
+            final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> oldData,
+            final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> newData, final PathArgument identifier) {
+
+        final Optional<NormalizedNode<?, ?>> maybeNewChild = getChild(newData, identifier);
+        final Optional<NormalizedNode<?, ?>> maybeOldChild = getChild(oldData, identifier);
+        if (maybeOldChild.isPresent()) {
+            final NormalizedNode<?, ?> oldChild = maybeOldChild.get();
+            if (maybeNewChild.isPresent()) {
+                return AbstractRecursiveCandidateNode.replaceNode(oldChild, maybeNewChild.get());
+            } else {
+                return TO_DELETED_NODE.apply(oldChild);
+            }
+        } else {
+            if (maybeNewChild.isPresent()) {
+                return TO_WRITTEN_NODE.apply(maybeNewChild.get());
+            } else {
+                return null;
+            }
+        }
+    }
+
     static Collection<DataTreeCandidateNode> deltaChildren(@Nullable final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> oldData,
             @Nullable final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> newData) {
         if (newData == null) {
-            return Collections2.transform(oldData.getValue(), TO_DELETED_NODES);
+            return Collections2.transform(oldData.getValue(), TO_DELETED_NODE);
         }
         if (oldData == null) {
-            return Collections2.transform(newData.getValue(), TO_WRITTEN_NODES);
+            return Collections2.transform(newData.getValue(), TO_WRITTEN_NODE);
         }
 
         // Create index for fast cross-references
index 76b3131b6b6518317523ea71d55ed9b67fe85c9d..25fb2df24078880b78bb1ad3f2ec3600899fad72 100644 (file)
@@ -23,7 +23,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 
 abstract class AbstractModifiedNodeBasedCandidateNode implements DataTreeCandidateNode {
 
-    private static final Function<NormalizedNode<?, ?>, DataTreeCandidateNode> TO_UNMODIFIED_NODES = new Function<NormalizedNode<?, ?>, DataTreeCandidateNode>() {
+    private static final Function<NormalizedNode<?, ?>, DataTreeCandidateNode> TO_UNMODIFIED_NODE = new Function<NormalizedNode<?, ?>, DataTreeCandidateNode>() {
         @Override
         public DataTreeCandidateNode apply(final NormalizedNode<?, ?> input) {
             return AbstractRecursiveCandidateNode.unmodifiedNode(input);
@@ -95,7 +95,7 @@ abstract class AbstractModifiedNodeBasedCandidateNode implements DataTreeCandida
             // Unmodified node, but we still need to resolve potential children. canHaveChildren returns
             // false if both arguments are null.
             if (canHaveChildren(oldMeta, newMeta)) {
-                return Collections2.transform(getContainer(newMeta != null ? newMeta : oldMeta).getValue(), TO_UNMODIFIED_NODES);
+                return Collections2.transform(getContainer(newMeta != null ? newMeta : oldMeta).getValue(), TO_UNMODIFIED_NODE);
             } else {
                 return Collections.emptyList();
             }
@@ -145,17 +145,24 @@ abstract class AbstractModifiedNodeBasedCandidateNode implements DataTreeCandida
                 return childNode(childMod.get());
             }
             return null;
-        case DELETE:
         case UNMODIFIED:
-        case WRITE:
-            // FIXME: this is a linear walk. We need a Map of these in order to
-            //        do something like getChildMap().get(identifier);
-            for (DataTreeCandidateNode c : getChildNodes()) {
-                if (identifier.equals(c.getIdentifier())) {
-                    return c;
+            if (canHaveChildren(oldMeta, newMeta)) {
+                final Optional<NormalizedNode<?, ?>> maybeChild = getContainer(newMeta != null ? newMeta : oldMeta).getChild(identifier);
+                if (maybeChild.isPresent()) {
+                    return TO_UNMODIFIED_NODE.apply(maybeChild.get());
+                } else {
+                    return null;
                 }
+            } else {
+                return null;
+            }
+        case DELETE:
+        case WRITE:
+            if (canHaveChildren(oldMeta, newMeta)) {
+                return AbstractDataTreeCandidateNode.deltaChild(getContainer(oldMeta), getContainer(newMeta), identifier);
+            } else {
+                return null;
             }
-            return null;
         default:
             throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
         }