blob: 625f1ed3347be5a399f2b82dcd763cccc1a80eee [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
19import com.google.common.collect.ImmutableMap;
20import org.onosproject.yangutils.datamodel.YangList;
21import org.onosproject.yangutils.datamodel.YangSchemaNode;
22import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
23import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
24import org.onosproject.yms.app.ysr.YangSchemaRegistry;
25import org.onosproject.yms.ydt.YdtContext;
26import org.onosproject.yms.ydt.YdtContextOperationType;
27import org.onosproject.yms.ydt.YdtType;
28import org.onosproject.yms.ydt.YmsOperationType;
29
30import java.util.Iterator;
31import java.util.List;
32import java.util.Map;
33import java.util.Set;
34
35import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_MULTI_INSTANCE_LEAF_NODE;
36import static org.onosproject.yms.app.ydt.AppNodeFactory.getAppContext;
37import static org.onosproject.yms.app.ydt.RequestedCallType.LEAF;
38import static org.onosproject.yms.app.ydt.RequestedCallType.OTHER;
39import static org.onosproject.yms.app.ydt.RequestedCardinality.MULTI_INSTANCE;
40import static org.onosproject.yms.app.ydt.RequestedCardinality.MULTI_INSTANCE_LEAF;
41import static org.onosproject.yms.app.ydt.RequestedCardinality.SINGLE_INSTANCE;
42import static org.onosproject.yms.app.ydt.RequestedCardinality.UNKNOWN;
43import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg;
44import static org.onosproject.yms.app.ydt.YdtNodeFactory.getAppOpTypeFromYdtOpType;
45import static org.onosproject.yms.ydt.YdtContextOperationType.CREATE;
46import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE;
47import static org.onosproject.yms.ydt.YdtContextOperationType.MERGE;
48import static org.onosproject.yms.ydt.YdtContextOperationType.REMOVE;
49import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_LEAF_VALUE_NODE;
50import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_NODE;
51
52/**
53 * Represents YANG request work bench which contains all parameters for
54 * request handling and methods to build and obtain YANG data tree
55 * which is data (sub)instance representation, abstract of protocol.
56 */
57public class YangRequestWorkBench implements YdtExtendedBuilder {
58
59 // ydt formatted error string
60 private static final String FMT_NOT_EXIST =
61 "Application with name \"%s\" doesn't exist.";
62 private static final String E_USE_ADDLEAF =
63 "Requested Node should be created using addLeaf interface";
64 private static final String E_MULTI_INS =
65 "Adds an instance of type list or leaf-list node only";
66 private static final String E_CREATE =
67 "Create request is not allowed under delete operation";
68 private static final String E_DEL =
69 "Delete request is not allowed under create operation";
70 private static final String E_INVOKE_PARENT =
71 "Can't invoke get parent at logical root node";
72 private static final String FMT_TOO_FEW =
73 "Too few key parameters in %s. Expected %d; actual %d.";
74 private static final String FMT_TOO_MANY =
75 "Too many key parameters in %s. Expected %d; actual %d.";
76
77 /*
78 * Current node in YANG data tree, kept to maintain the
79 * current context in YDT.
80 */
81 private YdtNode curNode;
82
83 /*
84 * Root node in YANG data tree, kept to maintain the root context in
85 * YDT.
86 */
87 private YdtNode rootNode;
88
89 /*
90 * Current node in YANG data tree, kept to maintain the current context
91 * in ydt application tree.
92 */
93 private YdtAppContext appCurNode;
94
95 /*
96 * Root node in YANG data tree, kept to maintain the root context in ydt
97 * application tree.
98 */
99 private YdtAppContext appRootNode;
100
101 /**
102 * Root Node Tag attribute in YANG data tree, kept to maintain the root
103 * tag attributes in YDT.
104 * <p>
105 * First key param of map represent tagName name of tag attribute.
106 * Second param of map represent tagValue value of tag attribute
107 */
108 private Map<String, String> rootTagAttributeMap;
109
110 /*
111 * YANG schema registry reference.
112 */
113 private YangSchemaRegistry registry = null;
114
115 /*
116 * YMS operation type.
117 */
118 private final YmsOperationType ymsOperationType;
119
120 /*
121 * YDT default operation type.
122 */
123 private YdtContextOperationType ydtDefaultOpType;
124
125 /*
126 * Flag to identify data validation need to be done by YDT or not.
127 */
Vidyashree Rama76faccc2016-10-17 22:06:52 +0530128 private boolean validate = false;
sonu gupta1bb37b82016-11-11 16:51:18 +0530129 // TODO validate need to be handle later with interaction type basis in
130 // future when it will be supported
131
132
133 /**
134 * Creates an instance of YANG request work bench which is use to initialize
135 * logical rootNode and and schema registry.
136 *
137 * @param name name of logical container of a protocol
138 * which is a holder of the complete tree
139 * @param namespace namespace of logical container
140 * @param opType type of operation done by using YANG
141 * interface
142 * @param registry Yang schema registry
143 * @param isValidate Flag to identify data validation need to be
144 * done by YDT or not
145 */
146 public YangRequestWorkBench(String name, String namespace,
147 YmsOperationType opType,
148 YangSchemaRegistry registry,
149 boolean isValidate) {
150 YdtNode newNode;
151 YangSchemaNodeIdentifier nodeIdentifier =
152 new YangSchemaNodeIdentifier();
153 nodeIdentifier.setName(name);
154 nodeIdentifier.setNameSpace(namespace);
155 newNode = new YdtSingleInstanceNode(nodeIdentifier);
156 setRootNode(newNode);
157 this.registry = registry;
158 ymsOperationType = opType;
159 validate = isValidate;
160 // Set the logical root node for yang data app tree.
161 DefaultYdtAppContext appNode = getAppContext(true);
162
163 setAppRootNode(appNode);
164 }
165
166 /**
Vidyashree Rama76faccc2016-10-17 22:06:52 +0530167 * Creates an instance of YANG request work bench which is used to build YDT
168 * tree in YAB.
169 *
170 * @param curNode current YDT node
171 * @param operationType YMS operation type
172 */
173 public YangRequestWorkBench(YdtNode curNode,
174 YmsOperationType operationType) {
175 this.curNode = curNode;
176 ymsOperationType = operationType;
177 }
178
179 /**
sonu gupta1bb37b82016-11-11 16:51:18 +0530180 * Sets the logical root context information available in YDT node.
181 *
182 * @param node logical root node
183 */
184 private void setRootNode(YdtNode node) {
185 rootNode = node;
186 curNode = node;
187 }
188
189 /**
190 * Sets the app context tree logical root node for ydt application tree.
191 *
192 * @param node application tree's logical root node
193 */
194 private void setAppRootNode(YdtAppContext node) {
195 appRootNode = node;
196 appCurNode = node;
197 }
198
199 /**
200 * Returns the YANG schema registry of Ydt.
201 * This method will be used by ytb.
202 *
203 * @return YANG schema registry
204 */
205 public YangSchemaRegistry getYangSchemaRegistry() {
206 return registry;
207 }
208
209 /**
210 * Returns the app context tree root node for ydt application tree.
211 * This method will be used by yab.
212 *
213 * @return YdtAppContext refers to root node of ydt application tree
214 */
215 public YdtAppContext getAppRootNode() {
216 return appRootNode;
217 }
218
219 /**
220 * Returns the data tree for given node identifier.
221 *
222 * @param id Represents node identifier of YANG data tree node
223 * @param namespace namespace of the application requested by user
224 * @return YANG data tree node
225 */
226 private YdtNode moduleHandler(YangSchemaNodeIdentifier id,
227 String namespace) {
228
229 YangSchemaNode node = registry
230 .getYangSchemaNodeUsingSchemaName(id.getName());
231
232 if (node == null ||
233 namespace != null && !namespace.equals(node.getNameSpace())) {
234 curNode.errorHandler(errorMsg(
235 FMT_NOT_EXIST, id.getName()), rootNode);
236 }
237
238 YdtNode newNode = new YdtSingleInstanceNode(id);
239 newNode.setYangSchemaNode(node);
240 id.setNameSpace(node.getNameSpace());
241 return newNode;
242 }
243
244 @Override
245 public void setRootTagAttributeMap(Map<String, String> attributeTag) {
246 rootTagAttributeMap = attributeTag;
247 }
248
249 @Override
250 public Map<String, String> getRootTagAttributeMap() {
251 if (rootTagAttributeMap != null) {
252 return ImmutableMap.copyOf(rootTagAttributeMap);
253 }
254 return null;
255 }
256
257 @Override
258 public void addChild(String name, String namespace) {
259 addChild(name, namespace, UNKNOWN, null, OTHER);
260 }
261
262 @Override
263 public void addChild(String name, String namespace, YdtType ydtType) {
264 addChild(name, namespace, ydtType, null);
265 }
266
267 @Override
268 public void addChild(String name, String namespace,
269 YdtContextOperationType opType) {
270 addChild(name, namespace, UNKNOWN, opType, OTHER);
271 }
272
273 @Override
274 public void addChild(String name, String namespace, YdtType ydtType,
275 YdtContextOperationType opType) {
276 RequestedCardinality cardinality = null;
277 switch (ydtType) {
278 case MULTI_INSTANCE_NODE:
279 cardinality = MULTI_INSTANCE;
280 break;
281 case SINGLE_INSTANCE_NODE:
282 cardinality = SINGLE_INSTANCE;
283 break;
284 default:
285 curNode.errorHandler(E_USE_ADDLEAF, rootNode);
286 }
287 addChild(name, namespace, cardinality, opType, OTHER);
288 }
289
290 /**
291 * Adds a last child to YANG data tree; this method is to be used by all
292 * protocols internally which are aware or unaware of the nature
293 * (single/multiple) of node.
294 *
295 * @param name name of child to be added
296 * @param namespace namespace of child to be added
297 * @param cardinality type of YANG data tree node operation
298 * @param opType type of requested operation over a node
299 * @param callType to identify the whether its a leaf or other node
300 */
301 private void addChild(String name, String namespace,
302 RequestedCardinality cardinality,
303 YdtContextOperationType opType,
304 RequestedCallType callType) {
305
306 YdtNode childNode;
307 boolean isContextSwitch = false;
308 YangSchemaNode schemaNode = null;
309 YangSchemaNodeContextInfo contextInfo;
310 YangSchemaNode augmentingSchema = null;
311
312 YangSchemaNodeIdentifier id = new YangSchemaNodeIdentifier();
313 id.setName(name);
314
315 // Module/sub-module node handler.
316 if (curNode.equals(rootNode)) {
317 childNode = moduleHandler(id, namespace);
318 } else {
319
320 // If namespace given by user null, then take namespace from parent.
321 if (namespace == null) {
322 namespace = curNode.getYdtNodeIdentifier().getNameSpace();
323 }
324
325 id.setNameSpace(namespace);
326
327 /*
328 * Get the already exiting YDT node in YDT tree with same
329 * nodeIdentifier
330 */
331 childNode = curNode.getCollidingChild(id);
332
333 /*
334 * If colliding child doesn't exist ,
335 * then query yang data model for schema of given node.
336 */
337 if (childNode == null) {
338 /*
339 * Get Yang Schema node context info which is having
340 * YangSchemaNode and ContextSwitchedNode.
341 */
342 contextInfo = curNode.getSchemaNodeContextInfo(id);
343
344 if (contextInfo.getContextSwitchedNode() != null) {
345 augmentingSchema = appCurNode.getAugmentingSchemaNode(
346 id, contextInfo);
347 if (augmentingSchema != null) {
348 /*
349 * As two tree(YDT and YDT Application Tree) are getting
350 * prepared in parallel, So setting context switch
351 * flag it will help ydt to keep the track whether
352 * ydtApp tree also need to be traversed back to parent
353 * or not with YDT tree traverse to parent call.
354 */
355 isContextSwitch = true;
356 }
357 }
358 schemaNode = contextInfo.getSchemaNode();
359 } else {
360 /*
361 * If colliding child exist , then will be leaf-list or list
362 * If its leaf-list then return and add new requested
363 * value/valueSet in same node else take yang data model
364 * information from colliding child.
365 */
366 if (childNode.getYdtType() == MULTI_INSTANCE_LEAF_VALUE_NODE) {
367 curNode = childNode;
368 return;
369 }
370 schemaNode = childNode.getYangSchemaNode();
371 }
372 childNode = YdtNodeFactory.getNode(id, schemaNode, cardinality,
373 callType);
374 }
375
376 opType = getValidOpType(opType, callType, schemaNode);
377
378 childNode.setYdtContextOperationType(opType);
379
380 curNode.addChild(childNode, true);
381
382 // Update parent ydt node map.
383 curNode.updateYdtMap(id, childNode);
384
385 processAppTree(opType, childNode, augmentingSchema, isContextSwitch);
386
387 // Updating the curNode.
388 curNode = childNode;
389 }
390
391 /**
392 * Processes application tree on the bases of requested ydt node.
393 *
394 * @param opType user requested operation type
395 * @param childNode requested ydt node
396 * @param augmentingSchema schema of last augmenting node
397 * @param isContextSwitch true, for module node call; false for modules
398 * sub-node calls
399 */
400 private void processAppTree(
401 YdtContextOperationType opType, YdtNode childNode,
402 YangSchemaNode augmentingSchema, boolean isContextSwitch) {
403
404 if (augmentingSchema != null) {
405 if (!appCurNode.addSchemaToAppSet(augmentingSchema)) {
406 return;
407 }
408 }
409 if (opType == null) {
410 opType = curNode.getYdtContextOperationType();
411 } else {
412 // Updating operation type for parent nodes
413 appCurNode.updateAppOperationType(opType);
414 }
415
416 /*
417 * Create entry of module node in ydt app tree.
418 * Or if context switch happened then also add entry for same ydt
419 * node in the ydt application tree.
420 */
421 if (curNode.equals(rootNode) || isContextSwitch) {
422 addChildInAppTree(childNode, augmentingSchema, opType,
423 isContextSwitch);
424
425 // Setting app tree node operation.
426 appCurNode.setOperationType(getAppOpTypeFromYdtOpType(opType));
427 }
428
429 // Updating the delete operation list in app tree.
430 if (opType == DELETE || opType == REMOVE) {
431 appCurNode.addDeleteNode(childNode);
432 }
433 }
434
435 /**
436 * Returns the valid operation type for requested ydt node after performing
437 * validation.
438 *
439 * @param opType user requested operation type
440 * @param callType to identify the whether its a leaf or other node
441 * @param schemaNode schema node of user requested ydt node
442 * @return operation type
443 */
444 private YdtContextOperationType getValidOpType(
445 YdtContextOperationType opType, RequestedCallType callType,
446 YangSchemaNode schemaNode) {
447
448 // Operation type not supported for leaf node.
449 if (callType == LEAF || (callType == RequestedCallType.MULTI_INSTANCE &&
450 schemaNode.getYangSchemaNodeType() ==
451 YANG_MULTI_INSTANCE_LEAF_NODE)) {
452 return null;
453 }
454
455 // Reference for parent node operation type.
456 YdtContextOperationType parentOpType = curNode
457 .getYdtContextOperationType();
458
459 if (opType != null && parentOpType != null) {
460 validateOperationType(parentOpType, opType);
461 } else if (opType == null) {
462 opType = getOperationType(parentOpType);
463 }
464 return opType;
465 }
466
467 /**
468 * Returns the operation type for non leaf node.
469 * When "operation" attribute for current node is not specified or null,
470 * then the operation applied to the parent data node of the
471 * configuration is used. If no parent data node is available,
472 * then the default-operation'value is used.
473 * If default operation type is not set, merge will be taken as default
474 * operation type.
475 *
476 * @param parentOpType operation type of parent node
477 * @return operation type for current non leaf node
478 */
479 private YdtContextOperationType getOperationType(
480 YdtContextOperationType parentOpType) {
481
482 return parentOpType != null ? parentOpType :
483 (ydtDefaultOpType != null ? ydtDefaultOpType : MERGE);
484 }
485
486 /**
487 * Adds a last child to YANG app data tree.this method is to be used
488 * internally by other ydt interfaces.
489 *
490 * @param childNode node to be added in tree
491 * @param schemaNode last augmenting module node
492 * @param childOpType operation type of node
493 * @param isContextSwitch true, for module node call; false for modules
494 * sub-node calls
495 */
496 private void addChildInAppTree(YdtNode childNode,
497 YangSchemaNode schemaNode,
498 YdtContextOperationType childOpType,
499 boolean isContextSwitch) {
500
501 YdtAppNodeOperationType opType;
502
503 DefaultYdtAppContext appContext = getAppContext(isContextSwitch);
504
505 // Add context switched child in ydt App tree.
506 appCurNode.addChild(appContext);
507 //Updating the curNode.
508 appCurNode = appContext;
509
510 // Get the app tree operation type from ydt operation type.
511 opType = getAppOpTypeFromYdtOpType(childOpType);
512
513 appCurNode.setAppData(childNode, schemaNode);
514
515 appCurNode.setOperationType(opType);
516
517 childNode.setAppContextSwitch();
518 }
519
520 /**
521 * Validates the various combination of operation type.
522 *
523 * @param parentOpType Reference for parent node operation type
524 * @param childOpType type of YANG data tree node operation
525 */
526 private void validateOperationType(YdtContextOperationType parentOpType,
527 YdtContextOperationType childOpType) {
528
529 switch (parentOpType) {
530 case CREATE:
531 // Inside the create operation delete operation should not come.
532 if (childOpType == DELETE) {
533 curNode.errorHandler(E_CREATE, rootNode);
534 }
535 break;
536 case DELETE:
537 // Inside the delete operation create operation should not come.
538 if (childOpType == CREATE) {
539 curNode.errorHandler(E_DEL, rootNode);
540 }
541 break;
542 default:
543 //TODO check all possible scenario.
544 }
545 }
546
547 @Override
548 public void addLeaf(String name, String namespace, String value) {
549 addLeaf(name, namespace, value, null, UNKNOWN);
550 }
551
552 @Override
553 public void addLeaf(String name, String namespace, Set<String> valueSet) {
554 addLeaf(name, namespace, null, valueSet, MULTI_INSTANCE_LEAF);
555 }
556
557 /**
558 * Adds a last leaf with list of values/single value to YANG data tree.
559 * This method is used by all protocols which knows the nature
560 * (single/multiple) or not.
561 * Value of leaf can be null which indicates selection node in get
562 * operation.
563 *
564 * @param name name of child to be added
565 * @param namespace namespace of child to be added, if it's
566 * null, parent's
567 * namespace will be applied to child
568 * @param value value of the child
569 * @param valueSet list of value of the child
570 * @param cardinality type of YANG data tree node operation
571 */
572 private void addLeaf(String name, String namespace, String value,
573 Set<String> valueSet,
574 RequestedCardinality cardinality) {
575 addChild(name, namespace, cardinality, null, LEAF);
576
577 // After successful addition of child node updating the values in same.
578 if (value != null) {
579 curNode.addValue(value);
580 } else if (valueSet != null) {
581 curNode.addValueSet(valueSet);
582 }
583 }
584
585 @Override
586 public void traverseToParent() {
587 // If traverse back to parent for logical root node comes
588 if (curNode.equals(rootNode)) {
589 curNode.errorHandler(E_INVOKE_PARENT, rootNode);
590 }
591
592 // If node is of multiInstanceNode type then check key uniqueness.
593 if (curNode.getYdtType() == MULTI_INSTANCE_NODE) {
594 curNode.createKeyNodeList();
595 }
596
597 /*
598 * Check application switch for curNode if set,
599 * then traverseToParent in YDT application tree.
600 */
601 if (curNode.getParent().equals(rootNode) ||
602 curNode.getAppContextSwitch()) {
603 traverseToAppTreeParent();
604 }
605
606 /*
607 * Validate all multi Instance inside current context,
608 * This is not valid for leaf and leaf-list node.
609 */
610 if (curNode instanceof YdtMultiInstanceNode ||
611 curNode instanceof YdtSingleInstanceNode) {
612 curNode.validateMultiInstanceNode();
613 }
614
615 curNode = curNode.getParent();
616 }
617
618 /**
619 * Traverses up in YANG application tree to the parent node,
620 * This will be used when Ydt current context switch flag is set.
621 */
622 private void traverseToAppTreeParent() {
623 appCurNode = appCurNode.getParent();
624 }
625
626 @Override
627 public YdtContext getCurNode() {
628 return curNode;
629 }
630
631 @Override
632 public void setDefaultEditOperationType(
633 YdtContextOperationType opType) {
634 ydtDefaultOpType = opType;
635 }
636
637 @Override
638 public YdtExtendedContext getRootNode() {
639 return rootNode;
640 }
641
642 @Override
643 public YmsOperationType getYmsOperationType() {
644 return ymsOperationType;
645 }
646
647 @Override
648 public void addMultiInstanceChild(String name, String namespace,
649 List<String> keysValueList,
650 YdtContextOperationType opType) {
651 addChild(name, namespace, UNKNOWN, opType,
652 RequestedCallType.MULTI_INSTANCE);
653 int inputCount = keysValueList.size();
654 int expectedCount;
655 if (curNode.getYdtType() == MULTI_INSTANCE_LEAF_VALUE_NODE) {
656 // After successful addition of child node updating
657 // the values in same.
658 // inputCount = curNode.getValueSet().size() + inputCount;
659 // checkElementCount(expectedCount, inputCount);
660 // TODO check the element count
661 for (String value : keysValueList) {
662 curNode.addValue(value);
663 }
664 } else if (curNode.getYdtType() == MULTI_INSTANCE_NODE) {
665 YangList yangListHolder = (YangList) curNode.getYangSchemaNode();
666 List<String> schemaKeyList = yangListHolder.getKeyList();
667 expectedCount = schemaKeyList.size();
668 checkElementCount(name, expectedCount, inputCount);
669
670 Iterator<String> sklIter = schemaKeyList.iterator();
671 Iterator<String> kvlIter = keysValueList.iterator();
672 String keyEleName;
673 while (kvlIter.hasNext()) {
674 String value = kvlIter.next();
675 keyEleName = sklIter.next();
676 addLeaf(keyEleName, namespace, value);
677 if (kvlIter.hasNext()) {
678 traverseToParentWithoutValidation();
679 }
680 }
681 curNode = curNode.getParent();
682 } else {
683 curNode.errorHandler(E_MULTI_INS, rootNode);
684 }
685 }
686
687 /**
688 * Checks the user supplied list of argument match's the expected value
689 * or not.
690 *
691 * @param name name of the parent list/leaf-list node
692 * @param expected count suppose to be
693 * @param actual user supplied values count
694 */
695 private void checkElementCount(String name, int expected,
696 int actual) {
697 if (expected < actual) {
698 curNode.errorHandler(errorMsg(FMT_TOO_MANY, name, expected, actual),
699 rootNode);
700 } else if (expected > actual) {
701 curNode.errorHandler(errorMsg(FMT_TOO_FEW, name, expected, actual),
702 rootNode);
703 }
704 }
705
706 /**
707 * Adds a last child to YANG data tree, this method is to be used by
708 * YANG object builder sub-calls internally.
709 *
710 * @param opType type of requested operation over a node
711 * @return returns added ydt node in YDT tree
712 */
713 private YdtNode addExtendedChildNode(YdtContextOperationType opType,
714 YangSchemaNode schemaNode) {
715
716 YdtNode childNode;
717 YangSchemaNodeIdentifier id =
718 schemaNode.getYangSchemaNodeIdentifier();
719
720 childNode = YdtNodeFactory
721 .getYangSchemaNodeTypeSpecificContext(
722 id, schemaNode.getYangSchemaNodeType());
723
724 childNode.setId(id);
725
726 childNode.setYangSchemaNode(schemaNode);
727
728 childNode.setYdtContextOperationType(opType);
729
730 curNode.addChild(childNode, true);
731
732 curNode = childNode;
733
734 return childNode;
735 }
736
737 @Override
738 public YdtExtendedContext addChild(YdtContextOperationType opType,
739 YangSchemaNode schemaNode) {
740 return addExtendedChildNode(opType, schemaNode);
741 }
742
743 @Override
744 public YdtExtendedContext addLeafList(Set<String> valueSet,
745 YangSchemaNode schemaNode) {
746 YdtNode childNode = addExtendedChildNode(null, schemaNode);
747
748 // After successful addition of child node updating the values in same.
749 childNode.addValueSetWithoutValidation(valueSet);
750 return childNode;
751 }
752
753 @Override
754 public YdtExtendedContext addLeaf(String value,
755 YangSchemaNode schemaNode) {
756 YdtNode childNode = addExtendedChildNode(null, schemaNode);
757
758 // After successful addition of child node updating the values in same.
759 childNode.addValueWithoutValidation(value);
760 return childNode;
761 }
762
763 @Override
764 public void traverseToParentWithoutValidation() {
765 // If traverse back to parent for logical root node comes
766 if (curNode.equals(rootNode)) {
767 curNode.errorHandler(E_INVOKE_PARENT, rootNode);
768 }
769 curNode = curNode.getParent();
770 }
771}