Bug 1372 - toString methods in generated classes
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / NodeFactory.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.impl;
9
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;
17 import java.util.Map;
18
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;
27
28 /**
29  * @author michal.rehak
30  *
31  */
32 public abstract class NodeFactory {
33
34     /**
35      * @param qName
36      * @param parent
37      * @param value
38      * @return simple node modification, based on given qname, value and parent
39      */
40     public static <T> SimpleNode<T> createImmutableSimpleNode(final QName qName,
41             final CompositeNode parent, final T value) {
42         return createImmutableSimpleNode(qName, parent, value, null);
43     }
44
45     /**
46      * @param qName
47      * @param parent
48      * @param value
49      * @param modifyAction
50      * @param original originating node, if available
51      * @return simple node modification, based on given qname, value and parent
52      */
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;
59     }
60
61     /**
62      * @param qName
63      * @param parent
64      * @param value
65      * @return composite node modification, based on given qname, value (children), parent and modifyAction
66      */
67     public static CompositeNode createImmutableCompositeNode(final QName qName,
68             final CompositeNode parent, final List<Node<?>> value) {
69         return createImmutableCompositeNode(qName, parent, value, null);
70     }
71
72     /**
73      * @param qName
74      * @param parent
75      * @param valueArg
76      * @param modifyAction
77      * @param original originating node, if available
78      * @return composite node modification, based on given qName, value (children), parent and modifyAction
79      */
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;
83         if (value == null) {
84             value = new ArrayList<>();
85         }
86         MutableCompositeNodeTOImpl compositeNodeTOImpl =
87                 new MutableCompositeNodeTOImpl(qName, parent, value, modifyAction);
88         compositeNodeTOImpl.setOriginal(original);
89         return compositeNodeTOImpl;
90     }
91
92
93     /**
94      * @param qName
95      * @param parent
96      * @param value
97      * @param modifyAction
98      * @return simple node modification, based on given qname, value, parent and modifyAction
99      */
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;
105     }
106
107     /**
108      * @param qName
109      * @param parent
110      * @param value
111      * @param modifyAction
112      * @return composite node modification, based on given qname, value (children), parent and modifyAction
113      */
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);
117     }
118
119     /**
120      * @param node
121      * @return copy of given node, parent and value are the same, but parent
122      * has no reference to this copy
123      */
124     public static <T> SimpleNode<T> copyNode(final SimpleNode<T> node) {
125         return createImmutableSimpleNode(node.getNodeType(), node.getParent(), node.getValue());
126     }
127
128     /**
129      * @param node
130      * @return copy of given node, parent and value are the same, but parent
131      * has no reference to this copy
132      */
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);
137     }
138
139     /**
140      * @param node
141      * @param children
142      * @return copy of given node, parent and children are the same, but parent and children
143      * have no reference to this copy
144      */
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());
148         return twinNode;
149     }
150
151     /**
152      * @param node
153      * @return copy of given node, parent and children are the same, but parent and children
154      * have no reference to this copy
155      */
156     public static CompositeNode copyNode(final CompositeNode node) {
157         return copyNode(node, node.getValue().toArray(new Node<?>[0]));
158     }
159
160     /**
161      * @param node root of original tree
162      * @param originalToCopyArg (optional) empty map, where binding between original and copy
163      * will be stored
164      * @return copy of given node and all subnodes recursively
165      */
166     public static MutableCompositeNode copyDeepAsMutable(final CompositeNode node,
167             final Map<Node<?>, Node<?>> originalToCopyArg) {
168
169         Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
170         if (originalToCopy == null) {
171             originalToCopy = new HashMap<>();
172         }
173
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);
179
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<?>>());
185
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<?>) {
196                     mutableAscendant =
197                             createMutableSimpleNode(child.getNodeType(), mutableNode,
198                                     child.getValue(),
199                                     ((NodeModification) child).getModificationAction(), null);
200                 } else {
201                     throw new IllegalStateException("Node class deep copy not supported: "
202                             +child.getClass().getName());
203                 }
204
205                 mutableNode.getValue().add(mutableAscendant);
206                 originalToCopy.put(child, mutableAscendant);
207             }
208             mutableNode.init();
209         }
210
211         return mutableRoot;
212     }
213
214     /**
215      * @param node root of original tree
216      * @param originalToCopyArg (optional) empty map, where binding between original and copy
217      * will be stored
218      * @return copy of given node and all subnodes recursively
219      */
220     public static CompositeNode copyDeepAsImmutable(final CompositeNode node,
221             final Map<Node<?>, Node<?>> originalToCopyArg) {
222         final Deque<CompositeNode> jobQueue = new ArrayDeque<>();
223         jobQueue.push(node);
224
225         Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;
226         if (originalToCopy == null) {
227             originalToCopy = new HashMap<>();
228         }
229
230         while (!jobQueue.isEmpty()) {
231             CompositeNode jobNode = jobQueue.peek();
232             if (!originalToCopy.isEmpty()
233                     && originalToCopy.keySet().containsAll(jobNode.getValue())) {
234                 jobQueue.pop();
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);
240             } else {
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);
248                     }
249                 }
250             }
251         }
252
253         return (CompositeNode) originalToCopy.get(node);
254     }
255
256 }