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.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashMap;
14 import java.util.List;
16 import java.util.Stack;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
20 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
21 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
22 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
23 import org.opendaylight.yangtools.yang.data.api.Node;
24 import org.opendaylight.yangtools.yang.data.api.NodeModification;
25 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
28 * @author michal.rehak
31 public abstract class NodeFactory {
37 * @return simple node modification, based on given qname, value and parent
39 public static <T> SimpleNode<T> createImmutableSimpleNode(final QName qName,
40 final CompositeNode parent, final T value) {
41 return createImmutableSimpleNode(qName, parent, value, null);
49 * @param original originating node, if available
50 * @return simple node modification, based on given qname, value and parent
52 public static <T> MutableSimpleNode<T> createMutableSimpleNode(final QName qName,
53 final CompositeNode parent, final Object value, final ModifyAction modifyAction, final SimpleNode<T> original) {
54 @SuppressWarnings("unchecked")
55 MutableSimpleNodeTOImpl<T> simpleNodeTOImpl =
56 new MutableSimpleNodeTOImpl<T>(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 CompositeNodeTOImpl compositeNodeModTOImpl =
117 new CompositeNodeTOImpl(qName, parent, value, modifyAction);
118 return compositeNodeModTOImpl;
123 * @return copy of given node, parent and value are the same, but parent
124 * has no reference to this copy
126 public static <T> SimpleNode<T> copyNode(final SimpleNode<T> node) {
127 SimpleNode<T> twinNode = createImmutableSimpleNode(
128 node.getNodeType(), node.getParent(), node.getValue());
134 * @return copy of given node, parent and value are the same, but parent
135 * has no reference to this copy
137 public static <T> MutableSimpleNode<T> copyNodeAsMutable(final SimpleNode<T> node) {
138 MutableSimpleNode<T> twinNode = createMutableSimpleNode(
139 node.getNodeType(), node.getParent(), node.getValue(),
140 node.getModificationAction(), null);
147 * @return copy of given node, parent and children are the same, but parent and children
148 * have no reference to this copy
150 public static CompositeNode copyNode(final CompositeNode node, final Node<?>... children) {
151 CompositeNode twinNode = createImmutableCompositeNode(
152 node.getNodeType(), node.getParent(), Arrays.asList(children), node.getModificationAction());
158 * @return copy of given node, parent and children are the same, but parent and children
159 * have no reference to this copy
161 public static CompositeNode copyNode(final CompositeNode node) {
162 return copyNode(node, node.getValue().toArray(new Node<?>[0]));
166 * @param node root of original tree
167 * @param originalToCopyArg (optional) empty map, where binding between original and copy
169 * @return copy of given node and all subnodes recursively
171 public static MutableCompositeNode copyDeepAsMutable(final CompositeNode node,
172 final Map<Node<?>, Node<?>> originalToCopyArg) {
174 Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
175 if (originalToCopy == null) {
176 originalToCopy = new HashMap<>();
179 MutableCompositeNode mutableRoot = createMutableCompositeNode(node.getNodeType(), null, null,
180 node.getModificationAction(), null);
181 Stack<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new Stack<>();
182 jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));
183 originalToCopy.put(node, mutableRoot);
185 while (!jobQueue.isEmpty()) {
186 SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();
187 CompositeNode originalNode = job.getKey();
188 MutableCompositeNode mutableNode = job.getValue();
189 mutableNode.setValue(new ArrayList<Node<?>>());
191 for (Node<?> child : originalNode.getValue()) {
192 Node<?> mutableAscendant = null;
193 if (child instanceof CompositeNode) {
194 MutableCompositeNode newMutable =
195 createMutableCompositeNode(child.getNodeType(), mutableNode, null,
196 ((NodeModification) child).getModificationAction(), null);
197 jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(
198 (CompositeNode) child, newMutable));
199 mutableAscendant = newMutable;
200 } else if (child instanceof SimpleNode<?>) {
202 createMutableSimpleNode(child.getNodeType(), mutableNode,
204 ((NodeModification) child).getModificationAction(), null);
206 throw new IllegalStateException("Node class deep copy not supported: "
207 +child.getClass().getName());
210 mutableNode.getValue().add(mutableAscendant);
211 originalToCopy.put(child, mutableAscendant);
220 * @param node root of original tree
221 * @param originalToCopyArg (optional) empty map, where binding between original and copy
223 * @return copy of given node and all subnodes recursively
225 public static CompositeNode copyDeepAsImmutable(final CompositeNode node,
226 final Map<Node<?>, Node<?>> originalToCopyArg) {
227 Stack<CompositeNode> jobQueue = new Stack<>();
230 Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
231 if (originalToCopy == null) {
232 originalToCopy = new HashMap<>();
235 while (!jobQueue.isEmpty()) {
236 CompositeNode jobNode = jobQueue.peek();
237 if (!originalToCopy.isEmpty()
238 && originalToCopy.keySet().containsAll(jobNode.getValue())) {
240 List<Node<?>> newChildren = NodeUtils.collectMapValues(jobNode.getValue(), originalToCopy);
241 CompositeNode nodeCopy = createImmutableCompositeNode(jobNode.getNodeType(), null,
242 newChildren, jobNode.getModificationAction());
243 NodeUtils.fixChildrenRelation(nodeCopy);
244 originalToCopy.put(jobNode, nodeCopy);
246 for (Node<?> child : jobNode.getValue()) {
247 if (child instanceof SimpleNode<?>) {
248 originalToCopy.put(child, createImmutableSimpleNode(
249 child.getNodeType(), null, child.getValue(),
250 ((NodeModification) child).getModificationAction()));
251 } else if (child instanceof CompositeNode) {
252 jobQueue.push((CompositeNode) child);
258 return (CompositeNode) originalToCopy.get(node);