blob: 0c72c61d3ee281d1494ee770cb10fb6681f8a3f2 [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;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053019import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
Vidyashree Rama405d2e62016-07-08 20:45:41 +053020import org.onosproject.yangutils.datamodel.utils.Parsable;
21
22import static org.onosproject.yangutils.datamodel.TraversalType.CHILD;
23import static org.onosproject.yangutils.datamodel.TraversalType.PARENT;
24import static org.onosproject.yangutils.datamodel.TraversalType.SIBILING;
25import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.cloneLeaves;
26import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.updateClonedLeavesUnionEnumRef;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053027
28/**
Bharat saraswald9822e92016-04-05 15:13:44 +053029 * Represents base class of a node in data model tree.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053030 */
Vinod Kumar S427d2932016-04-20 13:02:58 +053031public abstract class YangNode
Vidyashree Rama1b499062016-07-12 20:52:48 +053032 implements Cloneable, Serializable, YangDataNode, Comparable<YangNode> {
Bharat saraswal96dfef02016-06-16 00:29:12 +053033
34 private static final long serialVersionUID = 806201601L;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053035
Vinod Kumar S67e7be62016-02-11 20:13:28 +053036 /**
37 * Type of node.
38 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053039 private YangNodeType nodeType;
40
Vinod Kumar S67e7be62016-02-11 20:13:28 +053041 /**
42 * Parent reference.
43 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053044 private YangNode parent;
45
Vinod Kumar S67e7be62016-02-11 20:13:28 +053046 /**
47 * First child reference.
48 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053049 private YangNode child;
50
Vinod Kumar S67e7be62016-02-11 20:13:28 +053051 /**
52 * Next sibling reference.
53 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053054 private YangNode nextSibling;
55
Vinod Kumar S67e7be62016-02-11 20:13:28 +053056 /**
57 * Previous sibling reference.
58 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053059 private YangNode previousSibling;
60
61 /**
Vidyashree Rama1b499062016-07-12 20:52:48 +053062 * Priority of the node.
63 */
64 private int priority;
65
66 /**
Bharat saraswald50c6382016-07-14 21:57:13 +053067 * Flag if the node is for translation.
68 */
69 private boolean isToTranslate = true;
70
71 /**
Vidyashree Rama1b499062016-07-12 20:52:48 +053072 * Returns the priority of the node.
73 *
74 * @return priority of the node
75 */
76 public int getPriority() {
77 return priority;
78 }
79
80 /**
81 * Sets the priority of the node.
82 *
83 * @param priority of the node
84 */
85 public void setPriority(int priority) {
86 this.priority = priority;
87 }
88
89 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053090 * Returns the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053091 *
92 * @return nodes name
93 */
94 public abstract String getName();
95
96 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053097 * Sets the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053098 *
99 * @param name nodes name
100 */
101 public abstract void setName(String name);
102
103 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530104 * Creates a YANG node object.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530105 */
106 @SuppressWarnings("unused")
107 private YangNode() {
108
109 }
110
111 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530112 * Creates a specific type of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530113 *
114 * @param type of YANG node
115 */
116 protected YangNode(YangNodeType type) {
117 setNodeType(type);
118 }
119
120 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530121 * Returns the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530122 *
123 * @return node type
124 */
125 public YangNodeType getNodeType() {
126 return nodeType;
127 }
128
129 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530130 * Sets the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530131 *
132 * @param nodeType type of node
133 */
134 private void setNodeType(YangNodeType nodeType) {
135 this.nodeType = nodeType;
136 }
137
138 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530139 * Returns the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530140 *
141 * @return parent of node
142 */
143 public YangNode getParent() {
144 return parent;
145 }
146
147 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530148 * Sets the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530149 *
150 * @param parent node
151 */
152 public void setParent(YangNode parent) {
153 this.parent = parent;
154 }
155
156 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530157 * Returns the first child of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530158 *
159 * @return first child of node
160 */
161 public YangNode getChild() {
162 return child;
163 }
164
165 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530166 * Sets the first instance of a child node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530167 *
168 * @param child is only child to be set
169 */
170 public void setChild(YangNode child) {
171 this.child = child;
172 }
173
174 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530175 * Returns the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530176 *
177 * @return next sibling of node
178 */
179 public YangNode getNextSibling() {
180 return nextSibling;
181 }
182
183 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530184 * Sets the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530185 *
186 * @param sibling YANG node
187 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530188 private void setNextSibling(YangNode sibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530189 nextSibling = sibling;
190 }
191
192 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530193 * Returns the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530194 *
195 * @return previous sibling node
196 */
197 public YangNode getPreviousSibling() {
198 return previousSibling;
199 }
200
201 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530202 * Sets the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530203 *
204 * @param previousSibling points to predecessor sibling
205 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530206 private void setPreviousSibling(YangNode previousSibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530207 this.previousSibling = previousSibling;
208 }
209
210 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530211 * Adds a child node, the children sibling list will be sorted based on node
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530212 * type.
213 *
214 * @param newChild refers to a child to be added
215 * @throws DataModelException due to violation in data model rules
216 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530217 public void addChild(YangNode newChild)
218 throws DataModelException {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530219 if (newChild.getNodeType() == null) {
220 throw new DataModelException("Abstract node cannot be inserted into a tree");
221 }
222
223 if (newChild.getParent() == null) {
224 newChild.setParent(this);
225 } else if (newChild.getParent() != this) {
226 throw new DataModelException("Node is already part of a tree");
227 }
228
229 if (newChild.getChild() != null) {
230 throw new DataModelException("Child to be added is not atomic, it already has a child");
231 }
232
233 if (newChild.getNextSibling() != null) {
234 throw new DataModelException("Child to be added is not atomic, it already has a next sibling");
235 }
236
237 if (newChild.getPreviousSibling() != null) {
238 throw new DataModelException("Child to be added is not atomic, it already has a previous sibling");
239 }
240
241 /* First child to be added */
242 if (getChild() == null) {
243 setChild(newChild);
244 return;
245 }
246
247 YangNode curNode;
248 curNode = getChild();
249
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530250 /*
251 * Get the predecessor child of new child
252 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530253 while (curNode.getNextSibling() != null) {
Vinod Kumar S38046502016-03-23 15:30:27 +0530254
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530255 curNode = curNode.getNextSibling();
256 }
257
258 /* If the new node needs to be the last child */
259 if (curNode.getNextSibling() == null) {
260 curNode.setNextSibling(newChild);
261 newChild.setPreviousSibling(curNode);
Vinod Kumar S427d2932016-04-20 13:02:58 +0530262 }
263 }
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530264
Vidyashree Rama1b499062016-07-12 20:52:48 +0530265 @Override
266 public int compareTo(YangNode otherNode) {
267 if (priority == otherNode.getPriority()) {
268 return 1;
269 }
270 return ((Integer) otherNode.getPriority()).compareTo(priority);
271 }
272
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530273 /**
274 * Clones the current node contents and create a new node.
275 *
Bharat saraswald50c6382016-07-14 21:57:13 +0530276 * @param yangUses YANG uses
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530277 * @return cloned node
278 * @throws CloneNotSupportedException clone is not supported by the referred
279 * node
280 */
janani b23ccc312016-07-14 19:35:22 +0530281 public YangNode clone(YangUses yangUses)
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530282 throws CloneNotSupportedException {
283 YangNode clonedNode = (YangNode) super.clone();
284 if (clonedNode instanceof YangLeavesHolder) {
285 try {
janani b23ccc312016-07-14 19:35:22 +0530286 cloneLeaves((YangLeavesHolder) clonedNode, yangUses);
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530287 } catch (DataModelException e) {
288 throw new CloneNotSupportedException(e.getMessage());
289 }
290 }
291
292 clonedNode.setParent(null);
293 clonedNode.setChild(null);
294 clonedNode.setNextSibling(null);
295 clonedNode.setPreviousSibling(null);
296 return clonedNode;
297 }
298
299 /**
300 * Clones the subtree from the specified source node to the mentioned target
301 * node. The source and target root node cloning is carried out by the
302 * caller.
303 *
304 * @param srcRootNode source node for sub tree cloning
305 * @param dstRootNode destination node where the sub tree needs to be cloned
Bharat saraswald50c6382016-07-14 21:57:13 +0530306 * @param yangUses YANG uses
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530307 * @throws DataModelException data model error
308 */
janani b23ccc312016-07-14 19:35:22 +0530309 public static void cloneSubTree(YangNode srcRootNode, YangNode dstRootNode, YangUses yangUses)
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530310 throws DataModelException {
311
312 YangNode nextNodeToClone = srcRootNode;
313 TraversalType curTraversal;
314
315 YangNode clonedTreeCurNode = dstRootNode;
316 YangNode newNode = null;
317
318 nextNodeToClone = nextNodeToClone.getChild();
319 if (nextNodeToClone == null) {
320 return;
321 } else {
322 /**
323 * Root level cloning is taken care in the caller.
324 */
325 curTraversal = CHILD;
326 }
327
328 /**
329 * Caller ensures the cloning of the root nodes
330 */
331 try {
332 while (nextNodeToClone != srcRootNode) {
333 if (nextNodeToClone == null) {
334 throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
335 }
336 if (curTraversal != PARENT) {
janani b23ccc312016-07-14 19:35:22 +0530337 newNode = nextNodeToClone.clone(yangUses);
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530338 detectCollisionWhileCloning(clonedTreeCurNode, newNode, curTraversal);
339 }
340
341 if (curTraversal == CHILD) {
342
343 /**
344 * add the new node to the cloned tree.
345 */
346 clonedTreeCurNode.addChild(newNode);
347
348 /**
349 * update the cloned tree's traversal current node as the
350 * new node.
351 */
352 clonedTreeCurNode = newNode;
353 } else if (curTraversal == SIBILING) {
354
355 clonedTreeCurNode.addNextSibling(newNode);
356 clonedTreeCurNode = newNode;
357 } else if (curTraversal == PARENT) {
358 if (clonedTreeCurNode instanceof YangLeavesHolder) {
359 updateClonedLeavesUnionEnumRef((YangLeavesHolder) clonedTreeCurNode);
360 }
361 clonedTreeCurNode = clonedTreeCurNode.getParent();
362 }
363
364 if (curTraversal != PARENT && nextNodeToClone.getChild() != null) {
365 curTraversal = CHILD;
366
367 /**
368 * update the traversal's current node.
369 */
370 nextNodeToClone = nextNodeToClone.getChild();
371
372 } else if (nextNodeToClone.getNextSibling() != null) {
373
374 curTraversal = SIBILING;
375
376 nextNodeToClone = nextNodeToClone.getNextSibling();
377 } else {
378 curTraversal = PARENT;
379 nextNodeToClone = nextNodeToClone.getParent();
380 }
381 }
382 } catch (CloneNotSupportedException e) {
383 throw new DataModelException("Failed to clone the tree");
384 }
385
386 }
387
388 /**
389 * Detects collision when the grouping is deep copied to the uses's parent.
390 *
391 * @param currentNode parent/previous sibling node for the new node
392 * @param newNode node which has to be added
393 * @param addAs traversal type of the node
394 * @throws DataModelException data model error
395 */
396 private static void detectCollisionWhileCloning(YangNode currentNode, YangNode newNode, TraversalType addAs)
397 throws DataModelException {
398 if (!(currentNode instanceof CollisionDetector)
399 || !(newNode instanceof Parsable)) {
400 throw new DataModelException("Node in data model tree does not support collision detection");
401 }
402
403 CollisionDetector collisionDetector = (CollisionDetector) currentNode;
404 Parsable parsable = (Parsable) newNode;
405 if (addAs == TraversalType.CHILD) {
406 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
407 } else if (addAs == TraversalType.SIBILING) {
408 currentNode = currentNode.getParent();
409 if (!(currentNode instanceof CollisionDetector)) {
410 throw new DataModelException("Node in data model tree does not support collision detection");
411 }
412 collisionDetector = (CollisionDetector) currentNode;
413 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
414 } else {
415 throw new DataModelException("Errored tree cloning");
416 }
417
418 }
419
420 /**
Bharat saraswald50c6382016-07-14 21:57:13 +0530421 * /** Returns true if translation required.
422 *
423 * @return true if translation required
424 */
425 public boolean isToTranslate() {
426 return isToTranslate;
427 }
428
429 /**
430 * Sest true if translation required.
431 *
432 * @param toTranslate true if translation required.
433 */
434 public void setToTranslate(boolean toTranslate) {
435 isToTranslate = toTranslate;
436 }
437
438 /**
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530439 * Adds a new next sibling.
440 *
441 * @param newSibling new sibling to be added
442 * @throws DataModelException data model error
443 */
444 private void addNextSibling(YangNode newSibling)
445 throws DataModelException {
446
447 if (newSibling.getNodeType() == null) {
448 throw new DataModelException("Cloned abstract node cannot be inserted into a tree");
449 }
450
451 if (newSibling.getParent() == null) {
452 /**
453 * Since the siblings needs to have a common parent, set the parent
454 * as the current node's parent
455 */
456 newSibling.setParent(getParent());
457
458 } else {
459 throw new DataModelException("Node is already part of a tree, and cannot be added as a sibling");
460 }
461
462 if (newSibling.getPreviousSibling() == null) {
463 newSibling.setPreviousSibling(this);
464 setNextSibling(newSibling);
465 } else {
466 throw new DataModelException("New sibling to be added is not atomic, it already has a previous sibling");
467 }
468
469 if (newSibling.getChild() != null) {
470 throw new DataModelException("Sibling to be added is not atomic, it already has a child");
471 }
472
473 if (newSibling.getNextSibling() != null) {
474 throw new DataModelException("Sibling to be added is not atomic, it already has a next sibling");
475 }
476 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530477}