2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.impl;
10 import java.util.AbstractMap.SimpleEntry;
11 import java.util.ArrayDeque;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Deque;
15 import java.util.HashMap;
16 import java.util.List;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
21 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
22 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
23 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
24 import org.opendaylight.yangtools.yang.data.api.Node;
25 import org.opendaylight.yangtools.yang.data.api.NodeModification;
26 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
29 * @author michal.rehak
32 public abstract class NodeFactory {
38 * @return simple node modification, based on given qname, value and parent
40 public static <T> SimpleNode<T> createImmutableSimpleNode(final QName qName,
41 final CompositeNode parent, final T value) {
42 return createImmutableSimpleNode(qName, parent, value, null);
50 * @param original originating node, if available
51 * @return simple node modification, based on given qname, value and parent
53 public static <T> MutableSimpleNode<T> createMutableSimpleNode(final QName qName,
54 final CompositeNode parent, final Object value, final ModifyAction modifyAction, final SimpleNode<T> original) {
55 @SuppressWarnings("unchecked")
56 MutableSimpleNodeTOImpl<T> simpleNodeTOImpl = new MutableSimpleNodeTOImpl<>(qName, parent, (T) value, modifyAction);
57 simpleNodeTOImpl.setOriginal(original);
58 return simpleNodeTOImpl;
65 * @return composite node modification, based on given qname, value (children), parent and modifyAction
67 public static CompositeNode createImmutableCompositeNode(final QName qName,
68 final CompositeNode parent, final List<Node<?>> value) {
69 return createImmutableCompositeNode(qName, parent, value, null);
77 * @param original originating node, if available
78 * @return composite node modification, based on given qName, value (children), parent and modifyAction
80 public static MutableCompositeNode createMutableCompositeNode(final QName qName,
81 final CompositeNode parent, final List<Node<?>> valueArg, final ModifyAction modifyAction, final CompositeNode original) {
82 List<Node<?>> value = valueArg;
84 value = new ArrayList<>();
86 MutableCompositeNodeTOImpl compositeNodeTOImpl =
87 new MutableCompositeNodeTOImpl(qName, parent, value, modifyAction);
88 compositeNodeTOImpl.setOriginal(original);
89 return compositeNodeTOImpl;
98 * @return simple node modification, based on given qname, value, parent and modifyAction
100 public static <T> SimpleNode<T> createImmutableSimpleNode(final QName qName,
101 final CompositeNode parent, final T value, final ModifyAction modifyAction) {
102 SimpleNodeTOImpl<T> simpleNodeModTOImpl =
103 new SimpleNodeTOImpl<T>(qName, parent, value, modifyAction);
104 return simpleNodeModTOImpl;
111 * @param modifyAction
112 * @return composite node modification, based on given qname, value (children), parent and modifyAction
114 public static CompositeNode createImmutableCompositeNode(final QName qName,
115 final CompositeNode parent, final List<Node<?>> value, final ModifyAction modifyAction) {
116 return new CompositeNodeTOImpl(qName, parent, value, modifyAction);
121 * @return copy of given node, parent and value are the same, but parent
122 * has no reference to this copy
124 public static <T> SimpleNode<T> copyNode(final SimpleNode<T> node) {
125 return createImmutableSimpleNode(node.getNodeType(), node.getParent(), node.getValue());
130 * @return copy of given node, parent and value are the same, but parent
131 * has no reference to this copy
133 public static <T> MutableSimpleNode<T> copyNodeAsMutable(final SimpleNode<T> node) {
134 return createMutableSimpleNode(
135 node.getNodeType(), node.getParent(), node.getValue(),
136 node.getModificationAction(), null);
142 * @return copy of given node, parent and children are the same, but parent and children
143 * have no reference to this copy
145 public static CompositeNode copyNode(final CompositeNode node, final Node<?>... children) {
146 CompositeNode twinNode = createImmutableCompositeNode(
147 node.getNodeType(), node.getParent(), Arrays.asList(children), node.getModificationAction());
153 * @return copy of given node, parent and children are the same, but parent and children
154 * have no reference to this copy
156 public static CompositeNode copyNode(final CompositeNode node) {
157 return copyNode(node, node.getValue().toArray(new Node<?>[0]));
161 * @param node root of original tree
162 * @param originalToCopyArg (optional) empty map, where binding between original and copy
164 * @return copy of given node and all subnodes recursively
166 public static MutableCompositeNode copyDeepAsMutable(final CompositeNode node,
167 final Map<Node<?>, Node<?>> originalToCopyArg) {
169 Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
170 if (originalToCopy == null) {
171 originalToCopy = new HashMap<>();
174 MutableCompositeNode mutableRoot = createMutableCompositeNode(node.getNodeType(), null, null,
175 node.getModificationAction(), null);
176 final Deque<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new ArrayDeque<>();
177 jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));
178 originalToCopy.put(node, mutableRoot);
180 while (!jobQueue.isEmpty()) {
181 SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();
182 CompositeNode originalNode = job.getKey();
183 MutableCompositeNode mutableNode = job.getValue();
184 mutableNode.setValue(new ArrayList<Node<?>>());
186 for (Node<?> child : originalNode.getValue()) {
187 Node<?> mutableAscendant = null;
188 if (child instanceof CompositeNode) {
189 MutableCompositeNode newMutable =
190 createMutableCompositeNode(child.getNodeType(), mutableNode, null,
191 ((NodeModification) child).getModificationAction(), null);
192 jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(
193 (CompositeNode) child, newMutable));
194 mutableAscendant = newMutable;
195 } else if (child instanceof SimpleNode<?>) {
197 createMutableSimpleNode(child.getNodeType(), mutableNode,
199 ((NodeModification) child).getModificationAction(), null);
201 throw new IllegalStateException("Node class deep copy not supported: "
202 +child.getClass().getName());
205 mutableNode.getValue().add(mutableAscendant);
206 originalToCopy.put(child, mutableAscendant);
215 * @param node root of original tree
216 * @param originalToCopyArg (optional) empty map, where binding between original and copy
218 * @return copy of given node and all subnodes recursively
220 public static CompositeNode copyDeepAsImmutable(final CompositeNode node,
221 final Map<Node<?>, Node<?>> originalToCopyArg) {
222 final Deque<CompositeNode> jobQueue = new ArrayDeque<>();
225 Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
226 if (originalToCopy == null) {
227 originalToCopy = new HashMap<>();
230 while (!jobQueue.isEmpty()) {
231 CompositeNode jobNode = jobQueue.peek();
232 if (!originalToCopy.isEmpty()
233 && originalToCopy.keySet().containsAll(jobNode.getValue())) {
235 List<Node<?>> newChildren = NodeUtils.collectMapValues(jobNode.getValue(), originalToCopy);
236 CompositeNode nodeCopy = createImmutableCompositeNode(jobNode.getNodeType(), null,
237 newChildren, jobNode.getModificationAction());
238 NodeUtils.fixChildrenRelation(nodeCopy);
239 originalToCopy.put(jobNode, nodeCopy);
241 for (Node<?> child : jobNode.getValue()) {
242 if (child instanceof SimpleNode<?>) {
243 originalToCopy.put(child, createImmutableSimpleNode(
244 child.getNodeType(), null, child.getValue(),
245 ((NodeModification) child).getModificationAction()));
246 } else if (child instanceof CompositeNode) {
247 jobQueue.push((CompositeNode) child);
253 return (CompositeNode) originalToCopy.get(node);