blob: ae2943349f79f9ee2ed7c22dd893e9ab755761f2 [file] [log] [blame]
Vinod Kumar S8c4e6492016-02-05 20:21:19 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Vinod Kumar S8c4e6492016-02-05 20:21:19 +05303 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.yangutils.datamodel;
17
18import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
janani b4e53f9b2016-04-26 18:49:20 +053019import org.onosproject.yangutils.parser.Parsable;
Vinod Kumar S427d2932016-04-20 13:02:58 +053020import org.onosproject.yangutils.translator.tojava.TraversalType;
21
22import static org.onosproject.yangutils.translator.tojava.TraversalType.CHILD;
23import static org.onosproject.yangutils.translator.tojava.TraversalType.PARENT;
24import static org.onosproject.yangutils.translator.tojava.TraversalType.SIBILING;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053025
26/**
Bharat saraswald9822e92016-04-05 15:13:44 +053027 * Represents base class of a node in data model tree.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053028 */
Vinod Kumar S427d2932016-04-20 13:02:58 +053029public abstract class YangNode
30 implements Cloneable {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053031
Vinod Kumar S67e7be62016-02-11 20:13:28 +053032 /**
33 * Type of node.
34 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053035 private YangNodeType nodeType;
36
Vinod Kumar S67e7be62016-02-11 20:13:28 +053037 /**
38 * Parent reference.
39 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053040 private YangNode parent;
41
Vinod Kumar S67e7be62016-02-11 20:13:28 +053042 /**
43 * First child reference.
44 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053045 private YangNode child;
46
Vinod Kumar S67e7be62016-02-11 20:13:28 +053047 /**
48 * Next sibling reference.
49 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053050 private YangNode nextSibling;
51
Vinod Kumar S67e7be62016-02-11 20:13:28 +053052 /**
53 * Previous sibling reference.
54 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053055 private YangNode previousSibling;
56
57 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053058 * Returns the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053059 *
60 * @return nodes name
61 */
62 public abstract String getName();
63
64 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053065 * Sets the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053066 *
67 * @param name nodes name
68 */
69 public abstract void setName(String name);
70
71 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053072 * Creates a YANG node object.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053073 */
74 @SuppressWarnings("unused")
75 private YangNode() {
76
77 }
78
79 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053080 * Creates a specific type of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053081 *
82 * @param type of YANG node
83 */
84 protected YangNode(YangNodeType type) {
85 setNodeType(type);
86 }
87
88 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053089 * Returns the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053090 *
91 * @return node type
92 */
93 public YangNodeType getNodeType() {
94 return nodeType;
95 }
96
97 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053098 * Sets the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053099 *
100 * @param nodeType type of node
101 */
102 private void setNodeType(YangNodeType nodeType) {
103 this.nodeType = nodeType;
104 }
105
106 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530107 * Returns the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530108 *
109 * @return parent of node
110 */
111 public YangNode getParent() {
112 return parent;
113 }
114
115 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530116 * Sets the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530117 *
118 * @param parent node
119 */
120 public void setParent(YangNode parent) {
121 this.parent = parent;
122 }
123
124 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530125 * Returns the first child of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530126 *
127 * @return first child of node
128 */
129 public YangNode getChild() {
130 return child;
131 }
132
133 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530134 * Sets the first instance of a child node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530135 *
136 * @param child is only child to be set
137 */
138 public void setChild(YangNode child) {
139 this.child = child;
140 }
141
142 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530143 * Returns the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530144 *
145 * @return next sibling of node
146 */
147 public YangNode getNextSibling() {
148 return nextSibling;
149 }
150
151 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530152 * Sets the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530153 *
154 * @param sibling YANG node
155 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530156 private void setNextSibling(YangNode sibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530157 nextSibling = sibling;
158 }
159
160 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530161 * Returns the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530162 *
163 * @return previous sibling node
164 */
165 public YangNode getPreviousSibling() {
166 return previousSibling;
167 }
168
169 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530170 * Sets the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530171 *
172 * @param previousSibling points to predecessor sibling
173 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530174 private void setPreviousSibling(YangNode previousSibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530175 this.previousSibling = previousSibling;
176 }
177
178 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530179 * Adds a child node, the children sibling list will be sorted based on node
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530180 * type.
181 *
182 * @param newChild refers to a child to be added
183 * @throws DataModelException due to violation in data model rules
184 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530185 public void addChild(YangNode newChild)
186 throws DataModelException {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530187 if (newChild.getNodeType() == null) {
188 throw new DataModelException("Abstract node cannot be inserted into a tree");
189 }
190
191 if (newChild.getParent() == null) {
192 newChild.setParent(this);
193 } else if (newChild.getParent() != this) {
194 throw new DataModelException("Node is already part of a tree");
195 }
196
197 if (newChild.getChild() != null) {
198 throw new DataModelException("Child to be added is not atomic, it already has a child");
199 }
200
201 if (newChild.getNextSibling() != null) {
202 throw new DataModelException("Child to be added is not atomic, it already has a next sibling");
203 }
204
205 if (newChild.getPreviousSibling() != null) {
206 throw new DataModelException("Child to be added is not atomic, it already has a previous sibling");
207 }
208
209 /* First child to be added */
210 if (getChild() == null) {
211 setChild(newChild);
212 return;
213 }
214
215 YangNode curNode;
216 curNode = getChild();
217
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530218 /*
219 * Get the predecessor child of new child
220 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530221 while (curNode.getNextSibling() != null) {
Vinod Kumar S38046502016-03-23 15:30:27 +0530222
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530223 curNode = curNode.getNextSibling();
224 }
225
226 /* If the new node needs to be the last child */
227 if (curNode.getNextSibling() == null) {
228 curNode.setNextSibling(newChild);
229 newChild.setPreviousSibling(curNode);
Vinod Kumar S427d2932016-04-20 13:02:58 +0530230 }
231 }
232
233 /**
234 * Clone the current node contents and create a new node.
235 *
236 * @return cloned node
237 * @throws CloneNotSupportedException clone is not supported by the referred node
238 */
239 public YangNode clone()
240 throws CloneNotSupportedException {
241 YangNode clonedNode = (YangNode) super.clone();
242 clonedNode.setParent(null);
243 clonedNode.setChild(null);
244 clonedNode.setNextSibling(null);
245 clonedNode.setPreviousSibling(null);
246 return clonedNode;
247 }
248
249 /**
250 * Clone the subtree from the specified source node to the mentioned target node.
251 * The source and target root node cloning is carried out by the caller.
252 *
253 * @param srcRootNode source node for sub tree cloning
254 * @param dstRootNode destination node where the sub tree needs to be cloned
255 * @throws DataModelException data model error
256 */
257 public static void cloneSubTree(YangNode srcRootNode, YangNode dstRootNode)
258 throws DataModelException {
259
260 YangNode nextNodeToClone = srcRootNode;
261 TraversalType curTraversal;
262
263
264 YangNode clonedTreeCurNode = dstRootNode;
265 YangNode newNode = null;
266
267 nextNodeToClone = nextNodeToClone.getChild();
268 if (nextNodeToClone == null) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530269 return;
Vinod Kumar S427d2932016-04-20 13:02:58 +0530270 } else {
271 /**
272 * Root level cloning is taken care in the caller.
273 */
274 curTraversal = CHILD;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530275 }
276
Vinod Kumar S427d2932016-04-20 13:02:58 +0530277 /**
278 * Caller ensures the cloning of the root nodes
Vinod Kumar S38046502016-03-23 15:30:27 +0530279 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530280 try {
281 while (nextNodeToClone != srcRootNode) {
282 if (nextNodeToClone == null) {
283 throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
284 }
janani b4e53f9b2016-04-26 18:49:20 +0530285 if (curTraversal != PARENT) {
Vinod Kumar S427d2932016-04-20 13:02:58 +0530286 newNode = nextNodeToClone.clone();
janani b4e53f9b2016-04-26 18:49:20 +0530287 detectCollisionWhileCloning(clonedTreeCurNode, newNode, curTraversal);
288 }
289 if (curTraversal == CHILD) {
Vinod Kumar S427d2932016-04-20 13:02:58 +0530290
291 /**
292 * add the new node to the cloned tree.
293 */
294 clonedTreeCurNode.addChild(newNode);
295
296 /**
297 * update the cloned tree's travesal current node as the new node.
298 */
299 clonedTreeCurNode = newNode;
300 } else if (curTraversal == SIBILING) {
Vinod Kumar S427d2932016-04-20 13:02:58 +0530301
302 clonedTreeCurNode.addNextSibling(newNode);
303 clonedTreeCurNode = newNode;
304 } else if (curTraversal == PARENT) {
305 clonedTreeCurNode = clonedTreeCurNode.getParent();
306 }
307
308 if (curTraversal != PARENT && nextNodeToClone.getChild() != null) {
309 curTraversal = CHILD;
310
311 /**
312 * update the traversal's current node.
313 */
314 nextNodeToClone = nextNodeToClone.getChild();
315
316 } else if (nextNodeToClone.getNextSibling() != null) {
317
318 curTraversal = SIBILING;
319
320 nextNodeToClone = nextNodeToClone.getNextSibling();
321 } else {
322 curTraversal = PARENT;
323 nextNodeToClone = nextNodeToClone.getParent();
324 }
325 }
326 } catch (CloneNotSupportedException e) {
327 throw new DataModelException("Failed to clone the tree");
328 }
329
330 }
331
332 /**
janani b4e53f9b2016-04-26 18:49:20 +0530333 * Detects collision when the grouping is deep copied to the uses's parent.
334 *
335 * @param currentNode parent/previous sibling node for the new node
336 * @param newNode node which has to be added
337 * @param addAs traversal type of the node
338 * @throws DataModelException data model error
339 */
340 private static void detectCollisionWhileCloning(YangNode currentNode, YangNode newNode, TraversalType addAs)
341 throws DataModelException {
342 if ((!(currentNode instanceof CollisionDetector))
343 || (!(newNode instanceof Parsable))) {
344 throw new DataModelException("Node in data model tree does not support collision detection");
345 }
346
347 CollisionDetector collisionDetector = (CollisionDetector) currentNode;
348 Parsable parsable = (Parsable) newNode;
349 if (addAs == TraversalType.CHILD) {
350 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
351 } else if (addAs == TraversalType.SIBILING) {
352 currentNode = currentNode.getParent();
353 if (!(currentNode instanceof CollisionDetector)) {
354 throw new DataModelException("Node in data model tree does not support collision detection");
355 }
356 collisionDetector = (CollisionDetector) currentNode;
357 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
358 } else {
359 throw new DataModelException("Errored tree cloning");
360 }
361
362 }
363
364 /**
Vinod Kumar S427d2932016-04-20 13:02:58 +0530365 * Add a new next sibling.
366 *
367 * @param newSibling new sibling to be added
368 * @throws DataModelException data model error
369 */
370 private void addNextSibling(YangNode newSibling)
371 throws DataModelException {
372
373 if (newSibling.getNodeType() == null) {
374 throw new DataModelException("Cloned abstract node cannot be inserted into a tree");
375 }
376
377 if (newSibling.getParent() == null) {
378 /**
379 * Since the siblings needs to have a common parent, set the parent as the current node's parent
380 */
381 newSibling.setParent(this.getParent());
382
383 } else {
384 throw new DataModelException("Node is already part of a tree, and cannot be added as a sibling");
385 }
386
387 if (newSibling.getPreviousSibling() == null) {
388 newSibling.setPreviousSibling(this);
389 setNextSibling(newSibling);
390 } else {
391 throw new DataModelException("New sibling to be added is not atomic, it already has a previous sibling");
392 }
393
394 if (newSibling.getChild() != null) {
395 throw new DataModelException("Sibling to be added is not atomic, it already has a child");
396 }
397
398 if (newSibling.getNextSibling() != null) {
399 throw new DataModelException("Sibling to be added is not atomic, it already has a next sibling");
400 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530401 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530402}