A race condition occurs between ARPHandler and HostTracker if the ARP
[controller.git] / opendaylight / sal / yang-prototype / yang / yang-data-impl / src / main / java / org / opendaylight / controller / yang / data / impl / NodeFactory.java
1 /*\r
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 package org.opendaylight.controller.yang.data.impl;\r
9 \r
10 import java.util.AbstractMap.SimpleEntry;\r
11 import java.util.ArrayList;\r
12 import java.util.Arrays;\r
13 import java.util.HashMap;\r
14 import java.util.List;\r
15 import java.util.Map;\r
16 import java.util.Stack;\r
17 \r
18 import org.opendaylight.controller.yang.common.QName;\r
19 import org.opendaylight.controller.yang.data.api.CompositeNode;\r
20 import org.opendaylight.controller.yang.data.api.ModifyAction;\r
21 import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
22 import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
23 import org.opendaylight.controller.yang.data.api.Node;\r
24 import org.opendaylight.controller.yang.data.api.NodeModification;\r
25 import org.opendaylight.controller.yang.data.api.SimpleNode;\r
26 \r
27 /**\r
28  * @author michal.rehak\r
29  * \r
30  */\r
31 public abstract class NodeFactory {\r
32 \r
33     /**\r
34      * @param qName\r
35      * @param parent\r
36      * @param value\r
37      * @return simple node modification, based on given qname, value and parent\r
38      */\r
39     public static <T> SimpleNode<T> createImmutableSimpleNode(QName qName,\r
40             CompositeNode parent, T value) {\r
41         return createImmutableSimpleNode(qName, parent, value, null);\r
42     }\r
43     \r
44     /**\r
45      * @param qName\r
46      * @param parent\r
47      * @param value\r
48      * @param modifyAction \r
49      * @param original originating node, if available\r
50      * @return simple node modification, based on given qname, value and parent\r
51      */\r
52     public static <T> MutableSimpleNode<T> createMutableSimpleNode(QName qName,\r
53             CompositeNode parent, Object value, ModifyAction modifyAction, SimpleNode<T> original) {\r
54         @SuppressWarnings("unchecked")\r
55         MutableSimpleNodeTOImpl<T> simpleNodeTOImpl = \r
56                 new MutableSimpleNodeTOImpl<T>(qName, parent, (T) value, modifyAction);\r
57         simpleNodeTOImpl.setOriginal(original);\r
58         return simpleNodeTOImpl;\r
59     }\r
60     \r
61     /**\r
62      * @param qName\r
63      * @param parent\r
64      * @param value\r
65      * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
66      */\r
67     public static CompositeNode createImmutableCompositeNode(QName qName,\r
68             CompositeNode parent, List<Node<?>> value) {\r
69         return createImmutableCompositeNode(qName, parent, value, null);\r
70     }\r
71     \r
72     /**\r
73      * @param qName\r
74      * @param parent\r
75      * @param valueArg \r
76      * @param modifyAction \r
77      * @param original originating node, if available\r
78      * @return composite node modification, based on given qName, value (children), parent and modifyAction\r
79      */\r
80     public static MutableCompositeNode createMutableCompositeNode(QName qName,\r
81             CompositeNode parent, List<Node<?>> valueArg, ModifyAction modifyAction, CompositeNode original) {\r
82         List<Node<?>> value = valueArg;\r
83         if (value == null) {\r
84             value = new ArrayList<>();\r
85         }\r
86         MutableCompositeNodeTOImpl compositeNodeTOImpl = \r
87                 new MutableCompositeNodeTOImpl(qName, parent, value, modifyAction);\r
88         compositeNodeTOImpl.setOriginal(original);\r
89         return compositeNodeTOImpl;\r
90     }\r
91     \r
92     \r
93     /**\r
94      * @param qName\r
95      * @param parent\r
96      * @param value\r
97      * @param modifyAction\r
98      * @return simple node modification, based on given qname, value, parent and modifyAction\r
99      */\r
100     public static <T> SimpleNode<T> createImmutableSimpleNode(QName qName,\r
101             CompositeNode parent, T value, ModifyAction modifyAction) {\r
102         SimpleNodeTOImpl<T> simpleNodeModTOImpl = \r
103                 new SimpleNodeTOImpl<T>(qName, parent, value, modifyAction);\r
104         return simpleNodeModTOImpl;\r
105     }\r
106 \r
107     /**\r
108      * @param qName\r
109      * @param parent\r
110      * @param value\r
111      * @param modifyAction \r
112      * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
113      */\r
114     public static CompositeNode createImmutableCompositeNode(QName qName,\r
115             CompositeNode parent, List<Node<?>> value, ModifyAction modifyAction) {\r
116         CompositeNodeTOImpl compositeNodeModTOImpl = \r
117                 new CompositeNodeTOImpl(qName, parent, value, modifyAction);\r
118         return compositeNodeModTOImpl;\r
119     }\r
120 \r
121     /**\r
122      * @param node\r
123      * @return copy of given node, parent and value are the same, but parent \r
124      * has no reference to this copy \r
125      */\r
126     public static <T> SimpleNode<T> copyNode(SimpleNode<T> node) {\r
127         SimpleNode<T> twinNode = createImmutableSimpleNode(\r
128                     node.getNodeType(), node.getParent(), node.getValue());\r
129         return twinNode;\r
130     }\r
131     \r
132     /**\r
133      * @param node\r
134      * @return copy of given node, parent and value are the same, but parent \r
135      * has no reference to this copy \r
136      */\r
137     public static <T> MutableSimpleNode<T> copyNodeAsMutable(SimpleNode<T> node) {\r
138         MutableSimpleNode<T> twinNode = createMutableSimpleNode(\r
139                     node.getNodeType(), node.getParent(), node.getValue(), \r
140                     node.getModificationAction(), null);\r
141         return twinNode;\r
142     }\r
143     \r
144     /**\r
145      * @param node\r
146      * @param children \r
147      * @return copy of given node, parent and children are the same, but parent and children \r
148      * have no reference to this copy\r
149      */\r
150     public static CompositeNode copyNode(CompositeNode node, Node<?>... children) {\r
151         CompositeNode twinNode = createImmutableCompositeNode(\r
152                 node.getNodeType(), node.getParent(), Arrays.asList(children), node.getModificationAction());\r
153         return twinNode;\r
154     }\r
155     \r
156     /**\r
157      * @param node\r
158      * @return copy of given node, parent and children are the same, but parent and children \r
159      * have no reference to this copy\r
160      */\r
161     public static CompositeNode copyNode(CompositeNode node) {\r
162        return copyNode(node, node.getChildren().toArray(new Node<?>[0]));\r
163     }\r
164     \r
165     /**\r
166      * @param node root of original tree\r
167      * @param originalToCopyArg (optional) empty map, where binding between original and copy \r
168      * will be stored\r
169      * @return copy of given node and all subnodes recursively\r
170      */\r
171     public static MutableCompositeNode copyDeepAsMutable(CompositeNode node, \r
172             Map<Node<?>, Node<?>> originalToCopyArg) {\r
173         \r
174         Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;\r
175         if (originalToCopy == null) {\r
176             originalToCopy = new HashMap<>();\r
177         }\r
178 \r
179         MutableCompositeNode mutableRoot = createMutableCompositeNode(node.getNodeType(), null, null, \r
180                 node.getModificationAction(), null);\r
181         Stack<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new Stack<>();\r
182         jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));\r
183         originalToCopy.put(node, mutableRoot);\r
184 \r
185         while (!jobQueue.isEmpty()) {\r
186             SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();\r
187             CompositeNode originalNode = job.getKey();\r
188             MutableCompositeNode mutableNode = job.getValue();\r
189             mutableNode.setValue(new ArrayList<Node<?>>());\r
190 \r
191             for (Node<?> child : originalNode.getChildren()) {\r
192                 Node<?> mutableAscendant = null;\r
193                 if (child instanceof CompositeNode) {\r
194                     MutableCompositeNode newMutable = \r
195                             createMutableCompositeNode(child.getNodeType(), mutableNode, null, \r
196                                     ((NodeModification) child).getModificationAction(), null);\r
197                     jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(\r
198                             (CompositeNode) child, newMutable));\r
199                     mutableAscendant = newMutable;\r
200                 } else if (child instanceof SimpleNode<?>) {\r
201                     mutableAscendant = \r
202                             createMutableSimpleNode(child.getNodeType(), mutableNode, \r
203                                     child.getValue(), \r
204                                     ((NodeModification) child).getModificationAction(), null);\r
205                 } else {\r
206                     throw new IllegalStateException("Node class deep copy not supported: "\r
207                             +child.getClass().getName());\r
208                 }\r
209 \r
210                 mutableNode.getChildren().add(mutableAscendant);\r
211                 originalToCopy.put(child, mutableAscendant);\r
212             }\r
213             mutableNode.init();\r
214         }\r
215 \r
216         return mutableRoot;\r
217     }\r
218     \r
219     /**\r
220      * @param node root of original tree\r
221      * @param originalToCopyArg (optional) empty map, where binding between original and copy \r
222      * will be stored\r
223      * @return copy of given node and all subnodes recursively\r
224      */\r
225     public static CompositeNode copyDeepAsImmutable(CompositeNode node, \r
226             Map<Node<?>, Node<?>> originalToCopyArg) {\r
227         Stack<CompositeNode> jobQueue = new Stack<>();\r
228         jobQueue.push(node);\r
229         \r
230         Map<Node<?>, Node<?>> originalToCopy = originalToCopyArg;\r
231         if (originalToCopy == null) {\r
232             originalToCopy = new HashMap<>();\r
233         }\r
234         \r
235         while (!jobQueue.isEmpty()) {\r
236             CompositeNode jobNode = jobQueue.peek();\r
237             if (!originalToCopy.isEmpty() \r
238                     && originalToCopy.keySet().containsAll(jobNode.getChildren())) {\r
239                 jobQueue.pop();\r
240                 List<Node<?>> newChildren = NodeUtils.collectMapValues(jobNode.getChildren(), originalToCopy);\r
241                 CompositeNode nodeCopy = createImmutableCompositeNode(jobNode.getNodeType(), null, \r
242                         newChildren, jobNode.getModificationAction());\r
243                 NodeUtils.fixChildrenRelation(nodeCopy);\r
244                 originalToCopy.put(jobNode, nodeCopy);\r
245             } else {\r
246                 for (Node<?> child : jobNode.getChildren()) {\r
247                     if (child instanceof SimpleNode<?>) {\r
248                         originalToCopy.put(child, createImmutableSimpleNode(\r
249                                 child.getNodeType(), null, child.getValue(), \r
250                                 ((NodeModification) child).getModificationAction()));\r
251                     } else if (child instanceof CompositeNode) {\r
252                         jobQueue.push((CompositeNode) child);\r
253                     }\r
254                 }\r
255             }\r
256         }\r
257        \r
258         return (CompositeNode) originalToCopy.get(node);\r
259     }\r
260     \r
261 }\r