BUG-1275: do not copy arrays in XmlDocumentUtilsforEachChild()
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / NodeFactory.java
index 5e944577628fc778b809221817b5e0405e203f48..735ff27c44957cfd154fc49a30c421fcd5d8e7e2 100644 (file)
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.yangtools.yang.data.impl;\r
-\r
-import java.util.AbstractMap.SimpleEntry;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Stack;\r
-\r
-import org.opendaylight.yangtools.yang.common.QName;\r
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;\r
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;\r
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;\r
-import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;\r
-import org.opendaylight.yangtools.yang.data.api.Node;\r
-import org.opendaylight.yangtools.yang.data.api.NodeModification;\r
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;\r
-\r
-/**\r
- * @author michal.rehak\r
- *\r
- */\r
-public abstract class NodeFactory {\r
-\r
-    /**\r
-     * @param qName\r
-     * @param parent\r
-     * @param value\r
-     * @return simple node modification, based on given qname, value and parent\r
-     */\r
-    public static <T> SimpleNode<T> createImmutableSimpleNode(QName qName,\r
-            CompositeNode parent, T value) {\r
-        return createImmutableSimpleNode(qName, parent, value, null);\r
-    }\r
-\r
-    /**\r
-     * @param qName\r
-     * @param parent\r
-     * @param value\r
-     * @param modifyAction\r
-     * @param original originating node, if available\r
-     * @return simple node modification, based on given qname, value and parent\r
-     */\r
-    public static <T> MutableSimpleNode<T> createMutableSimpleNode(QName qName,\r
-            CompositeNode parent, Object value, ModifyAction modifyAction, SimpleNode<T> original) {\r
-        @SuppressWarnings("unchecked")\r
-        MutableSimpleNodeTOImpl<T> simpleNodeTOImpl =\r
-                new MutableSimpleNodeTOImpl<T>(qName, parent, (T) value, modifyAction);\r
-        simpleNodeTOImpl.setOriginal(original);\r
-        return simpleNodeTOImpl;\r
-    }\r
-\r
-    /**\r
-     * @param qName\r
-     * @param parent\r
-     * @param value\r
-     * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
-     */\r
-    public static CompositeNode createImmutableCompositeNode(QName qName,\r
-            CompositeNode parent, List<Node<?>> value) {\r
-        return createImmutableCompositeNode(qName, parent, value, null);\r
-    }\r
-\r
-    /**\r
-     * @param qName\r
-     * @param parent\r
-     * @param valueArg\r
-     * @param modifyAction\r
-     * @param original originating node, if available\r
-     * @return composite node modification, based on given qName, value (children), parent and modifyAction\r
-     */\r
-    public static MutableCompositeNode createMutableCompositeNode(QName qName,\r
-            CompositeNode parent, List<Node<?>> valueArg, ModifyAction modifyAction, CompositeNode original) {\r
-        List<Node<?>> value = valueArg;\r
-        if (value == null) {\r
-            value = new ArrayList<>();\r
-        }\r
-        MutableCompositeNodeTOImpl compositeNodeTOImpl =\r
-                new MutableCompositeNodeTOImpl(qName, parent, value, modifyAction);\r
-        compositeNodeTOImpl.setOriginal(original);\r
-        return compositeNodeTOImpl;\r
-    }\r
-\r
-\r
-    /**\r
-     * @param qName\r
-     * @param parent\r
-     * @param value\r
-     * @param modifyAction\r
-     * @return simple node modification, based on given qname, value, parent and modifyAction\r
-     */\r
-    public static <T> SimpleNode<T> createImmutableSimpleNode(QName qName,\r
-            CompositeNode parent, T value, ModifyAction modifyAction) {\r
-        SimpleNodeTOImpl<T> simpleNodeModTOImpl =\r
-                new SimpleNodeTOImpl<T>(qName, parent, value, modifyAction);\r
-        return simpleNodeModTOImpl;\r
-    }\r
-\r
-    /**\r
-     * @param qName\r
-     * @param parent\r
-     * @param value\r
-     * @param modifyAction\r
-     * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
-     */\r
-    public static CompositeNode createImmutableCompositeNode(QName qName,\r
-            CompositeNode parent, List<Node<?>> value, ModifyAction modifyAction) {\r
-        CompositeNodeTOImpl compositeNodeModTOImpl =\r
-                new CompositeNodeTOImpl(qName, parent, value, modifyAction);\r
-        return compositeNodeModTOImpl;\r
-    }\r
-\r
-    /**\r
-     * @param node\r
-     * @return copy of given node, parent and value are the same, but parent\r
-     * has no reference to this copy\r
-     */\r
-    public static <T> SimpleNode<T> copyNode(SimpleNode<T> node) {\r
-        SimpleNode<T> twinNode = createImmutableSimpleNode(\r
-                    node.getNodeType(), node.getParent(), node.getValue());\r
-        return twinNode;\r
-    }\r
-\r
-    /**\r
-     * @param node\r
-     * @return copy of given node, parent and value are the same, but parent\r
-     * has no reference to this copy\r
-     */\r
-    public static <T> MutableSimpleNode<T> copyNodeAsMutable(SimpleNode<T> node) {\r
-        MutableSimpleNode<T> twinNode = createMutableSimpleNode(\r
-                    node.getNodeType(), node.getParent(), node.getValue(),\r
-                    node.getModificationAction(), null);\r
-        return twinNode;\r
-    }\r
-\r
-    /**\r
-     * @param node\r
-     * @param children\r
-     * @return copy of given node, parent and children are the same, but parent and children\r
-     * have no reference to this copy\r
-     */\r
-    public static CompositeNode copyNode(CompositeNode node, Node<?>... children) {\r
-        CompositeNode twinNode = createImmutableCompositeNode(\r
-                node.getNodeType(), node.getParent(), Arrays.asList(children), node.getModificationAction());\r
-        return twinNode;\r
-    }\r
-\r
-    /**\r
-     * @param node\r
-     * @return copy of given node, parent and children are the same, but parent and children\r
-     * have no reference to this copy\r
-     */\r
-    public static CompositeNode copyNode(CompositeNode node) {\r
-       return copyNode(node, node.getChildren().toArray(new Node<?>[0]));\r
-    }\r
-\r
-    /**\r
-     * @param node root of original tree\r
-     * @param originalToCopyArg (optional) empty map, where binding between original and copy\r
-     * will be stored\r
-     * @return copy of given node and all subnodes recursively\r
-     */\r
-    public static MutableCompositeNode copyDeepAsMutable(CompositeNode node,\r
-            Map<Node<?>, Node<?>> originalToCopyArg) {\r
-\r
-        Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;\r
-        if (originalToCopy == null) {\r
-            originalToCopy = new HashMap<>();\r
-        }\r
-\r
-        MutableCompositeNode mutableRoot = createMutableCompositeNode(node.getNodeType(), null, null,\r
-                node.getModificationAction(), null);\r
-        Stack<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new Stack<>();\r
-        jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));\r
-        originalToCopy.put(node, mutableRoot);\r
-\r
-        while (!jobQueue.isEmpty()) {\r
-            SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();\r
-            CompositeNode originalNode = job.getKey();\r
-            MutableCompositeNode mutableNode = job.getValue();\r
-            mutableNode.setValue(new ArrayList<Node<?>>());\r
-\r
-            for (Node<?> child : originalNode.getChildren()) {\r
-                Node<?> mutableAscendant = null;\r
-                if (child instanceof CompositeNode) {\r
-                    MutableCompositeNode newMutable =\r
-                            createMutableCompositeNode(child.getNodeType(), mutableNode, null,\r
-                                    ((NodeModification) child).getModificationAction(), null);\r
-                    jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(\r
-                            (CompositeNode) child, newMutable));\r
-                    mutableAscendant = newMutable;\r
-                } else if (child instanceof SimpleNode<?>) {\r
-                    mutableAscendant =\r
-                            createMutableSimpleNode(child.getNodeType(), mutableNode,\r
-                                    child.getValue(),\r
-                                    ((NodeModification) child).getModificationAction(), null);\r
-                } else {\r
-                    throw new IllegalStateException("Node class deep copy not supported: "\r
-                            +child.getClass().getName());\r
-                }\r
-\r
-                mutableNode.getChildren().add(mutableAscendant);\r
-                originalToCopy.put(child, mutableAscendant);\r
-            }\r
-            mutableNode.init();\r
-        }\r
-\r
-        return mutableRoot;\r
-    }\r
-\r
-    /**\r
-     * @param node root of original tree\r
-     * @param originalToCopyArg (optional) empty map, where binding between original and copy\r
-     * will be stored\r
-     * @return copy of given node and all subnodes recursively\r
-     */\r
-    public static CompositeNode copyDeepAsImmutable(CompositeNode node,\r
-            Map<Node<?>, Node<?>> originalToCopyArg) {\r
-        Stack<CompositeNode> jobQueue = new Stack<>();\r
-        jobQueue.push(node);\r
-\r
-        Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;\r
-        if (originalToCopy == null) {\r
-            originalToCopy = new HashMap<>();\r
-        }\r
-\r
-        while (!jobQueue.isEmpty()) {\r
-            CompositeNode jobNode = jobQueue.peek();\r
-            if (!originalToCopy.isEmpty()\r
-                    && originalToCopy.keySet().containsAll(jobNode.getChildren())) {\r
-                jobQueue.pop();\r
-                List<Node<?>> newChildren = NodeUtils.collectMapValues(jobNode.getChildren(), originalToCopy);\r
-                CompositeNode nodeCopy = createImmutableCompositeNode(jobNode.getNodeType(), null,\r
-                        newChildren, jobNode.getModificationAction());\r
-                NodeUtils.fixChildrenRelation(nodeCopy);\r
-                originalToCopy.put(jobNode, nodeCopy);\r
-            } else {\r
-                for (Node<?> child : jobNode.getChildren()) {\r
-                    if (child instanceof SimpleNode<?>) {\r
-                        originalToCopy.put(child, createImmutableSimpleNode(\r
-                                child.getNodeType(), null, child.getValue(),\r
-                                ((NodeModification) child).getModificationAction()));\r
-                    } else if (child instanceof CompositeNode) {\r
-                        jobQueue.push((CompositeNode) child);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        return (CompositeNode) originalToCopy.get(node);\r
-    }\r
-\r
-}\r
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.NodeModification;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+/**
+ * @author michal.rehak
+ *
+ */
+public abstract class NodeFactory {
+
+    /**
+     * @param qName
+     * @param parent
+     * @param value
+     * @return simple node modification, based on given qname, value and parent
+     */
+    public static <T> SimpleNode<T> createImmutableSimpleNode(final QName qName,
+            final CompositeNode parent, final T value) {
+        return createImmutableSimpleNode(qName, parent, value, null);
+    }
+
+    /**
+     * @param qName
+     * @param parent
+     * @param value
+     * @param modifyAction
+     * @param original originating node, if available
+     * @return simple node modification, based on given qname, value and parent
+     */
+    public static <T> MutableSimpleNode<T> createMutableSimpleNode(final QName qName,
+            final CompositeNode parent, final Object value, final ModifyAction modifyAction, final SimpleNode<T> original) {
+        @SuppressWarnings("unchecked")
+        MutableSimpleNodeTOImpl<T> simpleNodeTOImpl =
+                new MutableSimpleNodeTOImpl<T>(qName, parent, (T) value, modifyAction);
+        simpleNodeTOImpl.setOriginal(original);
+        return simpleNodeTOImpl;
+    }
+
+    /**
+     * @param qName
+     * @param parent
+     * @param value
+     * @return composite node modification, based on given qname, value (children), parent and modifyAction
+     */
+    public static CompositeNode createImmutableCompositeNode(final QName qName,
+            final CompositeNode parent, final List<Node<?>> value) {
+        return createImmutableCompositeNode(qName, parent, value, null);
+    }
+
+    /**
+     * @param qName
+     * @param parent
+     * @param valueArg
+     * @param modifyAction
+     * @param original originating node, if available
+     * @return composite node modification, based on given qName, value (children), parent and modifyAction
+     */
+    public static MutableCompositeNode createMutableCompositeNode(final QName qName,
+            final CompositeNode parent, final List<Node<?>> valueArg, final ModifyAction modifyAction, final CompositeNode original) {
+        List<Node<?>> value = valueArg;
+        if (value == null) {
+            value = new ArrayList<>();
+        }
+        MutableCompositeNodeTOImpl compositeNodeTOImpl =
+                new MutableCompositeNodeTOImpl(qName, parent, value, modifyAction);
+        compositeNodeTOImpl.setOriginal(original);
+        return compositeNodeTOImpl;
+    }
+
+
+    /**
+     * @param qName
+     * @param parent
+     * @param value
+     * @param modifyAction
+     * @return simple node modification, based on given qname, value, parent and modifyAction
+     */
+    public static <T> SimpleNode<T> createImmutableSimpleNode(final QName qName,
+            final CompositeNode parent, final T value, final ModifyAction modifyAction) {
+        SimpleNodeTOImpl<T> simpleNodeModTOImpl =
+                new SimpleNodeTOImpl<T>(qName, parent, value, modifyAction);
+        return simpleNodeModTOImpl;
+    }
+
+    /**
+     * @param qName
+     * @param parent
+     * @param value
+     * @param modifyAction
+     * @return composite node modification, based on given qname, value (children), parent and modifyAction
+     */
+    public static CompositeNode createImmutableCompositeNode(final QName qName,
+            final CompositeNode parent, final List<Node<?>> value, final ModifyAction modifyAction) {
+        CompositeNodeTOImpl compositeNodeModTOImpl =
+                new CompositeNodeTOImpl(qName, parent, value, modifyAction);
+        return compositeNodeModTOImpl;
+    }
+
+    /**
+     * @param node
+     * @return copy of given node, parent and value are the same, but parent
+     * has no reference to this copy
+     */
+    public static <T> SimpleNode<T> copyNode(final SimpleNode<T> node) {
+        SimpleNode<T> twinNode = createImmutableSimpleNode(
+                    node.getNodeType(), node.getParent(), node.getValue());
+        return twinNode;
+    }
+
+    /**
+     * @param node
+     * @return copy of given node, parent and value are the same, but parent
+     * has no reference to this copy
+     */
+    public static <T> MutableSimpleNode<T> copyNodeAsMutable(final SimpleNode<T> node) {
+        MutableSimpleNode<T> twinNode = createMutableSimpleNode(
+                    node.getNodeType(), node.getParent(), node.getValue(),
+                    node.getModificationAction(), null);
+        return twinNode;
+    }
+
+    /**
+     * @param node
+     * @param children
+     * @return copy of given node, parent and children are the same, but parent and children
+     * have no reference to this copy
+     */
+    public static CompositeNode copyNode(final CompositeNode node, final Node<?>... children) {
+        CompositeNode twinNode = createImmutableCompositeNode(
+                node.getNodeType(), node.getParent(), Arrays.asList(children), node.getModificationAction());
+        return twinNode;
+    }
+
+    /**
+     * @param node
+     * @return copy of given node, parent and children are the same, but parent and children
+     * have no reference to this copy
+     */
+    public static CompositeNode copyNode(final CompositeNode node) {
+       return copyNode(node, node.getValue().toArray(new Node<?>[0]));
+    }
+
+    /**
+     * @param node root of original tree
+     * @param originalToCopyArg (optional) empty map, where binding between original and copy
+     * will be stored
+     * @return copy of given node and all subnodes recursively
+     */
+    public static MutableCompositeNode copyDeepAsMutable(final CompositeNode node,
+            final Map<Node<?>, Node<?>> originalToCopyArg) {
+
+        Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
+        if (originalToCopy == null) {
+            originalToCopy = new HashMap<>();
+        }
+
+        MutableCompositeNode mutableRoot = createMutableCompositeNode(node.getNodeType(), null, null,
+                node.getModificationAction(), null);
+        Stack<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new Stack<>();
+        jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));
+        originalToCopy.put(node, mutableRoot);
+
+        while (!jobQueue.isEmpty()) {
+            SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();
+            CompositeNode originalNode = job.getKey();
+            MutableCompositeNode mutableNode = job.getValue();
+            mutableNode.setValue(new ArrayList<Node<?>>());
+
+            for (Node<?> child : originalNode.getValue()) {
+                Node<?> mutableAscendant = null;
+                if (child instanceof CompositeNode) {
+                    MutableCompositeNode newMutable =
+                            createMutableCompositeNode(child.getNodeType(), mutableNode, null,
+                                    ((NodeModification) child).getModificationAction(), null);
+                    jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(
+                            (CompositeNode) child, newMutable));
+                    mutableAscendant = newMutable;
+                } else if (child instanceof SimpleNode<?>) {
+                    mutableAscendant =
+                            createMutableSimpleNode(child.getNodeType(), mutableNode,
+                                    child.getValue(),
+                                    ((NodeModification) child).getModificationAction(), null);
+                } else {
+                    throw new IllegalStateException("Node class deep copy not supported: "
+                            +child.getClass().getName());
+                }
+
+                mutableNode.getValue().add(mutableAscendant);
+                originalToCopy.put(child, mutableAscendant);
+            }
+            mutableNode.init();
+        }
+
+        return mutableRoot;
+    }
+
+    /**
+     * @param node root of original tree
+     * @param originalToCopyArg (optional) empty map, where binding between original and copy
+     * will be stored
+     * @return copy of given node and all subnodes recursively
+     */
+    public static CompositeNode copyDeepAsImmutable(final CompositeNode node,
+            final Map<Node<?>, Node<?>> originalToCopyArg) {
+        Stack<CompositeNode> jobQueue = new Stack<>();
+        jobQueue.push(node);
+
+        Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
+        if (originalToCopy == null) {
+            originalToCopy = new HashMap<>();
+        }
+
+        while (!jobQueue.isEmpty()) {
+            CompositeNode jobNode = jobQueue.peek();
+            if (!originalToCopy.isEmpty()
+                    && originalToCopy.keySet().containsAll(jobNode.getValue())) {
+                jobQueue.pop();
+                List<Node<?>> newChildren = NodeUtils.collectMapValues(jobNode.getValue(), originalToCopy);
+                CompositeNode nodeCopy = createImmutableCompositeNode(jobNode.getNodeType(), null,
+                        newChildren, jobNode.getModificationAction());
+                NodeUtils.fixChildrenRelation(nodeCopy);
+                originalToCopy.put(jobNode, nodeCopy);
+            } else {
+                for (Node<?> child : jobNode.getValue()) {
+                    if (child instanceof SimpleNode<?>) {
+                        originalToCopy.put(child, createImmutableSimpleNode(
+                                child.getNodeType(), null, child.getValue(),
+                                ((NodeModification) child).getModificationAction()));
+                    } else if (child instanceof CompositeNode) {
+                        jobQueue.push((CompositeNode) child);
+                    }
+                }
+            }
+        }
+
+        return (CompositeNode) originalToCopy.get(node);
+    }
+
+}