blob: 48cf53a2390e97abe1220c891272f608332e2cc3 [file] [log] [blame]
sonu gupta1bb37b82016-11-11 16:51:18 +05301/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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 */
16
17package org.onosproject.yms.app.ydt;
18
sonu gupta1bb37b82016-11-11 16:51:18 +053019import org.onosproject.yangutils.datamodel.YangSchemaNode;
20import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
21import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
22import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
23import org.onosproject.yms.app.ydt.exceptions.YdtException;
24import org.onosproject.yms.ydt.YdtContext;
25import org.onosproject.yms.ydt.YdtContextOperationType;
26import org.onosproject.yms.ydt.YdtExtendedInfoType;
27import org.onosproject.yms.ydt.YdtType;
28
29import java.util.ArrayList;
30import java.util.HashMap;
31import java.util.HashSet;
32import java.util.List;
33import java.util.Map;
34import java.util.Set;
35
36import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg;
37
38/**
39 * Represents implementation of interfaces to build and obtain YANG data tree
40 * which is data (sub)instance representation, abstract of protocol.
41 */
42public abstract class YdtNode<T> implements YdtExtendedContext, Cloneable {
43
sonu guptaeff184b2016-11-24 12:43:49 +053044 // YDT formatted error string
45 private static final String FMT_NON_LIST_STR =
sonu gupta1bb37b82016-11-11 16:51:18 +053046 "List of key cannot be created for leaf and leaf-list %s node.";
47 private static final String FMT_VAL_N =
48 "Value cannot be set in non leaf %s node.";
49 private static final String FMT_VAL_NS =
50 "ValueSet cannot be set in non leaf-list %s node.";
51 private static final String FMT_VAL_IN =
52 "Value cannot be invoke from non leaf %s node.";
53 private static final String FMT_VAL_INS =
54 "ValueSet cannot be invoke from non leaf-list %s node";
sonu gupta1bb37b82016-11-11 16:51:18 +053055
sonu guptaeff184b2016-11-24 12:43:49 +053056 // YDT error string
sonu gupta1bb37b82016-11-11 16:51:18 +053057 private static final String E_EXIST = "Node is already part of a tree";
58 private static final String E_ATOMIC =
59 "Child to be added is not atomic, it already has a child";
60 private static final String E_SIB =
61 "Child to be added is not atomic, it already has a next sibling";
62 private static final String E_PRE =
63 "Child to be added is not atomic, it already has a previous " +
64 "sibling";
65 private static final String E_SUPPORT = "Requested node type not supported";
66
67 /*
68 * Parent reference.
69 */
70 private YdtNode parent;
71
72 /*
73 * First child reference.
74 */
75 private YdtNode child;
76
77 /*
78 * Next sibling reference.
79 */
80 private YdtNode nextSibling;
81
82 /*
83 * Previous sibling reference.
84 */
85 private YdtNode previousSibling;
86
87 /*
88 * Last child reference.
89 */
90 private YdtNode lastChild;
91
92 /*
93 * Type of node.
94 */
sonu guptaeff184b2016-11-24 12:43:49 +053095 private final YdtType ydtType;
sonu gupta1bb37b82016-11-11 16:51:18 +053096
97 /*
98 * Flag to keep the track of context switch,
99 * if set then traverse back to parent in YDT app tree else no need.
100 */
101 private boolean isContextSwitch;
102
103 /*
104 * YDT extended information.
105 */
106 private T ydtExtendedInfo;
107
108 /*
109 * YDT extended information type.
110 */
111 private YdtExtendedInfoType ydtExtendedInfoType;
112
113 /*
sonu guptaeff184b2016-11-24 12:43:49 +0530114 * Ydt map to keep the track of node added under current parent node.
sonu gupta1bb37b82016-11-11 16:51:18 +0530115 */
sonu guptaeff184b2016-11-24 12:43:49 +0530116 final Map<YangSchemaNodeIdentifier, YdtNode<T>> ydtNodeMap =
117 new HashMap<>();
118
119 /*
120 * Ydt map to keep the track of multi instance node added under current
121 * parent node.
122 */
123 private final Map<YangSchemaNodeIdentifier,
124 List<YdtNode<YdtMultiInstanceNode>>> ydtMultiInsMap =
sonu gupta1bb37b82016-11-11 16:51:18 +0530125 new HashMap<>();
126
127 /*
128 * Reference for data-model schema node.
129 */
130 private YangSchemaNode yangSchemaNode;
131
132 /*
133 * Reference for ydt node operation type.
134 */
135 private YdtContextOperationType ydtContextOperationType;
136
137 /*
sonu gupta1bb37b82016-11-11 16:51:18 +0530138 * Ydt map to keep the track of application information object
139 * with respective type.
140 */
141 private final Map<AppType, Object> ydtAppInfoMap = new HashMap<>();
142
143 private YdtContext clonedNode;
144
145 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530146 * Creates a specific type of node.
147 *
148 * @param type of YDT node
149 * @param node schema node
150 */
151 YdtNode(YdtType type, YangSchemaNode node) {
152 ydtType = type;
153 yangSchemaNode = node;
154 }
155
156 /**
157 * Creates a specific type of node.
158 *
159 * @param type of YDT node
160 */
161 YdtNode(YdtType type) {
162 ydtType = type;
163 }
164
165 /**
sonu gupta1bb37b82016-11-11 16:51:18 +0530166 * Returns the cloned ydt node.
167 *
168 * @return clonedNode cloned ydt node
169 */
170 public YdtContext getClonedNode() {
171 return clonedNode;
172 }
173
174 /**
175 * Sets the cloned node.
176 *
177 * @param clonedNode cloned ydt node
178 */
179 public void setClonedNode(YdtContext clonedNode) {
180 this.clonedNode = clonedNode;
181 }
182
183 @Override
184 public String getName() {
sonu guptaeff184b2016-11-24 12:43:49 +0530185 return yangSchemaNode.getName();
sonu gupta1bb37b82016-11-11 16:51:18 +0530186 }
187
188 @Override
189 public String getNamespace() {
sonu guptaeff184b2016-11-24 12:43:49 +0530190 return yangSchemaNode.getNameSpace().getModuleNamespace();
191 }
192
193 @Override
194 public String getModuleNameAsNameSpace() {
195 return yangSchemaNode.getNameSpace().getModuleName();
sonu gupta1bb37b82016-11-11 16:51:18 +0530196 }
197
198 @Override
199 public <T> T getYdtContextExtendedInfo() {
200 return (T) ydtExtendedInfo;
201 }
202
203 @Override
204 public YdtExtendedInfoType getYdtExtendedInfoType() {
205 return ydtExtendedInfoType;
206 }
207
208 @Override
209 public YdtType getYdtType() {
210 return ydtType;
211 }
212
213 @Override
214 public YdtNode getParent() {
215 return parent;
216 }
217
218 @Override
219 public YdtNode getFirstChild() {
220 return child;
221 }
222
223 @Override
224 public YdtNode getNextSibling() {
225 return nextSibling;
226 }
227
228 public YangSchemaNode getYangSchemaNode() {
229 return yangSchemaNode;
230 }
231
232 @Override
233 public YdtNode getLastChild() {
234 return lastChild;
235 }
236
237 @Override
238 public Object getAppInfo(AppType appType) {
239 return ydtAppInfoMap.get(appType);
240 }
241
242 @Override
243 public void addAppInfo(AppType appType, Object object) {
244 ydtAppInfoMap.put(appType, object);
245 }
246
sonu guptaeff184b2016-11-24 12:43:49 +0530247 /**
248 * Returns child schema node context information. It is used by YMS to
249 * obtain the child schema corresponding to data node identifier.
250 *
251 * @param id represents a identifier of YANG data tree node
252 * @return YANG data node context information
253 * @throws YdtException when user requested node schema doesn't exist
254 */
sonu gupta1bb37b82016-11-11 16:51:18 +0530255 public YangSchemaNodeContextInfo getSchemaNodeContextInfo(
sonu guptaeff184b2016-11-24 12:43:49 +0530256 YangSchemaNodeIdentifier id) throws YdtException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530257 try {
258 return getYangSchemaNode().getChildSchema(id);
259 } catch (DataModelException e) {
sonu guptaeff184b2016-11-24 12:43:49 +0530260 throw new YdtException(e.getLocalizedMessage());
sonu gupta1bb37b82016-11-11 16:51:18 +0530261 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530262 }
263
264 /**
265 * Adds the given value to the non single instance leaf node.
266 * <p>
267 * This default implementation throws an exception stating that
268 * the value cannot be added. Subclasses may override this method
269 * to provide the correct behavior for their specific implementation.
270 *
271 * @param value value in a single instance node
272 */
sonu guptaeff184b2016-11-24 12:43:49 +0530273 public void addValue(String value) throws YdtException {
274 throw new YdtException(errorMsg(FMT_VAL_N, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530275 }
276
277 /**
278 * Creates the list of key element's of multi instance node.
sonu guptaeff184b2016-11-24 12:43:49 +0530279 * This will not be applicable on leaf and leaf-list node.
280 *
281 * @throws YdtException when user requested multi instance node is missing
282 * any of the key element in request or requested
283 * node is of type other then multi instance node
sonu gupta1bb37b82016-11-11 16:51:18 +0530284 */
sonu guptaeff184b2016-11-24 12:43:49 +0530285 public void createKeyNodeList() throws YdtException {
286 throw new YdtException(errorMsg(FMT_NON_LIST_STR, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530287 }
288
289 /**
290 * Adds the given value to the non single instance leaf node.
291 * <p>
292 * This default implementation throws an exception stating that
293 * the value cannot be added. Subclasses may override this method
294 * to provide the correct behavior for their specific implementation.
295 * This will be applicable in case of call from SBI so no need
296 * to validate the value.
297 *
sonu guptaeff184b2016-11-24 12:43:49 +0530298 * @param value value in a single instance leaf node
299 * @param isKeyLeaf true, for key leaf; false non key leaf
sonu gupta1bb37b82016-11-11 16:51:18 +0530300 */
sonu guptaeff184b2016-11-24 12:43:49 +0530301 public void addValueWithoutValidation(String value, boolean isKeyLeaf)
302 throws YdtException {
303 throw new YdtException(errorMsg(FMT_VAL_N, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530304 }
305
306 /**
307 * Adds the given valueSet to the non multi instance leaf node.
308 * <p>
309 * This default implementation throws an exception stating that
310 * the value cannot be added. Subclasses may override this method
311 * to provide the correct behavior for their specific implementation.
312 *
313 * @param valueSet valueSet in a multi instance leaf node
314 */
sonu guptaeff184b2016-11-24 12:43:49 +0530315 public void addValueSet(Set<String> valueSet) throws YdtException {
316 throw new YdtException(errorMsg(FMT_VAL_NS, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530317 }
318
319 /**
320 * Adds the given valueSet to the non multi instance leaf node.
321 * <p>
322 * This default implementation throws an exception stating that
323 * the value cannot be added. Subclasses may override this method
324 * to provide the correct behavior for their specific implementation.
325 * This will be applicable in case of call from SBI so no need
326 * to validate the value.
327 *
328 * @param valueSet valueSet in a multi instance leaf node
329 */
sonu guptaeff184b2016-11-24 12:43:49 +0530330 public void addValueSetWithoutValidation(Set<String> valueSet)
331 throws YdtException {
332 throw new YdtException(errorMsg(FMT_VAL_NS, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530333 }
334
335 /**
336 * Validates requested node allowed to have duplicate entry or not.
337 * <p>
338 * This default implementation throws an exception stating that
339 * the duplicate entry found. Subclasses may override this method
340 * to provide the correct behavior for their specific implementation.
341 */
sonu guptaeff184b2016-11-24 12:43:49 +0530342 void validDuplicateEntryProcessing() throws YdtException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530343 }
344
345 /**
346 * Returns already existing YdtNode in Ydt tree with same nodeIdentifier.
347 *
348 * @param id represents a identifier of YANG data tree node
349 * @return YDT node
sonu guptaeff184b2016-11-24 12:43:49 +0530350 * @throws YdtException when user requested node already part of YDT tree.
sonu gupta1bb37b82016-11-11 16:51:18 +0530351 */
sonu guptaeff184b2016-11-24 12:43:49 +0530352 public YdtNode getCollidingChild(YangSchemaNodeIdentifier id)
353 throws YdtException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530354
355 // Find the key in YDT map for getting the colliding node.
sonu guptaeff184b2016-11-24 12:43:49 +0530356 YdtNode collidingChild = ydtNodeMap.get(id);
sonu gupta1bb37b82016-11-11 16:51:18 +0530357
358 /*
359 * If colliding child exist then process colliding node in respective
360 * YDT node type.
361 */
362 if (collidingChild != null) {
sonu guptaeff184b2016-11-24 12:43:49 +0530363 collidingChild.validDuplicateEntryProcessing();
364 return collidingChild;
sonu gupta1bb37b82016-11-11 16:51:18 +0530365 }
366
367 return null;
368 }
369
370 /**
sonu gupta1bb37b82016-11-11 16:51:18 +0530371 * Sets the parent of node.
372 *
373 * @param parent node
374 */
375 public void setParent(YdtNode parent) {
376 this.parent = parent;
377 }
378
379 /**
380 * Sets the first instance of a child node.
381 *
382 * @param child is only child to be set
383 */
384 public void setChild(YdtNode child) {
385 this.child = child;
386 }
387
388 /**
389 * Sets the next sibling of node.
390 *
391 * @param sibling YANG node
392 */
393 public void setNextSibling(YdtNode sibling) {
394 nextSibling = sibling;
395 }
396
397 /**
398 * Returns the previous sibling of a node.
399 *
400 * @return previous sibling of a node
401 */
402 public YdtNode getPreviousSibling() {
403 return previousSibling;
404 }
405
406 /**
407 * Sets the previous sibling.
408 *
409 * @param previousSibling points to predecessor sibling
410 */
411 public void setPreviousSibling(YdtNode previousSibling) {
412 this.previousSibling = previousSibling;
413 }
414
415 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530416 public String getValue() throws YdtException {
417 throw new YdtException(errorMsg(FMT_VAL_IN, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530418 }
419
420 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530421 public Set<String> getValueSet() throws YdtException {
422 throw new YdtException(errorMsg(FMT_VAL_INS, getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530423 }
424
425 /**
426 * Sets the data-model node reference for of a given node.
427 *
428 * @param yangSchemaNode YANG data node
429 */
430 public void setYangSchemaNode(YangSchemaNode yangSchemaNode) {
431 this.yangSchemaNode = yangSchemaNode;
432 }
433
434 /**
435 * Sets the last instance of a child node.
436 *
437 * @param child is last child to be set
438 */
439 public void setLastChild(YdtNode child) {
440 lastChild = child;
441 }
442
sonu gupta1bb37b82016-11-11 16:51:18 +0530443
444 /**
445 * Adds a child node.
446 * The children sibling list will be sorted based on node
447 * type. This will add single child or sub-tree based on isAtomic flag.
448 *
449 * @param newChild refers to a new child to be added
450 * @param isAtomic boolean flag to maintain atomicity of the current node
451 * @throws YdtException in case of violation of any YDT rule
452 */
453 public void addChild(YdtContext newChild, boolean isAtomic)
454 throws YdtException {
455
456 if (!(newChild instanceof YdtNode)) {
sonu guptaeff184b2016-11-24 12:43:49 +0530457 throw new YdtException(errorMsg(E_SUPPORT));
sonu gupta1bb37b82016-11-11 16:51:18 +0530458 }
459
460 YdtNode node = (YdtNode) newChild;
461
462 if (node.getParent() == null) {
463 node.setParent(this);
464 } else if (!node.getParent().equals(this)) {
sonu guptaeff184b2016-11-24 12:43:49 +0530465 throw new YdtException(E_EXIST);
sonu gupta1bb37b82016-11-11 16:51:18 +0530466 }
467
468 if (node.getFirstChild() != null && isAtomic) {
sonu guptaeff184b2016-11-24 12:43:49 +0530469 throw new YdtException(E_ATOMIC);
sonu gupta1bb37b82016-11-11 16:51:18 +0530470 }
471
472 if (node.getNextSibling() != null) {
sonu guptaeff184b2016-11-24 12:43:49 +0530473 throw new YdtException(E_SIB);
sonu gupta1bb37b82016-11-11 16:51:18 +0530474 }
475
476 if (node.getPreviousSibling() != null) {
sonu guptaeff184b2016-11-24 12:43:49 +0530477 throw new YdtException(E_PRE);
sonu gupta1bb37b82016-11-11 16:51:18 +0530478 }
479
480 // If new node needs to be added as first child.
481 if (getFirstChild() == null) {
482 setChild(node);
483 setLastChild(node);
484 return;
485 }
486
487 // If new node needs to be added as last child.
488 YdtNode curNode = getLastChild();
489 curNode.setNextSibling(node);
490 node.setPreviousSibling(curNode);
491 setLastChild(node);
492 }
493
494 @Override
495 public YdtContextOperationType getYdtContextOperationType() {
496 return ydtContextOperationType;
497 }
498
499 /**
500 * Sets type of yang data tree node operation.
501 *
502 * @param opType type of yang data tree node operation
503 */
504 public void setYdtContextOperationType(YdtContextOperationType opType) {
505 ydtContextOperationType = opType;
506 }
507
508 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530509 * Updates ydt maps of current context parent node.
510 *
511 * @param node ydt node for which map need to be updated
512 */
513 void updateYdtMap(YdtNode node) {
514
515 YangSchemaNodeIdentifier id = node.getYangSchemaNode()
516 .getYangSchemaNodeIdentifier();
517 /*
518 * If node to be added is of type multi instance node(list) then multi
519 * instance node to be updated
520 */
521 if (node.getYdtType() == YdtType.MULTI_INSTANCE_NODE) {
522 updateMultiInsMap(id, node);
523 }
524
525 /*
526 * If entry for multi instance node is already there with same id then
527 * existing entry will be overwritten by the new entry.
528 */
529 ydtNodeMap.put(id, node);
530 }
531
532 /**
533 * Updates ydt multi instance map of current context parent node.
sonu gupta1bb37b82016-11-11 16:51:18 +0530534 *
535 * @param id object node identifier
536 * @param node ydt node for which map need to be updated
537 */
sonu guptaeff184b2016-11-24 12:43:49 +0530538 private void updateMultiInsMap(YangSchemaNodeIdentifier id, YdtNode node) {
539
540 List<YdtNode<YdtMultiInstanceNode>> list = ydtMultiInsMap.get(id);
sonu gupta1bb37b82016-11-11 16:51:18 +0530541 if (list == null) {
542 list = new ArrayList<>();
sonu guptaeff184b2016-11-24 12:43:49 +0530543 ydtMultiInsMap.put(id, list);
sonu gupta1bb37b82016-11-11 16:51:18 +0530544 }
545 list.add(node);
546 }
547
548 /**
549 * Returns the flag for node if context switch.
550 *
551 * @return isContextSwitch flag of a node
552 */
553 public boolean getAppContextSwitch() {
554 return isContextSwitch;
555 }
556
557 /**
558 * Sets the flag to keep the track of context switch.
559 * If it is set then when YDT get traverToParent then
560 * traverse back to parent in YDT application tree.
561 */
562 public void setAppContextSwitch() {
563 isContextSwitch = true;
564 }
565
566 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530567 * Validates all multi Instance nodes inside current context.
sonu gupta1bb37b82016-11-11 16:51:18 +0530568 */
sonu guptaeff184b2016-11-24 12:43:49 +0530569 public void validateMultiInstanceNode() throws YdtException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530570
571 // Set for checking whether input string is unique or not.
572 Set<String> keyStringSet = new HashSet<>();
573
sonu guptaeff184b2016-11-24 12:43:49 +0530574 if (ydtMultiInsMap.size() != 0) {
575 /*
576 * Iterating over values in map and find multi instance node list
577 * only.
578 */
579 for (List<YdtNode<YdtMultiInstanceNode>> ydtNodeList :
580 ydtMultiInsMap.values()) {
581 try {
582 ydtNodeList.get(0).validateInstances(keyStringSet,
583 ydtNodeList);
584 } catch (YdtException e) {
585 throw new YdtException(e.getLocalizedMessage());
sonu gupta1bb37b82016-11-11 16:51:18 +0530586 }
587 }
588 }
589 }
590
591 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530592 * Validates the given list of instances by verifying the allowed
593 * instance count and key element uniqueness.
594 * <p>
595 * This default implementation do nothing if requested node is of type
596 * other then multiInstanceNode. Subclasses may override this method
597 * to provide the correct behavior for their specific implementation.
sonu gupta1bb37b82016-11-11 16:51:18 +0530598 *
sonu guptaeff184b2016-11-24 12:43:49 +0530599 * @param keyStringSet set to validate the key element uniqueness
600 * @param ydtNodeList list of instance's of same list
sonu gupta1bb37b82016-11-11 16:51:18 +0530601 */
sonu guptaeff184b2016-11-24 12:43:49 +0530602 void validateInstances(Set<String> keyStringSet,
603 List<YdtNode<YdtMultiInstanceNode>>
604 ydtNodeList) throws YdtException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530605
sonu gupta1bb37b82016-11-11 16:51:18 +0530606 }
607
608 /**
609 * Clones the current node contents and create a new node.
610 *
611 * @return cloned node
612 * @throws CloneNotSupportedException clone is not supported
613 * by the referred node
614 */
615 public YdtNode clone() throws CloneNotSupportedException {
616 YdtNode clonedNode = (YdtNode) super.clone();
617 clonedNode.setPreviousSibling(null);
618 clonedNode.setNextSibling(null);
619 clonedNode.setParent(null);
620 clonedNode.setChild(null);
621 clonedNode.setLastChild(null);
622 return clonedNode;
623 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530624}