blob: 0413e65367b32abfea0496e46b1585006db2117f [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;
Vinod Kumar S427d2932016-04-20 13:02:58 +053019import org.onosproject.yangutils.translator.tojava.TraversalType;
20
21import static org.onosproject.yangutils.translator.tojava.TraversalType.CHILD;
22import static org.onosproject.yangutils.translator.tojava.TraversalType.PARENT;
23import static org.onosproject.yangutils.translator.tojava.TraversalType.SIBILING;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053024
25/**
Bharat saraswald9822e92016-04-05 15:13:44 +053026 * Represents base class of a node in data model tree.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053027 */
Vinod Kumar S427d2932016-04-20 13:02:58 +053028public abstract class YangNode
29 implements Cloneable {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053030
Vinod Kumar S67e7be62016-02-11 20:13:28 +053031 /**
32 * Type of node.
33 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053034 private YangNodeType nodeType;
35
Vinod Kumar S67e7be62016-02-11 20:13:28 +053036 /**
37 * Parent reference.
38 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053039 private YangNode parent;
40
Vinod Kumar S67e7be62016-02-11 20:13:28 +053041 /**
42 * First child reference.
43 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053044 private YangNode child;
45
Vinod Kumar S67e7be62016-02-11 20:13:28 +053046 /**
47 * Next sibling reference.
48 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053049 private YangNode nextSibling;
50
Vinod Kumar S67e7be62016-02-11 20:13:28 +053051 /**
52 * Previous sibling reference.
53 */
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053054 private YangNode previousSibling;
55
56 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053057 * Returns the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053058 *
59 * @return nodes name
60 */
61 public abstract String getName();
62
63 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053064 * Sets the nodes name.
Vinod Kumar S38046502016-03-23 15:30:27 +053065 *
66 * @param name nodes name
67 */
68 public abstract void setName(String name);
69
70 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053071 * Creates a YANG node object.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053072 */
73 @SuppressWarnings("unused")
74 private YangNode() {
75
76 }
77
78 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053079 * Creates a specific type of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053080 *
81 * @param type of YANG node
82 */
83 protected YangNode(YangNodeType type) {
84 setNodeType(type);
85 }
86
87 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053088 * Returns the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053089 *
90 * @return node type
91 */
92 public YangNodeType getNodeType() {
93 return nodeType;
94 }
95
96 /**
Bharat saraswald9822e92016-04-05 15:13:44 +053097 * Sets the node type.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +053098 *
99 * @param nodeType type of node
100 */
101 private void setNodeType(YangNodeType nodeType) {
102 this.nodeType = nodeType;
103 }
104
105 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530106 * Returns the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530107 *
108 * @return parent of node
109 */
110 public YangNode getParent() {
111 return parent;
112 }
113
114 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530115 * Sets the parent of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530116 *
117 * @param parent node
118 */
119 public void setParent(YangNode parent) {
120 this.parent = parent;
121 }
122
123 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530124 * Returns the first child of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530125 *
126 * @return first child of node
127 */
128 public YangNode getChild() {
129 return child;
130 }
131
132 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530133 * Sets the first instance of a child node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530134 *
135 * @param child is only child to be set
136 */
137 public void setChild(YangNode child) {
138 this.child = child;
139 }
140
141 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530142 * Returns the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530143 *
144 * @return next sibling of node
145 */
146 public YangNode getNextSibling() {
147 return nextSibling;
148 }
149
150 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530151 * Sets the next sibling of node.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530152 *
153 * @param sibling YANG node
154 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530155 private void setNextSibling(YangNode sibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530156 nextSibling = sibling;
157 }
158
159 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530160 * Returns the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530161 *
162 * @return previous sibling node
163 */
164 public YangNode getPreviousSibling() {
165 return previousSibling;
166 }
167
168 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530169 * Sets the previous sibling.
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530170 *
171 * @param previousSibling points to predecessor sibling
172 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530173 private void setPreviousSibling(YangNode previousSibling) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530174 this.previousSibling = previousSibling;
175 }
176
177 /**
Bharat saraswald9822e92016-04-05 15:13:44 +0530178 * Adds a child node, the children sibling list will be sorted based on node
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530179 * type.
180 *
181 * @param newChild refers to a child to be added
182 * @throws DataModelException due to violation in data model rules
183 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530184 public void addChild(YangNode newChild)
185 throws DataModelException {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530186 if (newChild.getNodeType() == null) {
187 throw new DataModelException("Abstract node cannot be inserted into a tree");
188 }
189
190 if (newChild.getParent() == null) {
191 newChild.setParent(this);
192 } else if (newChild.getParent() != this) {
193 throw new DataModelException("Node is already part of a tree");
194 }
195
196 if (newChild.getChild() != null) {
197 throw new DataModelException("Child to be added is not atomic, it already has a child");
198 }
199
200 if (newChild.getNextSibling() != null) {
201 throw new DataModelException("Child to be added is not atomic, it already has a next sibling");
202 }
203
204 if (newChild.getPreviousSibling() != null) {
205 throw new DataModelException("Child to be added is not atomic, it already has a previous sibling");
206 }
207
208 /* First child to be added */
209 if (getChild() == null) {
210 setChild(newChild);
211 return;
212 }
213
214 YangNode curNode;
215 curNode = getChild();
216
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530217 /*
218 * Get the predecessor child of new child
219 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530220 while (curNode.getNextSibling() != null) {
Vinod Kumar S38046502016-03-23 15:30:27 +0530221
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530222 curNode = curNode.getNextSibling();
223 }
224
225 /* If the new node needs to be the last child */
226 if (curNode.getNextSibling() == null) {
227 curNode.setNextSibling(newChild);
228 newChild.setPreviousSibling(curNode);
Vinod Kumar S427d2932016-04-20 13:02:58 +0530229 }
230 }
231
232 /**
233 * Clone the current node contents and create a new node.
234 *
235 * @return cloned node
236 * @throws CloneNotSupportedException clone is not supported by the referred node
237 */
238 public YangNode clone()
239 throws CloneNotSupportedException {
240 YangNode clonedNode = (YangNode) super.clone();
241 clonedNode.setParent(null);
242 clonedNode.setChild(null);
243 clonedNode.setNextSibling(null);
244 clonedNode.setPreviousSibling(null);
245 return clonedNode;
246 }
247
248 /**
249 * Clone the subtree from the specified source node to the mentioned target node.
250 * The source and target root node cloning is carried out by the caller.
251 *
252 * @param srcRootNode source node for sub tree cloning
253 * @param dstRootNode destination node where the sub tree needs to be cloned
254 * @throws DataModelException data model error
255 */
256 public static void cloneSubTree(YangNode srcRootNode, YangNode dstRootNode)
257 throws DataModelException {
258
259 YangNode nextNodeToClone = srcRootNode;
260 TraversalType curTraversal;
261
262
263 YangNode clonedTreeCurNode = dstRootNode;
264 YangNode newNode = null;
265
266 nextNodeToClone = nextNodeToClone.getChild();
267 if (nextNodeToClone == null) {
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530268 return;
Vinod Kumar S427d2932016-04-20 13:02:58 +0530269 } else {
270 /**
271 * Root level cloning is taken care in the caller.
272 */
273 curTraversal = CHILD;
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530274 }
275
Vinod Kumar S427d2932016-04-20 13:02:58 +0530276 /**
277 * Caller ensures the cloning of the root nodes
Vinod Kumar S38046502016-03-23 15:30:27 +0530278 */
Vinod Kumar S427d2932016-04-20 13:02:58 +0530279 try {
280 while (nextNodeToClone != srcRootNode) {
281 if (nextNodeToClone == null) {
282 throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
283 }
284
285 if (curTraversal == CHILD) {
286 newNode = nextNodeToClone.clone();
287
288 /**
289 * add the new node to the cloned tree.
290 */
291 clonedTreeCurNode.addChild(newNode);
292
293 /**
294 * update the cloned tree's travesal current node as the new node.
295 */
296 clonedTreeCurNode = newNode;
297 } else if (curTraversal == SIBILING) {
298 newNode = nextNodeToClone.clone();
299
300 clonedTreeCurNode.addNextSibling(newNode);
301 clonedTreeCurNode = newNode;
302 } else if (curTraversal == PARENT) {
303 clonedTreeCurNode = clonedTreeCurNode.getParent();
304 }
305
306 if (curTraversal != PARENT && nextNodeToClone.getChild() != null) {
307 curTraversal = CHILD;
308
309 /**
310 * update the traversal's current node.
311 */
312 nextNodeToClone = nextNodeToClone.getChild();
313
314 } else if (nextNodeToClone.getNextSibling() != null) {
315
316 curTraversal = SIBILING;
317
318 nextNodeToClone = nextNodeToClone.getNextSibling();
319 } else {
320 curTraversal = PARENT;
321 nextNodeToClone = nextNodeToClone.getParent();
322 }
323 }
324 } catch (CloneNotSupportedException e) {
325 throw new DataModelException("Failed to clone the tree");
326 }
327
328 }
329
330 /**
331 * Add a new next sibling.
332 *
333 * @param newSibling new sibling to be added
334 * @throws DataModelException data model error
335 */
336 private void addNextSibling(YangNode newSibling)
337 throws DataModelException {
338
339 if (newSibling.getNodeType() == null) {
340 throw new DataModelException("Cloned abstract node cannot be inserted into a tree");
341 }
342
343 if (newSibling.getParent() == null) {
344 /**
345 * Since the siblings needs to have a common parent, set the parent as the current node's parent
346 */
347 newSibling.setParent(this.getParent());
348
349 } else {
350 throw new DataModelException("Node is already part of a tree, and cannot be added as a sibling");
351 }
352
353 if (newSibling.getPreviousSibling() == null) {
354 newSibling.setPreviousSibling(this);
355 setNextSibling(newSibling);
356 } else {
357 throw new DataModelException("New sibling to be added is not atomic, it already has a previous sibling");
358 }
359
360 if (newSibling.getChild() != null) {
361 throw new DataModelException("Sibling to be added is not atomic, it already has a child");
362 }
363
364 if (newSibling.getNextSibling() != null) {
365 throw new DataModelException("Sibling to be added is not atomic, it already has a next sibling");
366 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530367 }
Vinod Kumar S8c4e6492016-02-05 20:21:19 +0530368}