blob: a9f15f2095edab1b504c4e4e17eacbb7610280b0 [file] [log] [blame]
sonu guptaeff184b2016-11-24 12:43:49 +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
17
18package org.onosproject.yms.app.ydt;
19
20import org.onosproject.yangutils.datamodel.YangAugment;
21import org.onosproject.yangutils.datamodel.YangSchemaNode;
22import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
23import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
24import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
25import org.onosproject.yms.app.ydt.exceptions.YdtException;
26import org.onosproject.yms.ydt.YdtContextOperationType;
27
28import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.DELETE_ONLY;
29import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.OTHER_EDIT;
30import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg;
31import static org.onosproject.yms.ydt.YdtContextOperationType.CREATE;
32import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE;
33import static org.onosproject.yms.ydt.YdtContextOperationType.MERGE;
34
35/**
36 * Utils to support yang data tree node creation.
37 */
38final class YdtUtils {
39
40 // YDT formatted error string
41 private static final String E_CREATE_OP =
42 "Create request is not allowed under delete operation.";
43 private static final String E_DELETE_OP =
44 "Delete request is not allowed under create operation.";
45 private static final String FMT_TOO_FEW =
46 "Too few key parameters in %s. Expected %d; actual %d.";
47 private static final String FMT_TOO_MANY =
48 "Too many key parameters in %s. Expected %d; actual %d.";
49
50 //No instantiation.
51 private YdtUtils() {
52 }
53
54 /**
55 * Returns the app tree operation type with the help of YdtOperation type.
56 *
57 * @param opType ydt operation type
58 * @return app tree operation type
59 */
60 static YdtAppNodeOperationType getAppOpTypeFromYdtOpType(
61 YdtContextOperationType opType) {
62 // Get the app tree operation type.
63 switch (opType) {
64 case CREATE:
65 case MERGE:
66 case REPLACE:
67 return OTHER_EDIT;
68
69 case DELETE:
70 case REMOVE:
71 return DELETE_ONLY;
72
73 default:
74 return null;
75 //TODO handle the default data type.
76 }
77 }
78
79 /**
80 * Validates the various combination of operation type.
81 *
82 * @param parentOpType Reference for parent node operation type
83 * @param childOpType type of YANG data tree node operation
84 * @throws YdtException when user requested node operation type is
85 * not valid as per parent node operation type
86 */
87 private static void validateOperationType(YdtContextOperationType parentOpType,
88 YdtContextOperationType childOpType)
89 throws YdtException {
90
91 switch (parentOpType) {
92 case CREATE:
93 // Inside the create operation delete operation should not come.
94 if (childOpType == DELETE) {
95 throw new YdtException(E_CREATE_OP);
96 }
97 break;
98 case DELETE:
99 // Inside the delete operation create operation should not come.
100 if (childOpType == CREATE) {
101 throw new YdtException(E_DELETE_OP);
102 }
103 break;
104 default:
105 //TODO check all possible scenario.
106 }
107 }
108
109 /**
110 * Returns the operation type for non leaf node.
111 * When "operation" attribute for current node is not specified or null,
112 * then the operation applied to the parent data node of the
113 * configuration is used. If no parent data node is available,
114 * then the default-operation'value is used.
115 * If default operation type is not set, merge will be taken as default
116 * operation type.
117 *
118 * @param type operation type of parent node
119 * @param defType YDT default operation type
120 * @return operation type for current non leaf node
121 */
122 private static YdtContextOperationType getOperationType(
123 YdtContextOperationType type, YdtContextOperationType defType) {
124 return type != null ? type : (defType != null ? defType : MERGE);
125 }
126
127 /**
128 * Returns the yang node identifier with requested name and namespace.
129 *
130 * @param name name of the node
131 * @param namespace namespace of the node
132 * @return yang node identifier
133 */
134 static YangSchemaNodeIdentifier getNodeIdentifier(String name,
135 String namespace) {
136 YangSchemaNodeIdentifier id = new YangSchemaNodeIdentifier();
137 id.setName(name);
138 id.setNameSpace(new NameSpace(namespace));
139 return id;
140 }
141
142 /**
143 * Checks the user supplied list of argument match's the expected value
144 * or not.
145 *
146 * @param name name of the parent list/leaf-list node
147 * @param expected count suppose to be
148 * @param actual user supplied values count
149 * @throws YdtException when user requested multi instance node instance's
150 * count doesn't fit into the allowed instance limit
151 */
152 static void checkElementCount(String name, int expected,
153 int actual) throws YdtException {
154 if (expected < actual) {
155 throw new YdtException(
156 errorMsg(FMT_TOO_MANY, name, expected, actual));
157 } else if (expected > actual) {
158 throw new YdtException(
159 errorMsg(FMT_TOO_FEW, name, expected, actual));
160 }
161 }
162
163 /**
164 * Returns the valid operation type for requested ydt node after performing
165 * validation.
166 *
167 * @param opType user requested operation type
168 * @param newNode new requested ydt node
169 * @param parentNode parent node under which new node to be added
170 * @return operation type
171 * @throws YdtException when user requested node operation type is
172 * not valid as per parent node operation type
173 */
174 static YdtContextOperationType getValidOpType(
175 YdtContextOperationType opType, YdtContextOperationType defOpType,
176 YdtNode newNode, YdtNode parentNode)
177 throws YdtException {
178
179 switch (newNode.getYdtType()) {
180
181 case SINGLE_INSTANCE_NODE:
182 case MULTI_INSTANCE_NODE:
183
184 // Reference for parent node operation type.
185 YdtContextOperationType parentOpType =
186 parentNode.getYdtContextOperationType();
187
188 if (opType == null) {
189 opType = getOperationType(parentOpType, defOpType);
190 } else if (parentOpType != null) {
191 validateOperationType(parentOpType, opType);
192 }
193
194 return opType;
195
196 /*
197 * Nodes other then single/multi instance node does not support
198 * operation type so no need of validation for those.
199 */
200 default:
201 return null;
202 }
203 }
204
205 /**
206 * Returns augmenting node module yang schema node.
207 *
208 * @param id schema node identifier
209 * @param contextInfo Yang Schema node context info
210 * which is having YangSchemaNode and
211 * ContextSwitchedNode
212 * @return augmenting node module yang schema node
213 * @throws YdtException when user requested node schema doesn't exist
214 */
215 public static YangSchemaNode getAugmentingSchemaNode(
216 YangSchemaNodeIdentifier id,
217 YangSchemaNodeContextInfo contextInfo) throws YdtException {
218 YangSchemaNode lastAugMod = null;
219 YangSchemaNode switchedNode =
220 contextInfo.getContextSwitchedNode();
221
222 // Finding the last augmenting schema for case/choice scenario.
223 while (switchedNode != null) {
224 if (switchedNode instanceof YangAugment) {
225 lastAugMod = switchedNode;
226 }
227 try {
228 switchedNode = switchedNode.getChildSchema(id)
229 .getContextSwitchedNode();
230 } catch (DataModelException e) {
231 throw new YdtException(e.getMessage());
232 }
233 }
234 return lastAugMod;
235 }
236
237 /**
238 * De-reference all the tree node by walking the whole YDT from logical
239 * root node.
240 * This will be called only when any exception occurs while processing
241 * the node in Ydt tree.
242 *
243 * @param rootNode ydt logical root node
244 */
245 public static void freeRestResources(YdtNode rootNode) {
246
247 YdtNode currentNode = rootNode;
248 while (currentNode != null) {
249
250 // Move down to first child
251 YdtNode nextNode = currentNode.getFirstChild();
252 if (nextNode != null) {
253 currentNode = nextNode;
254 continue;
255 }
256
257 // No child nodes, so walk tree
258 while (currentNode != null) {
259 // To keep the track of last sibling.
260 YdtNode lastSibling = currentNode;
261
262 // Move to sibling if possible.
263 nextNode = currentNode.getNextSibling();
264
265 // free currentNode resources
266 free(lastSibling);
267
268 lastSibling.getNamespace();
269 if (nextNode != null) {
270 currentNode = nextNode;
271 break;
272 }
273
274 // Move up
275 if (currentNode.equals(rootNode)) {
276 currentNode = null;
277 } else {
278 currentNode = currentNode.getParent();
279 lastSibling.setParent(null);
280 }
281 }
282 }
283 }
284
285 /**
286 * Free the give YDT node by de-referencing it to null.
287 *
288 * @param node node to be freed
289 */
290 private static void free(YdtNode node) {
291 if (node.getParent() != null) {
292 YdtNode parent = node.getParent();
293 parent.setChild(null);
294 parent.setLastChild(null);
295 if (node.getNextSibling() != null) {
296 parent.setChild(node.getNextSibling());
297 }
298 }
299 YdtNode parentRef = node.getParent();
300 node = new YdtLogicalNode(null, null);
301 node.setParent(parentRef);
302 }
303}