blob: d501b0b69acee658e5b09e73c783a9b424d82d65 [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
Bharat saraswal96dfef02016-06-16 00:29:12 +053018import java.io.Serializable;
Bharat saraswal2d90b0c2016-08-04 02:00:03 +053019
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053020import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Vidyashree Rama405d2e62016-07-08 20:45:41 +053021import org.onosproject.yangutils.datamodel.utils.Parsable;
22
23import static org.onosproject.yangutils.datamodel.TraversalType.CHILD;
24import static org.onosproject.yangutils.datamodel.TraversalType.PARENT;
25import static org.onosproject.yangutils.datamodel.TraversalType.SIBILING;
26import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.cloneLeaves;
27import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.updateClonedLeavesUnionEnumRef;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053028
29/**
Bharat saraswald9822e92016-04-05 15:13:44 +053030 * Represents base class of a node in data model tree.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053031 */
Vinod Kumar S427d2932016-04-20 13:02:58 +053032public abstract class YangNode
Vidyashree Rama1b499062016-07-12 20:52:48 +053033 implements Cloneable, Serializable, YangDataNode, Comparable<YangNode> {
Bharat saraswal96dfef02016-06-16 00:29:12 +053034
35 private static final long serialVersionUID = 806201601L;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053036
Vinod Kumar S67e7be62016-02-11 20:13:28 +053037 /**
38 * Type of node.
39 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053040 private YangNodeType nodeType;
41
Vinod Kumar S67e7be62016-02-11 20:13:28 +053042 /**
43 * Parent reference.
44 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053045 private YangNode parent;
46
Vinod Kumar S67e7be62016-02-11 20:13:28 +053047 /**
48 * First child reference.
49 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053050 private YangNode child;
51
Vinod Kumar S67e7be62016-02-11 20:13:28 +053052 /**
53 * Next sibling reference.
54 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053055 private YangNode nextSibling;
56
Vinod Kumar S67e7be62016-02-11 20:13:28 +053057 /**
58 * Previous sibling reference.
59 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053060 private YangNode previousSibling;
61
62 /**
Vidyashree Rama1b499062016-07-12 20:52:48 +053063 * Priority of the node.
64 */
65 private int priority;
66
67 /**
Bharat saraswald50c6382016-07-14 21:57:13 +053068 * Flag if the node is for translation.
69 */
70 private boolean isToTranslate = true;
71
72 /**
Vidyashree Rama1b499062016-07-12 20:52:48 +053073 * Returns the priority of the node.
74 *
75 * @return priority of the node
76 */
77 public int getPriority() {
78 return priority;
79 }
80
81 /**
82 * Sets the priority of the node.
83 *
84 * @param priority of the node
85 */
86 public void setPriority(int priority) {
87 this.priority = priority;
88 }
89
90 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053091 * Returns the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053092 *
93 * @return nodes name
94 */
95 public abstract String getName();
96
97 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053098 * Sets the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053099 *
100 * @param name nodes name
101 */
102 public abstract void setName(String name);
103
104 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530105 * Creates a YANG node object.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530106 */
107 @SuppressWarnings("unused")
108 private YangNode() {
109
110 }
111
112 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530113 * Creates a specific type of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530114 *
115 * @param type of YANG node
116 */
117 protected YangNode(YangNodeType type) {
118 setNodeType(type);
119 }
120
121 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530122 * Returns the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530123 *
124 * @return node type
125 */
126 public YangNodeType getNodeType() {
127 return nodeType;
128 }
129
130 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530131 * Sets the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530132 *
133 * @param nodeType type of node
134 */
135 private void setNodeType(YangNodeType nodeType) {
136 this.nodeType = nodeType;
137 }
138
139 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530140 * Returns the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530141 *
142 * @return parent of node
143 */
144 public YangNode getParent() {
145 return parent;
146 }
147
148 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530149 * Sets the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530150 *
151 * @param parent node
152 */
153 public void setParent(YangNode parent) {
154 this.parent = parent;
155 }
156
157 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530158 * Returns the first child of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530159 *
160 * @return first child of node
161 */
162 public YangNode getChild() {
163 return child;
164 }
165
166 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530167 * Sets the first instance of a child node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530168 *
169 * @param child is only child to be set
170 */
171 public void setChild(YangNode child) {
172 this.child = child;
173 }
174
175 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530176 * Returns the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530177 *
178 * @return next sibling of node
179 */
180 public YangNode getNextSibling() {
181 return nextSibling;
182 }
183
184 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530185 * Sets the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530186 *
187 * @param sibling YANG node
188 */
Bharat saraswal2d90b0c2016-08-04 02:00:03 +0530189 public void setNextSibling(YangNode sibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530190 nextSibling = sibling;
191 }
192
193 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530194 * Returns the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530195 *
196 * @return previous sibling node
197 */
198 public YangNode getPreviousSibling() {
199 return previousSibling;
200 }
201
202 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530203 * Sets the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530204 *
205 * @param previousSibling points to predecessor sibling
206 */
Bharat saraswal2d90b0c2016-08-04 02:00:03 +0530207 public void setPreviousSibling(YangNode previousSibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530208 this.previousSibling = previousSibling;
209 }
210
211 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530212 * Adds a child node, the children sibling list will be sorted based on node
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530213 * type.
214 *
215 * @param newChild refers to a child to be added
216 * @throws DataModelException due to violation in data model rules
217 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530218 public void addChild(YangNode newChild)
219 throws DataModelException {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530220 if (newChild.getNodeType() == null) {
221 throw new DataModelException("Abstract node cannot be inserted into a tree");
222 }
223
224 if (newChild.getParent() == null) {
225 newChild.setParent(this);
226 } else if (newChild.getParent() != this) {
227 throw new DataModelException("Node is already part of a tree");
228 }
229
230 if (newChild.getChild() != null) {
231 throw new DataModelException("Child to be added is not atomic, it already has a child");
232 }
233
234 if (newChild.getNextSibling() != null) {
235 throw new DataModelException("Child to be added is not atomic, it already has a next sibling");
236 }
237
238 if (newChild.getPreviousSibling() != null) {
239 throw new DataModelException("Child to be added is not atomic, it already has a previous sibling");
240 }
241
242 /* First child to be added */
243 if (getChild() == null) {
244 setChild(newChild);
245 return;
246 }
247
248 YangNode curNode;
249 curNode = getChild();
250
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530251 /*
252 * Get the predecessor child of new child
253 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530254 while (curNode.getNextSibling() != null) {
Vinod Kumar S38046502016-03-23 15:30:27 +0530255
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530256 curNode = curNode.getNextSibling();
257 }
258
259 /* If the new node needs to be the last child */
260 if (curNode.getNextSibling() == null) {
261 curNode.setNextSibling(newChild);
262 newChild.setPreviousSibling(curNode);
Vinod Kumar S427d2932016-04-20 13:02:58 +0530263 }
264 }
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530265
Vidyashree Rama1b499062016-07-12 20:52:48 +0530266 @Override
267 public int compareTo(YangNode otherNode) {
268 if (priority == otherNode.getPriority()) {
269 return 1;
270 }
271 return ((Integer) otherNode.getPriority()).compareTo(priority);
272 }
273
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530274 /**
275 * Clones the current node contents and create a new node.
276 *
Bharat saraswald50c6382016-07-14 21:57:13 +0530277 * @param yangUses YANG uses
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530278 * @return cloned node
279 * @throws CloneNotSupportedException clone is not supported by the referred
280 * node
281 */
janani b23ccc312016-07-14 19:35:22 +0530282 public YangNode clone(YangUses yangUses)
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530283 throws CloneNotSupportedException {
284 YangNode clonedNode = (YangNode) super.clone();
285 if (clonedNode instanceof YangLeavesHolder) {
286 try {
janani b23ccc312016-07-14 19:35:22 +0530287 cloneLeaves((YangLeavesHolder) clonedNode, yangUses);
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530288 } catch (DataModelException e) {
289 throw new CloneNotSupportedException(e.getMessage());
290 }
291 }
292
293 clonedNode.setParent(null);
294 clonedNode.setChild(null);
295 clonedNode.setNextSibling(null);
296 clonedNode.setPreviousSibling(null);
297 return clonedNode;
298 }
299
300 /**
301 * Clones the subtree from the specified source node to the mentioned target
302 * node. The source and target root node cloning is carried out by the
303 * caller.
304 *
305 * @param srcRootNode source node for sub tree cloning
306 * @param dstRootNode destination node where the sub tree needs to be cloned
Bharat saraswald50c6382016-07-14 21:57:13 +0530307 * @param yangUses YANG uses
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530308 * @throws DataModelException data model error
309 */
janani b23ccc312016-07-14 19:35:22 +0530310 public static void cloneSubTree(YangNode srcRootNode, YangNode dstRootNode, YangUses yangUses)
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530311 throws DataModelException {
312
313 YangNode nextNodeToClone = srcRootNode;
314 TraversalType curTraversal;
315
316 YangNode clonedTreeCurNode = dstRootNode;
317 YangNode newNode = null;
318
319 nextNodeToClone = nextNodeToClone.getChild();
320 if (nextNodeToClone == null) {
321 return;
322 } else {
323 /**
324 * Root level cloning is taken care in the caller.
325 */
326 curTraversal = CHILD;
327 }
328
329 /**
330 * Caller ensures the cloning of the root nodes
331 */
332 try {
333 while (nextNodeToClone != srcRootNode) {
334 if (nextNodeToClone == null) {
335 throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
336 }
337 if (curTraversal != PARENT) {
janani b23ccc312016-07-14 19:35:22 +0530338 newNode = nextNodeToClone.clone(yangUses);
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530339 detectCollisionWhileCloning(clonedTreeCurNode, newNode, curTraversal);
340 }
341
342 if (curTraversal == CHILD) {
343
344 /**
345 * add the new node to the cloned tree.
346 */
347 clonedTreeCurNode.addChild(newNode);
348
349 /**
350 * update the cloned tree's traversal current node as the
351 * new node.
352 */
353 clonedTreeCurNode = newNode;
354 } else if (curTraversal == SIBILING) {
355
356 clonedTreeCurNode.addNextSibling(newNode);
357 clonedTreeCurNode = newNode;
358 } else if (curTraversal == PARENT) {
359 if (clonedTreeCurNode instanceof YangLeavesHolder) {
360 updateClonedLeavesUnionEnumRef((YangLeavesHolder) clonedTreeCurNode);
361 }
362 clonedTreeCurNode = clonedTreeCurNode.getParent();
363 }
364
365 if (curTraversal != PARENT && nextNodeToClone.getChild() != null) {
366 curTraversal = CHILD;
367
368 /**
369 * update the traversal's current node.
370 */
371 nextNodeToClone = nextNodeToClone.getChild();
372
373 } else if (nextNodeToClone.getNextSibling() != null) {
374
375 curTraversal = SIBILING;
376
377 nextNodeToClone = nextNodeToClone.getNextSibling();
378 } else {
379 curTraversal = PARENT;
380 nextNodeToClone = nextNodeToClone.getParent();
381 }
382 }
383 } catch (CloneNotSupportedException e) {
384 throw new DataModelException("Failed to clone the tree");
385 }
386
387 }
388
389 /**
390 * Detects collision when the grouping is deep copied to the uses's parent.
391 *
392 * @param currentNode parent/previous sibling node for the new node
393 * @param newNode node which has to be added
394 * @param addAs traversal type of the node
395 * @throws DataModelException data model error
396 */
397 private static void detectCollisionWhileCloning(YangNode currentNode, YangNode newNode, TraversalType addAs)
398 throws DataModelException {
399 if (!(currentNode instanceof CollisionDetector)
400 || !(newNode instanceof Parsable)) {
401 throw new DataModelException("Node in data model tree does not support collision detection");
402 }
403
404 CollisionDetector collisionDetector = (CollisionDetector) currentNode;
405 Parsable parsable = (Parsable) newNode;
406 if (addAs == TraversalType.CHILD) {
407 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
408 } else if (addAs == TraversalType.SIBILING) {
409 currentNode = currentNode.getParent();
410 if (!(currentNode instanceof CollisionDetector)) {
411 throw new DataModelException("Node in data model tree does not support collision detection");
412 }
413 collisionDetector = (CollisionDetector) currentNode;
414 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
415 } else {
416 throw new DataModelException("Errored tree cloning");
417 }
418
419 }
420
421 /**
Bharat saraswald50c6382016-07-14 21:57:13 +0530422 * /** Returns true if translation required.
423 *
424 * @return true if translation required
425 */
426 public boolean isToTranslate() {
427 return isToTranslate;
428 }
429
430 /**
431 * Sest true if translation required.
432 *
433 * @param toTranslate true if translation required.
434 */
435 public void setToTranslate(boolean toTranslate) {
436 isToTranslate = toTranslate;
437 }
438
439 /**
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530440 * Adds a new next sibling.
441 *
442 * @param newSibling new sibling to be added
443 * @throws DataModelException data model error
444 */
445 private void addNextSibling(YangNode newSibling)
446 throws DataModelException {
447
448 if (newSibling.getNodeType() == null) {
449 throw new DataModelException("Cloned abstract node cannot be inserted into a tree");
450 }
451
452 if (newSibling.getParent() == null) {
453 /**
454 * Since the siblings needs to have a common parent, set the parent
455 * as the current node's parent
456 */
457 newSibling.setParent(getParent());
458
459 } else {
460 throw new DataModelException("Node is already part of a tree, and cannot be added as a sibling");
461 }
462
463 if (newSibling.getPreviousSibling() == null) {
464 newSibling.setPreviousSibling(this);
465 setNextSibling(newSibling);
466 } else {
467 throw new DataModelException("New sibling to be added is not atomic, it already has a previous sibling");
468 }
469
470 if (newSibling.getChild() != null) {
471 throw new DataModelException("Sibling to be added is not atomic, it already has a child");
472 }
473
474 if (newSibling.getNextSibling() != null) {
475 throw new DataModelException("Sibling to be added is not atomic, it already has a next sibling");
476 }
477 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530478}