blob: 381a39a172173e5733ab88ec88112b69b5794cad [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 /**
67 * Returns the priority of the node.
68 *
69 * @return priority of the node
70 */
71 public int getPriority() {
72 return priority;
73 }
74
75 /**
76 * Sets the priority of the node.
77 *
78 * @param priority of the node
79 */
80 public void setPriority(int priority) {
81 this.priority = priority;
82 }
83
84 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053085 * Returns the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053086 *
87 * @return nodes name
88 */
89 public abstract String getName();
90
91 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053092 * Sets the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053093 *
94 * @param name nodes name
95 */
96 public abstract void setName(String name);
97
98 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053099 * Creates a YANG node object.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530100 */
101 @SuppressWarnings("unused")
102 private YangNode() {
103
104 }
105
106 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530107 * Creates a specific type of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530108 *
109 * @param type of YANG node
110 */
111 protected YangNode(YangNodeType type) {
112 setNodeType(type);
113 }
114
115 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530116 * Returns the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530117 *
118 * @return node type
119 */
120 public YangNodeType getNodeType() {
121 return nodeType;
122 }
123
124 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530125 * Sets the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530126 *
127 * @param nodeType type of node
128 */
129 private void setNodeType(YangNodeType nodeType) {
130 this.nodeType = nodeType;
131 }
132
133 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530134 * Returns the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530135 *
136 * @return parent of node
137 */
138 public YangNode getParent() {
139 return parent;
140 }
141
142 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530143 * Sets the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530144 *
145 * @param parent node
146 */
147 public void setParent(YangNode parent) {
148 this.parent = parent;
149 }
150
151 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530152 * Returns the first child of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530153 *
154 * @return first child of node
155 */
156 public YangNode getChild() {
157 return child;
158 }
159
160 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530161 * Sets the first instance of a child node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530162 *
163 * @param child is only child to be set
164 */
165 public void setChild(YangNode child) {
166 this.child = child;
167 }
168
169 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530170 * Returns the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530171 *
172 * @return next sibling of node
173 */
174 public YangNode getNextSibling() {
175 return nextSibling;
176 }
177
178 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530179 * Sets the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530180 *
181 * @param sibling YANG node
182 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530183 private void setNextSibling(YangNode sibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530184 nextSibling = sibling;
185 }
186
187 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530188 * Returns the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530189 *
190 * @return previous sibling node
191 */
192 public YangNode getPreviousSibling() {
193 return previousSibling;
194 }
195
196 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530197 * Sets the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530198 *
199 * @param previousSibling points to predecessor sibling
200 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530201 private void setPreviousSibling(YangNode previousSibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530202 this.previousSibling = previousSibling;
203 }
204
205 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530206 * Adds a child node, the children sibling list will be sorted based on node
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530207 * type.
208 *
209 * @param newChild refers to a child to be added
210 * @throws DataModelException due to violation in data model rules
211 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530212 public void addChild(YangNode newChild)
213 throws DataModelException {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530214 if (newChild.getNodeType() == null) {
215 throw new DataModelException("Abstract node cannot be inserted into a tree");
216 }
217
218 if (newChild.getParent() == null) {
219 newChild.setParent(this);
220 } else if (newChild.getParent() != this) {
221 throw new DataModelException("Node is already part of a tree");
222 }
223
224 if (newChild.getChild() != null) {
225 throw new DataModelException("Child to be added is not atomic, it already has a child");
226 }
227
228 if (newChild.getNextSibling() != null) {
229 throw new DataModelException("Child to be added is not atomic, it already has a next sibling");
230 }
231
232 if (newChild.getPreviousSibling() != null) {
233 throw new DataModelException("Child to be added is not atomic, it already has a previous sibling");
234 }
235
236 /* First child to be added */
237 if (getChild() == null) {
238 setChild(newChild);
239 return;
240 }
241
242 YangNode curNode;
243 curNode = getChild();
244
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530245 /*
246 * Get the predecessor child of new child
247 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530248 while (curNode.getNextSibling() != null) {
Vinod Kumar S38046502016-03-23 15:30:27 +0530249
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530250 curNode = curNode.getNextSibling();
251 }
252
253 /* If the new node needs to be the last child */
254 if (curNode.getNextSibling() == null) {
255 curNode.setNextSibling(newChild);
256 newChild.setPreviousSibling(curNode);
Vinod Kumar S427d2932016-04-20 13:02:58 +0530257 }
258 }
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530259
Vidyashree Rama1b499062016-07-12 20:52:48 +0530260 @Override
261 public int compareTo(YangNode otherNode) {
262 if (priority == otherNode.getPriority()) {
263 return 1;
264 }
265 return ((Integer) otherNode.getPriority()).compareTo(priority);
266 }
267
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530268 /**
269 * Clones the current node contents and create a new node.
270 *
271 * @return cloned node
272 * @throws CloneNotSupportedException clone is not supported by the referred
273 * node
274 */
janani b23ccc312016-07-14 19:35:22 +0530275 public YangNode clone(YangUses yangUses)
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530276 throws CloneNotSupportedException {
277 YangNode clonedNode = (YangNode) super.clone();
278 if (clonedNode instanceof YangLeavesHolder) {
279 try {
janani b23ccc312016-07-14 19:35:22 +0530280 cloneLeaves((YangLeavesHolder) clonedNode, yangUses);
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530281 } catch (DataModelException e) {
282 throw new CloneNotSupportedException(e.getMessage());
283 }
284 }
285
286 clonedNode.setParent(null);
287 clonedNode.setChild(null);
288 clonedNode.setNextSibling(null);
289 clonedNode.setPreviousSibling(null);
290 return clonedNode;
291 }
292
293 /**
294 * Clones the subtree from the specified source node to the mentioned target
295 * node. The source and target root node cloning is carried out by the
296 * caller.
297 *
298 * @param srcRootNode source node for sub tree cloning
299 * @param dstRootNode destination node where the sub tree needs to be cloned
300 * @throws DataModelException data model error
301 */
janani b23ccc312016-07-14 19:35:22 +0530302 public static void cloneSubTree(YangNode srcRootNode, YangNode dstRootNode, YangUses yangUses)
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530303 throws DataModelException {
304
305 YangNode nextNodeToClone = srcRootNode;
306 TraversalType curTraversal;
307
308 YangNode clonedTreeCurNode = dstRootNode;
309 YangNode newNode = null;
310
311 nextNodeToClone = nextNodeToClone.getChild();
312 if (nextNodeToClone == null) {
313 return;
314 } else {
315 /**
316 * Root level cloning is taken care in the caller.
317 */
318 curTraversal = CHILD;
319 }
320
321 /**
322 * Caller ensures the cloning of the root nodes
323 */
324 try {
325 while (nextNodeToClone != srcRootNode) {
326 if (nextNodeToClone == null) {
327 throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
328 }
329 if (curTraversal != PARENT) {
janani b23ccc312016-07-14 19:35:22 +0530330 newNode = nextNodeToClone.clone(yangUses);
Vidyashree Rama405d2e62016-07-08 20:45:41 +0530331 detectCollisionWhileCloning(clonedTreeCurNode, newNode, curTraversal);
332 }
333
334 if (curTraversal == CHILD) {
335
336 /**
337 * add the new node to the cloned tree.
338 */
339 clonedTreeCurNode.addChild(newNode);
340
341 /**
342 * update the cloned tree's traversal current node as the
343 * new node.
344 */
345 clonedTreeCurNode = newNode;
346 } else if (curTraversal == SIBILING) {
347
348 clonedTreeCurNode.addNextSibling(newNode);
349 clonedTreeCurNode = newNode;
350 } else if (curTraversal == PARENT) {
351 if (clonedTreeCurNode instanceof YangLeavesHolder) {
352 updateClonedLeavesUnionEnumRef((YangLeavesHolder) clonedTreeCurNode);
353 }
354 clonedTreeCurNode = clonedTreeCurNode.getParent();
355 }
356
357 if (curTraversal != PARENT && nextNodeToClone.getChild() != null) {
358 curTraversal = CHILD;
359
360 /**
361 * update the traversal's current node.
362 */
363 nextNodeToClone = nextNodeToClone.getChild();
364
365 } else if (nextNodeToClone.getNextSibling() != null) {
366
367 curTraversal = SIBILING;
368
369 nextNodeToClone = nextNodeToClone.getNextSibling();
370 } else {
371 curTraversal = PARENT;
372 nextNodeToClone = nextNodeToClone.getParent();
373 }
374 }
375 } catch (CloneNotSupportedException e) {
376 throw new DataModelException("Failed to clone the tree");
377 }
378
379 }
380
381 /**
382 * Detects collision when the grouping is deep copied to the uses's parent.
383 *
384 * @param currentNode parent/previous sibling node for the new node
385 * @param newNode node which has to be added
386 * @param addAs traversal type of the node
387 * @throws DataModelException data model error
388 */
389 private static void detectCollisionWhileCloning(YangNode currentNode, YangNode newNode, TraversalType addAs)
390 throws DataModelException {
391 if (!(currentNode instanceof CollisionDetector)
392 || !(newNode instanceof Parsable)) {
393 throw new DataModelException("Node in data model tree does not support collision detection");
394 }
395
396 CollisionDetector collisionDetector = (CollisionDetector) currentNode;
397 Parsable parsable = (Parsable) newNode;
398 if (addAs == TraversalType.CHILD) {
399 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
400 } else if (addAs == TraversalType.SIBILING) {
401 currentNode = currentNode.getParent();
402 if (!(currentNode instanceof CollisionDetector)) {
403 throw new DataModelException("Node in data model tree does not support collision detection");
404 }
405 collisionDetector = (CollisionDetector) currentNode;
406 collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
407 } else {
408 throw new DataModelException("Errored tree cloning");
409 }
410
411 }
412
413 /**
414 * Adds a new next sibling.
415 *
416 * @param newSibling new sibling to be added
417 * @throws DataModelException data model error
418 */
419 private void addNextSibling(YangNode newSibling)
420 throws DataModelException {
421
422 if (newSibling.getNodeType() == null) {
423 throw new DataModelException("Cloned abstract node cannot be inserted into a tree");
424 }
425
426 if (newSibling.getParent() == null) {
427 /**
428 * Since the siblings needs to have a common parent, set the parent
429 * as the current node's parent
430 */
431 newSibling.setParent(getParent());
432
433 } else {
434 throw new DataModelException("Node is already part of a tree, and cannot be added as a sibling");
435 }
436
437 if (newSibling.getPreviousSibling() == null) {
438 newSibling.setPreviousSibling(this);
439 setNextSibling(newSibling);
440 } else {
441 throw new DataModelException("New sibling to be added is not atomic, it already has a previous sibling");
442 }
443
444 if (newSibling.getChild() != null) {
445 throw new DataModelException("Sibling to be added is not atomic, it already has a child");
446 }
447
448 if (newSibling.getNextSibling() != null) {
449 throw new DataModelException("Sibling to be added is not atomic, it already has a next sibling");
450 }
451 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530452}