blob: 2159de569a362b5198972a2a22c151dcca2e22af [file] [log] [blame]
sonu gupta1bb37b82016-11-11 16:51:18 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
sonu gupta1bb37b82016-11-11 16:51:18 +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 */
16
17package org.onosproject.yms.app.ydt;
18
19import com.google.common.collect.ImmutableMap;
sonu guptaeff184b2016-11-24 12:43:49 +053020import org.onosproject.yangutils.datamodel.YangAugment;
21import org.onosproject.yangutils.datamodel.YangLeaf;
sonu gupta1bb37b82016-11-11 16:51:18 +053022import org.onosproject.yangutils.datamodel.YangList;
23import org.onosproject.yangutils.datamodel.YangSchemaNode;
24import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
25import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
sonu guptaeff184b2016-11-24 12:43:49 +053026import org.onosproject.yms.app.ydt.exceptions.YdtException;
sonu gupta1bb37b82016-11-11 16:51:18 +053027import org.onosproject.yms.app.ysr.YangSchemaRegistry;
Sonu Gupta1f418aa2017-02-23 20:48:46 +053028import org.onosproject.yms.ydt.YdtContext;
sonu gupta1bb37b82016-11-11 16:51:18 +053029import org.onosproject.yms.ydt.YdtContextOperationType;
30import org.onosproject.yms.ydt.YdtType;
31import org.onosproject.yms.ydt.YmsOperationType;
32
sonu guptaeff184b2016-11-24 12:43:49 +053033import java.util.HashSet;
sonu gupta1bb37b82016-11-11 16:51:18 +053034import java.util.Iterator;
35import java.util.List;
36import java.util.Map;
37import java.util.Set;
38
sonu gupta1bb37b82016-11-11 16:51:18 +053039import static org.onosproject.yms.app.ydt.AppNodeFactory.getAppContext;
40import static org.onosproject.yms.app.ydt.RequestedCallType.LEAF;
sonu guptaeff184b2016-11-24 12:43:49 +053041import static org.onosproject.yms.app.ydt.RequestedCallType.NON_LEAF;
sonu gupta1bb37b82016-11-11 16:51:18 +053042import static org.onosproject.yms.app.ydt.RequestedCardinality.MULTI_INSTANCE;
43import static org.onosproject.yms.app.ydt.RequestedCardinality.MULTI_INSTANCE_LEAF;
44import static org.onosproject.yms.app.ydt.RequestedCardinality.SINGLE_INSTANCE;
45import static org.onosproject.yms.app.ydt.RequestedCardinality.UNKNOWN;
46import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg;
sonu guptaeff184b2016-11-24 12:43:49 +053047import static org.onosproject.yms.app.ydt.YdtNodeFactory.getNode;
48import static org.onosproject.yms.app.ydt.YdtNodeFactory.getYangSchemaNodeTypeSpecificContext;
49import static org.onosproject.yms.app.ydt.YdtUtils.checkElementCount;
50import static org.onosproject.yms.app.ydt.YdtUtils.freeRestResources;
51import static org.onosproject.yms.app.ydt.YdtUtils.getAppOpTypeFromYdtOpType;
52import static org.onosproject.yms.app.ydt.YdtUtils.getAugmentingSchemaNode;
53import static org.onosproject.yms.app.ydt.YdtUtils.getNodeIdentifier;
54import static org.onosproject.yms.app.ydt.YdtUtils.getValidOpType;
sonu gupta1bb37b82016-11-11 16:51:18 +053055import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE;
sonu gupta1bb37b82016-11-11 16:51:18 +053056import static org.onosproject.yms.ydt.YdtContextOperationType.REMOVE;
57import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_LEAF_VALUE_NODE;
58import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_NODE;
59
60/**
61 * Represents YANG request work bench which contains all parameters for
62 * request handling and methods to build and obtain YANG data tree
63 * which is data (sub)instance representation, abstract of protocol.
64 */
65public class YangRequestWorkBench implements YdtExtendedBuilder {
66
sonu guptaeff184b2016-11-24 12:43:49 +053067 // Ydt formatted error string
sonu gupta1bb37b82016-11-11 16:51:18 +053068 private static final String FMT_NOT_EXIST =
69 "Application with name \"%s\" doesn't exist.";
sonu guptaeff184b2016-11-24 12:43:49 +053070
71 // Ydt error strings.
72 private static final String E_USE_ADD_LEAF =
73 "Requested Node should be created using addLeaf interface.";
74
sonu gupta1bb37b82016-11-11 16:51:18 +053075 private static final String E_INVOKE_PARENT =
sonu guptaeff184b2016-11-24 12:43:49 +053076 "Can't invoke get parent at logical root node.";
sonu gupta1bb37b82016-11-11 16:51:18 +053077
78 /*
sonu guptaeff184b2016-11-24 12:43:49 +053079 * Reference for the current context node in YANG data tree.
sonu gupta1bb37b82016-11-11 16:51:18 +053080 */
81 private YdtNode curNode;
82
83 /*
sonu guptaeff184b2016-11-24 12:43:49 +053084 * Reference for the logical root node in YANG data tree.
sonu gupta1bb37b82016-11-11 16:51:18 +053085 */
86 private YdtNode rootNode;
87
88 /*
sonu guptaeff184b2016-11-24 12:43:49 +053089 * Reference for the current context in ydt application tree.
sonu gupta1bb37b82016-11-11 16:51:18 +053090 */
91 private YdtAppContext appCurNode;
92
93 /*
sonu guptaeff184b2016-11-24 12:43:49 +053094 * Reference for the logical root node context in ydt application tree.
sonu gupta1bb37b82016-11-11 16:51:18 +053095 */
96 private YdtAppContext appRootNode;
97
98 /**
99 * Root Node Tag attribute in YANG data tree, kept to maintain the root
100 * tag attributes in YDT.
101 * <p>
102 * First key param of map represent tagName name of tag attribute.
103 * Second param of map represent tagValue value of tag attribute
104 */
105 private Map<String, String> rootTagAttributeMap;
106
107 /*
108 * YANG schema registry reference.
109 */
110 private YangSchemaRegistry registry = null;
111
112 /*
113 * YMS operation type.
114 */
115 private final YmsOperationType ymsOperationType;
116
117 /*
118 * YDT default operation type.
119 */
120 private YdtContextOperationType ydtDefaultOpType;
121
122 /*
123 * Flag to identify data validation need to be done by YDT or not.
124 */
Vidyashree Rama76faccc2016-10-17 22:06:52 +0530125 private boolean validate = false;
sonu gupta1bb37b82016-11-11 16:51:18 +0530126 // TODO validate need to be handle later with interaction type basis in
127 // future when it will be supported
128
sonu guptaeff184b2016-11-24 12:43:49 +0530129 /*
130 * Reference for application tree node set.
131 * This set contains the method name's generated for an augmented
132 * target node to avoid the duplicate entries in YDT application tree for
133 * multiple augmented nodes under a single XPATH.
134 */
135 private Set<String> augGenMethodSet;
sonu gupta1bb37b82016-11-11 16:51:18 +0530136
137 /**
138 * Creates an instance of YANG request work bench which is use to initialize
139 * logical rootNode and and schema registry.
140 *
141 * @param name name of logical container of a protocol
142 * which is a holder of the complete tree
143 * @param namespace namespace of logical container
144 * @param opType type of operation done by using YANG
145 * interface
sonu guptaeff184b2016-11-24 12:43:49 +0530146 * @param reg Yang schema registry
sonu gupta1bb37b82016-11-11 16:51:18 +0530147 * @param isValidate Flag to identify data validation need to be
148 * done by YDT or not
149 */
150 public YangRequestWorkBench(String name, String namespace,
151 YmsOperationType opType,
sonu guptaeff184b2016-11-24 12:43:49 +0530152 YangSchemaRegistry reg,
sonu gupta1bb37b82016-11-11 16:51:18 +0530153 boolean isValidate) {
sonu guptaeff184b2016-11-24 12:43:49 +0530154
155 setRootNode(new YdtLogicalNode(name, namespace));
156 registry = reg;
sonu gupta1bb37b82016-11-11 16:51:18 +0530157 ymsOperationType = opType;
158 validate = isValidate;
sonu gupta1bb37b82016-11-11 16:51:18 +0530159
sonu guptaeff184b2016-11-24 12:43:49 +0530160 setAppRootNode(getAppContext(true));
sonu gupta1bb37b82016-11-11 16:51:18 +0530161 }
162
163 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530164 * Sets the logical root node for ydt.
Vidyashree Rama76faccc2016-10-17 22:06:52 +0530165 *
sonu guptaeff184b2016-11-24 12:43:49 +0530166 * @param node ydt logical root node
sonu gupta1bb37b82016-11-11 16:51:18 +0530167 */
168 private void setRootNode(YdtNode node) {
169 rootNode = node;
170 curNode = node;
171 }
172
173 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530174 * Sets the logical root node for ydt application tree.
sonu gupta1bb37b82016-11-11 16:51:18 +0530175 *
sonu guptaeff184b2016-11-24 12:43:49 +0530176 * @param node ydt application context logical root node
sonu gupta1bb37b82016-11-11 16:51:18 +0530177 */
178 private void setAppRootNode(YdtAppContext node) {
179 appRootNode = node;
180 appCurNode = node;
181 }
182
183 /**
184 * Returns the YANG schema registry of Ydt.
185 * This method will be used by ytb.
186 *
187 * @return YANG schema registry
188 */
189 public YangSchemaRegistry getYangSchemaRegistry() {
190 return registry;
191 }
192
193 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530194 * Returns the ydt app context tree logical root node.
195 * This method will be used by yab and ytb.
sonu gupta1bb37b82016-11-11 16:51:18 +0530196 *
sonu guptaeff184b2016-11-24 12:43:49 +0530197 * @return YdtAppContext app tree logical root node
sonu gupta1bb37b82016-11-11 16:51:18 +0530198 */
199 public YdtAppContext getAppRootNode() {
200 return appRootNode;
201 }
202
203 /**
sonu guptaeff184b2016-11-24 12:43:49 +0530204 * Returns the ydt module node with requested node identifier.
sonu gupta1bb37b82016-11-11 16:51:18 +0530205 *
sonu guptaeff184b2016-11-24 12:43:49 +0530206 * @param id module/application node identifier
sonu gupta1bb37b82016-11-11 16:51:18 +0530207 * @return YANG data tree node
sonu guptaeff184b2016-11-24 12:43:49 +0530208 * @throws YdtException when user requested node schema doesn't exist or
209 * requested node is already part of the tree
sonu gupta1bb37b82016-11-11 16:51:18 +0530210 */
sonu guptaeff184b2016-11-24 12:43:49 +0530211 private YdtNode moduleHandler(YangSchemaNodeIdentifier id)
212 throws YdtException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530213
sonu guptaeff184b2016-11-24 12:43:49 +0530214 YangSchemaNode node =
215 registry.getYangSchemaNodeUsingSchemaName(id.getName());
sonu gupta1bb37b82016-11-11 16:51:18 +0530216
sonu guptaeff184b2016-11-24 12:43:49 +0530217 String namespace = id.getNameSpace().getModuleNamespace();
218
219 /*
220 * Checking received schema node is having same namespace as
221 * requested by user or not.
222 */
223 if (node == null || namespace != null &&
224 !namespace.equals(node.getYangSchemaNodeIdentifier()
225 .getNameSpace()
226 .getModuleNamespace())) {
227 throw new YdtException(errorMsg(FMT_NOT_EXIST, id.getName()));
sonu gupta1bb37b82016-11-11 16:51:18 +0530228 }
229
sonu guptaeff184b2016-11-24 12:43:49 +0530230 /*
231 * If yms operation is for query then no validation need to be
232 * performed.
233 */
234 if (ymsOperationType != YmsOperationType.QUERY_REQUEST) {
235 // Checking whether module node is already exits in YDT or not.
236 try {
237 curNode.getCollidingChild(id);
238 } catch (YdtException e) {
239 throw new YdtException(e.getLocalizedMessage());
240 }
241 }
242
243 YdtNode newNode = new YdtSingleInstanceNode(node);
sonu gupta1bb37b82016-11-11 16:51:18 +0530244 newNode.setYangSchemaNode(node);
sonu gupta1bb37b82016-11-11 16:51:18 +0530245 return newNode;
246 }
247
248 @Override
249 public void setRootTagAttributeMap(Map<String, String> attributeTag) {
250 rootTagAttributeMap = attributeTag;
251 }
252
253 @Override
254 public Map<String, String> getRootTagAttributeMap() {
255 if (rootTagAttributeMap != null) {
256 return ImmutableMap.copyOf(rootTagAttributeMap);
257 }
258 return null;
259 }
260
261 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530262 public void addChild(String name, String namespace)
263 throws IllegalArgumentException {
264 addChild(name, namespace, UNKNOWN, null, NON_LEAF);
sonu gupta1bb37b82016-11-11 16:51:18 +0530265 }
266
267 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530268 public void addChild(String name, String namespace, YdtType ydtType)
269 throws IllegalArgumentException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530270 addChild(name, namespace, ydtType, null);
271 }
272
273 @Override
274 public void addChild(String name, String namespace,
sonu guptaeff184b2016-11-24 12:43:49 +0530275 YdtContextOperationType opType)
276 throws IllegalArgumentException {
277 addChild(name, namespace, UNKNOWN, opType, NON_LEAF);
sonu gupta1bb37b82016-11-11 16:51:18 +0530278 }
279
280 @Override
281 public void addChild(String name, String namespace, YdtType ydtType,
sonu guptaeff184b2016-11-24 12:43:49 +0530282 YdtContextOperationType opType)
283 throws IllegalArgumentException {
284 RequestedCardinality cardinality;
sonu gupta1bb37b82016-11-11 16:51:18 +0530285 switch (ydtType) {
286 case MULTI_INSTANCE_NODE:
287 cardinality = MULTI_INSTANCE;
288 break;
289 case SINGLE_INSTANCE_NODE:
290 cardinality = SINGLE_INSTANCE;
291 break;
292 default:
sonu guptaeff184b2016-11-24 12:43:49 +0530293 throw new IllegalArgumentException(E_USE_ADD_LEAF);
sonu gupta1bb37b82016-11-11 16:51:18 +0530294 }
sonu guptaeff184b2016-11-24 12:43:49 +0530295 addChild(name, namespace, cardinality, opType, NON_LEAF);
sonu gupta1bb37b82016-11-11 16:51:18 +0530296 }
297
298 /**
299 * Adds a last child to YANG data tree; this method is to be used by all
300 * protocols internally which are aware or unaware of the nature
301 * (single/multiple) of node.
302 *
303 * @param name name of child to be added
304 * @param namespace namespace of child to be added
305 * @param cardinality type of YANG data tree node operation
306 * @param opType type of requested operation over a node
307 * @param callType to identify the whether its a leaf or other node
sonu guptaeff184b2016-11-24 12:43:49 +0530308 * @throws IllegalArgumentException when method has been passed an illegal
309 * or inappropriate argument.
sonu gupta1bb37b82016-11-11 16:51:18 +0530310 */
311 private void addChild(String name, String namespace,
312 RequestedCardinality cardinality,
313 YdtContextOperationType opType,
sonu guptaeff184b2016-11-24 12:43:49 +0530314 RequestedCallType callType)
315 throws IllegalArgumentException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530316
sonu guptaeff184b2016-11-24 12:43:49 +0530317 YdtNode newNode;
318 boolean contextSwitch = false;
sonu gupta1bb37b82016-11-11 16:51:18 +0530319 YangSchemaNode augmentingSchema = null;
sonu guptaeff184b2016-11-24 12:43:49 +0530320 YangSchemaNodeIdentifier id = getNodeIdentifier(name, namespace);
Vidyashree Ramac8489702016-12-19 09:38:31 +0530321 if (name == null) {
322 if (!curNode.equals(rootNode)) {
323 throw new YdtException("Name is null for node other than module");
324 }
325
326 /*
327 * Since XML will not have module name, id.name will be null. In
328 * that case get schema node by using namespace. In NBI flow,
329 * name will never be null.
330 */
331 YangSchemaNode node = registry
332 .getSchemaWrtNameSpace(id.getNameSpace().getModuleNamespace());
333 id.setName(node.getName());
334 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530335
sonu guptaeff184b2016-11-24 12:43:49 +0530336 try {
337 // Module/sub-module node handler.
338 if (curNode.equals(rootNode)) {
339 newNode = moduleHandler(id);
sonu gupta1bb37b82016-11-11 16:51:18 +0530340 } else {
sonu guptaeff184b2016-11-24 12:43:49 +0530341
342 YangSchemaNode schemaNode;
343 YangSchemaNodeContextInfo contextInfo;
344
345 // If namespace given by user null, then take namespace from parent.
346 if (namespace == null) {
347 id.setNameSpace(curNode.getYangSchemaNode().getNameSpace());
sonu gupta1bb37b82016-11-11 16:51:18 +0530348 }
sonu guptaeff184b2016-11-24 12:43:49 +0530349
350 /*
351 * Get the already exiting YDT node in YDT tree with same
352 * nodeIdentifier
353 */
354 newNode = curNode.getCollidingChild(id);
355
356 /*
357 * If colliding child doesn't exist ,
358 * then query yang data model for schema of given node.
359 */
360 if (newNode == null) {
361 /*
362 * Get Yang Schema node context info which is having
363 * YangSchemaNode and ContextSwitchedNode.
364 */
365 contextInfo = curNode.getSchemaNodeContextInfo(id);
366
367 if (contextInfo.getContextSwitchedNode() != null) {
368 augmentingSchema = getAugmentingSchemaNode(
369 id, contextInfo);
370 if (augmentingSchema != null) {
371 /*
372 * As two tree(YDT and YDT Application Tree) are getting
373 * prepared in parallel, So setting context switch
374 * flag it will help ydt to keep the track whether
375 * ydtApp tree also need to be traversed back to parent
376 * or not with YDT tree traverse to parent call.
377 */
378 contextSwitch = true;
379 }
380 }
381 schemaNode = contextInfo.getSchemaNode();
382 } else {
383 /*
384 * If colliding child exist , then it will be leaf-list or list.
385 * If its leaf-list then return and add new requested
386 * value/valueSet in same node else take yang data model
387 * information from colliding child.
388 */
389 if (newNode.getYdtType() == MULTI_INSTANCE_LEAF_VALUE_NODE) {
390 curNode = newNode;
391 return;
392 }
393 schemaNode = newNode.getYangSchemaNode();
394 }
395
396 /*
397 * For yms query request node specific validation are not
398 * required as rest-conf can call addChild api for leaf/leaf-list
399 * node addition also in ydt.
400 */
401 if (ymsOperationType == YmsOperationType.QUERY_REQUEST) {
402 newNode = getYangSchemaNodeTypeSpecificContext(schemaNode);
403 } else {
404 newNode = getNode(schemaNode, cardinality, callType);
405 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530406 }
sonu guptaeff184b2016-11-24 12:43:49 +0530407
408 opType = getValidOpType(opType, ydtDefaultOpType, newNode, curNode);
409
410 newNode.setYdtContextOperationType(opType);
411
412 curNode.addChild(newNode, true);
413 } catch (YdtException e) {
414 freeRestResources(rootNode);
415 throw new IllegalArgumentException(e.getLocalizedMessage());
sonu gupta1bb37b82016-11-11 16:51:18 +0530416 }
417
sonu gupta1bb37b82016-11-11 16:51:18 +0530418 // Update parent ydt node map.
sonu guptaeff184b2016-11-24 12:43:49 +0530419 curNode.updateYdtMap(newNode);
sonu gupta1bb37b82016-11-11 16:51:18 +0530420
sonu guptaeff184b2016-11-24 12:43:49 +0530421 processAppTree(opType, newNode, augmentingSchema, contextSwitch);
sonu gupta1bb37b82016-11-11 16:51:18 +0530422
sonu guptaeff184b2016-11-24 12:43:49 +0530423 curNode = newNode;
sonu gupta1bb37b82016-11-11 16:51:18 +0530424 }
425
426 /**
427 * Processes application tree on the bases of requested ydt node.
428 *
429 * @param opType user requested operation type
430 * @param childNode requested ydt node
431 * @param augmentingSchema schema of last augmenting node
sonu guptaeff184b2016-11-24 12:43:49 +0530432 * @param contextSwitch true, for module node call; false for modules
sonu gupta1bb37b82016-11-11 16:51:18 +0530433 * sub-node calls
434 */
435 private void processAppTree(
436 YdtContextOperationType opType, YdtNode childNode,
sonu guptaeff184b2016-11-24 12:43:49 +0530437 YangSchemaNode augmentingSchema, boolean contextSwitch) {
sonu gupta1bb37b82016-11-11 16:51:18 +0530438
sonu guptaeff184b2016-11-24 12:43:49 +0530439 if (curNode == rootNode) {
440 augGenMethodSet = new HashSet<>();
sonu gupta1bb37b82016-11-11 16:51:18 +0530441 }
sonu guptaeff184b2016-11-24 12:43:49 +0530442
sonu gupta1bb37b82016-11-11 16:51:18 +0530443 if (opType == null) {
444 opType = curNode.getYdtContextOperationType();
445 } else {
446 // Updating operation type for parent nodes
447 appCurNode.updateAppOperationType(opType);
448 }
449
450 /*
sonu guptaeff184b2016-11-24 12:43:49 +0530451 * This is to avoid multiple entries of single augmented target.
sonu gupta1bb37b82016-11-11 16:51:18 +0530452 */
sonu guptaeff184b2016-11-24 12:43:49 +0530453 if (augmentingSchema != null) {
454 if (!augGenMethodSet.add(((YangAugment) augmentingSchema)
455 .getSetterMethodName())) {
456 return;
457 }
458 }
459
460 /*
461 * Create entry of module node in ydt app tree.
462 * Or if context switch happened then also add entry for same
463 * augmented ydt node in the ydt application tree.
464 */
465 if (curNode.equals(rootNode) || contextSwitch) {
sonu gupta1bb37b82016-11-11 16:51:18 +0530466 addChildInAppTree(childNode, augmentingSchema, opType,
sonu guptaeff184b2016-11-24 12:43:49 +0530467 contextSwitch);
sonu gupta1bb37b82016-11-11 16:51:18 +0530468
469 // Setting app tree node operation.
470 appCurNode.setOperationType(getAppOpTypeFromYdtOpType(opType));
471 }
472
473 // Updating the delete operation list in app tree.
474 if (opType == DELETE || opType == REMOVE) {
475 appCurNode.addDeleteNode(childNode);
476 }
477 }
478
sonu gupta1bb37b82016-11-11 16:51:18 +0530479
480 /**
481 * Adds a last child to YANG app data tree.this method is to be used
482 * internally by other ydt interfaces.
483 *
484 * @param childNode node to be added in tree
485 * @param schemaNode last augmenting module node
486 * @param childOpType operation type of node
487 * @param isContextSwitch true, for module node call; false for modules
488 * sub-node calls
489 */
490 private void addChildInAppTree(YdtNode childNode,
491 YangSchemaNode schemaNode,
492 YdtContextOperationType childOpType,
493 boolean isContextSwitch) {
494
495 YdtAppNodeOperationType opType;
496
497 DefaultYdtAppContext appContext = getAppContext(isContextSwitch);
498
499 // Add context switched child in ydt App tree.
500 appCurNode.addChild(appContext);
sonu guptaeff184b2016-11-24 12:43:49 +0530501
sonu gupta1bb37b82016-11-11 16:51:18 +0530502 appCurNode = appContext;
503
sonu gupta1bb37b82016-11-11 16:51:18 +0530504 opType = getAppOpTypeFromYdtOpType(childOpType);
505
506 appCurNode.setAppData(childNode, schemaNode);
507
508 appCurNode.setOperationType(opType);
509
510 childNode.setAppContextSwitch();
511 }
512
sonu gupta1bb37b82016-11-11 16:51:18 +0530513 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530514 public void addLeaf(String name, String namespace, String value)
515 throws IllegalArgumentException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530516 addLeaf(name, namespace, value, null, UNKNOWN);
517 }
518
519 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530520 public void addLeaf(String name, String namespace, Set<String> valueSet)
521 throws IllegalArgumentException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530522 addLeaf(name, namespace, null, valueSet, MULTI_INSTANCE_LEAF);
523 }
524
Sean Condonfe6ceba2017-02-26 16:40:03 +0000525 @Override
526 public void addNode(String name, String namespace)
527 throws IllegalArgumentException {
528 addChild(name, namespace, RequestedCardinality.UNKNOWN,
529 null, RequestedCallType.EMPTY_CONTAINER);
530 }
531
532
sonu gupta1bb37b82016-11-11 16:51:18 +0530533 /**
534 * Adds a last leaf with list of values/single value to YANG data tree.
535 * This method is used by all protocols which knows the nature
536 * (single/multiple) or not.
537 * Value of leaf can be null which indicates selection node in get
538 * operation.
539 *
540 * @param name name of child to be added
541 * @param namespace namespace of child to be added, if it's
542 * null, parent's
543 * namespace will be applied to child
544 * @param value value of the child
545 * @param valueSet list of value of the child
546 * @param cardinality type of YANG data tree node operation
sonu guptaeff184b2016-11-24 12:43:49 +0530547 * @throws IllegalArgumentException when method has been passed an illegal
548 * or inappropriate argument.
sonu gupta1bb37b82016-11-11 16:51:18 +0530549 */
550 private void addLeaf(String name, String namespace, String value,
551 Set<String> valueSet,
sonu guptaeff184b2016-11-24 12:43:49 +0530552 RequestedCardinality cardinality)
553 throws IllegalArgumentException {
554 try {
555 addChild(name, namespace, cardinality, null, LEAF);
sonu gupta1bb37b82016-11-11 16:51:18 +0530556
sonu guptaeff184b2016-11-24 12:43:49 +0530557 // After successful addition of child node updating the values in same.
558 if (value != null) {
559 curNode.addValue(value);
560 } else if (valueSet != null) {
561 curNode.addValueSet(valueSet);
562 }
563 } catch (YdtException e) {
564 freeRestResources(rootNode);
565 throw new IllegalArgumentException(e.getLocalizedMessage());
sonu gupta1bb37b82016-11-11 16:51:18 +0530566 }
567 }
568
569 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530570 public void traverseToParent() throws IllegalStateException {
sonu gupta1bb37b82016-11-11 16:51:18 +0530571 // If traverse back to parent for logical root node comes
572 if (curNode.equals(rootNode)) {
sonu guptaeff184b2016-11-24 12:43:49 +0530573 freeRestResources(rootNode);
574 throw new IllegalStateException(E_INVOKE_PARENT);
sonu gupta1bb37b82016-11-11 16:51:18 +0530575 }
576
sonu guptaeff184b2016-11-24 12:43:49 +0530577 try {
sonu gupta1bb37b82016-11-11 16:51:18 +0530578
sonu guptaeff184b2016-11-24 12:43:49 +0530579 // If node is of multiInstanceNode type then check key uniqueness.
580 if (curNode.getYdtType() == MULTI_INSTANCE_NODE) {
Sonu Gupta1f418aa2017-02-23 20:48:46 +0530581 List<YdtContext> keyList = ((YdtMultiInstanceNode) curNode).getKeyNodeList();
582 if (keyList == null || keyList.isEmpty()) {
583 curNode.createKeyNodeList();
584 }
sonu guptaeff184b2016-11-24 12:43:49 +0530585 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530586
sonu guptaeff184b2016-11-24 12:43:49 +0530587 /*
588 * Check application switch for curNode if set,
589 * then traverseToParent in YDT application tree.
590 */
591 if (curNode.getParent().equals(rootNode) ||
592 curNode.getAppContextSwitch()) {
593 traverseToAppTreeParent();
594 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530595
sonu guptaeff184b2016-11-24 12:43:49 +0530596 /*
597 * Validate all multi Instance inside current context,
598 * This is not valid for leaf and leaf-list node.
599 */
600 if (curNode instanceof YdtMultiInstanceNode ||
601 curNode instanceof YdtSingleInstanceNode) {
602 curNode.validateMultiInstanceNode();
603 }
604
605 curNode = curNode.getParent();
606 } catch (YdtException e) {
607 freeRestResources(rootNode);
608 throw new IllegalStateException(e.getLocalizedMessage());
609 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530610 }
611
612 /**
613 * Traverses up in YANG application tree to the parent node,
614 * This will be used when Ydt current context switch flag is set.
615 */
616 private void traverseToAppTreeParent() {
617 appCurNode = appCurNode.getParent();
618 }
619
620 @Override
janani b9069eb42016-11-24 17:50:08 +0530621 public YdtExtendedContext getCurNode() {
sonu gupta1bb37b82016-11-11 16:51:18 +0530622 return curNode;
623 }
624
625 @Override
626 public void setDefaultEditOperationType(
627 YdtContextOperationType opType) {
628 ydtDefaultOpType = opType;
629 }
630
631 @Override
632 public YdtExtendedContext getRootNode() {
633 return rootNode;
634 }
635
636 @Override
637 public YmsOperationType getYmsOperationType() {
638 return ymsOperationType;
639 }
640
641 @Override
642 public void addMultiInstanceChild(String name, String namespace,
643 List<String> keysValueList,
sonu guptaeff184b2016-11-24 12:43:49 +0530644 YdtContextOperationType opType)
645 throws IllegalArgumentException {
646
sonu gupta1bb37b82016-11-11 16:51:18 +0530647 addChild(name, namespace, UNKNOWN, opType,
648 RequestedCallType.MULTI_INSTANCE);
649 int inputCount = keysValueList.size();
sonu gupta1bb37b82016-11-11 16:51:18 +0530650
sonu guptaeff184b2016-11-24 12:43:49 +0530651 try {
652 if (curNode.getYdtType() == MULTI_INSTANCE_LEAF_VALUE_NODE) {
653
654 /*
655 * Calculating the current leaf-list node array size by adding
656 * existing elements count and new supplied elements by user for
657 * the same.
658 */
659 // TODO instance count for leaf list need to be handled.
660// if (curNode.getValueSet().size() + inputCount > expectedCount) {
661// curNode.errorHandler(
662// errorMsg(FMT_MANY_INS, name, expectedCount), rootNode);
663// }
664
665 /*
666 * After successful addition of child node updating
667 * the values in same.
668 */
669 for (String value : keysValueList) {
670 curNode.addValue(value);
sonu gupta1bb37b82016-11-11 16:51:18 +0530671 }
sonu guptaeff184b2016-11-24 12:43:49 +0530672 } else if (curNode.getYdtType() == MULTI_INSTANCE_NODE) {
sonu gupta1bb37b82016-11-11 16:51:18 +0530673
sonu guptaeff184b2016-11-24 12:43:49 +0530674 YangList yangListHolder = (YangList) curNode.getYangSchemaNode();
675 List<String> schemaKeyList = yangListHolder.getKeyList();
676 int expectedCount = schemaKeyList.size();
677 checkElementCount(name, expectedCount, inputCount);
678
679 //After validation adding the key nodes under the list node.
680 Iterator<String> sklIter = schemaKeyList.iterator();
681 Iterator<String> kvlIter = keysValueList.iterator();
682 String keyEleName;
683
684 while (kvlIter.hasNext()) {
685 String value = kvlIter.next();
686 keyEleName = sklIter.next();
687 addLeaf(keyEleName, namespace, value);
688 if (kvlIter.hasNext()) {
689 traverseToParentWithoutValidation();
690 }
691 }
692
693 curNode = curNode.getParent();
Sonu Gupta1f418aa2017-02-23 20:48:46 +0530694 curNode.createKeyNodeList();
sonu guptaeff184b2016-11-24 12:43:49 +0530695 }
696 } catch (YdtException e) {
697 freeRestResources(rootNode);
698 throw new IllegalArgumentException(e.getLocalizedMessage());
sonu gupta1bb37b82016-11-11 16:51:18 +0530699 }
700 }
701
702 /**
703 * Adds a last child to YANG data tree, this method is to be used by
704 * YANG object builder sub-calls internally.
705 *
706 * @param opType type of requested operation over a node
707 * @return returns added ydt node in YDT tree
708 */
709 private YdtNode addExtendedChildNode(YdtContextOperationType opType,
710 YangSchemaNode schemaNode) {
711
sonu guptaeff184b2016-11-24 12:43:49 +0530712 YdtNode childNode = getYangSchemaNodeTypeSpecificContext(schemaNode);
sonu gupta1bb37b82016-11-11 16:51:18 +0530713
714 childNode.setYangSchemaNode(schemaNode);
715
716 childNode.setYdtContextOperationType(opType);
717
718 curNode.addChild(childNode, true);
719
720 curNode = childNode;
721
722 return childNode;
723 }
724
725 @Override
726 public YdtExtendedContext addChild(YdtContextOperationType opType,
727 YangSchemaNode schemaNode) {
728 return addExtendedChildNode(opType, schemaNode);
729 }
730
731 @Override
732 public YdtExtendedContext addLeafList(Set<String> valueSet,
733 YangSchemaNode schemaNode) {
734 YdtNode childNode = addExtendedChildNode(null, schemaNode);
735
sonu guptaeff184b2016-11-24 12:43:49 +0530736 /*
737 * After successful addition of child node updating the values in
738 * valueSet.
739 */
sonu gupta1bb37b82016-11-11 16:51:18 +0530740 childNode.addValueSetWithoutValidation(valueSet);
741 return childNode;
742 }
743
744 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530745 public YdtExtendedContext addLeaf(String value, YangSchemaNode schemaNode) {
746
sonu gupta1bb37b82016-11-11 16:51:18 +0530747 YdtNode childNode = addExtendedChildNode(null, schemaNode);
748
749 // After successful addition of child node updating the values in same.
sonu guptaeff184b2016-11-24 12:43:49 +0530750 childNode.addValueWithoutValidation(value, ((YangLeaf) schemaNode)
751 .isKeyLeaf());
sonu gupta1bb37b82016-11-11 16:51:18 +0530752 return childNode;
753 }
754
755 @Override
sonu guptaeff184b2016-11-24 12:43:49 +0530756 public void traverseToParentWithoutValidation()
757 throws IllegalStateException {
758 // If traverse back to parent for logical root node comes.
sonu gupta1bb37b82016-11-11 16:51:18 +0530759 if (curNode.equals(rootNode)) {
sonu guptaeff184b2016-11-24 12:43:49 +0530760 freeRestResources(rootNode);
761 throw new IllegalStateException(E_INVOKE_PARENT);
sonu gupta1bb37b82016-11-11 16:51:18 +0530762 }
763 curNode = curNode.getParent();
764 }
sonu guptaeff184b2016-11-24 12:43:49 +0530765
766 /**
767 * Returns the method name's set for an augmented target node in an
768 * application tree.
769 *
770 * @return augGenMethodSet set of method name's
771 */
772 public Set<String> getAugGenMethodSet() {
773 return augGenMethodSet;
774 }
775
776 /**
777 * Sets the method name's set for an augmented target node in an
778 * application tree.
779 *
780 * @param augGenMethodSet set of method name's
781 */
782 public void setAugGenMethodSet(Set<String> augGenMethodSet) {
783 this.augGenMethodSet = augGenMethodSet;
784 }
sonu gupta1bb37b82016-11-11 16:51:18 +0530785}