blob: e9cdd574e483262ab3ee745fd05c6b7aa5a75664 [file] [log] [blame]
janani b05614f12016-10-04 12:55:43 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
janani b05614f12016-10-04 12:55:43 +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.ytb;
18
19import org.onosproject.yangutils.datamodel.YangAugment;
20import org.onosproject.yangutils.datamodel.YangCase;
janani b9069eb42016-11-24 17:50:08 +053021import org.onosproject.yangutils.datamodel.YangIdentity;
22import org.onosproject.yangutils.datamodel.YangIdentityRef;
janani b05614f12016-10-04 12:55:43 +053023import org.onosproject.yangutils.datamodel.YangLeafRef;
24import org.onosproject.yangutils.datamodel.YangNode;
25import org.onosproject.yangutils.datamodel.YangNotification;
26import org.onosproject.yangutils.datamodel.YangOutput;
27import org.onosproject.yangutils.datamodel.YangRpc;
janani b9069eb42016-11-24 17:50:08 +053028import org.onosproject.yangutils.datamodel.YangSchemaNode;
janani b05614f12016-10-04 12:55:43 +053029import org.onosproject.yangutils.datamodel.YangType;
30import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
31import org.onosproject.yangutils.translator.tojava.javamodel.JavaLeafInfoContainer;
32import org.onosproject.yms.app.utils.TraversalType;
33import org.onosproject.yms.app.ysr.YangSchemaRegistry;
34import org.onosproject.yms.ydt.YdtContextOperationType;
35
36import java.lang.reflect.InvocationTargetException;
37import java.lang.reflect.Method;
38import java.util.Arrays;
39import java.util.Base64;
janani b9069eb42016-11-24 17:50:08 +053040import java.util.Collection;
janani b05614f12016-10-04 12:55:43 +053041import java.util.HashSet;
janani b05614f12016-10-04 12:55:43 +053042import java.util.Set;
43
44import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_AUGMENT_NODE;
45import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_MULTI_INSTANCE_NODE;
46import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.BOOLEAN;
janani b05614f12016-10-04 12:55:43 +053047import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.EMPTY;
48import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT16;
49import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT32;
50import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT64;
51import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT8;
52import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.LEAFREF;
53import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT16;
54import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT32;
janani b05614f12016-10-04 12:55:43 +053055import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT8;
janani b9069eb42016-11-24 17:50:08 +053056import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
janani b05614f12016-10-04 12:55:43 +053057import static org.onosproject.yms.app.utils.TraversalType.PARENT;
58
59/**
60 * Representation of utility for YANG tree builder.
61 */
62public final class YtbUtil {
63
64 /**
65 * Static attribute for string value having null.
66 */
67 public static final String STR_NULL = "null";
68
69 /**
70 * Static attribute for a dot string.
71 */
72 public static final String PERIOD = ".";
73
74 private static final int ONE = 1;
janani b9069eb42016-11-24 17:50:08 +053075 private static final String YANG = "yang";
76 private static final String OP_TYPE = "OpType";
janani b05614f12016-10-04 12:55:43 +053077 private static final String STR_NONE = "NONE";
janani b05614f12016-10-04 12:55:43 +053078 private static final String ENUM_LEAF_IDENTIFIER = "$LeafIdentifier";
janani b05614f12016-10-04 12:55:43 +053079 private static final Set<YangDataTypes> PRIMITIVE_TYPES =
80 new HashSet<>(Arrays.asList(INT8, INT16, INT32, INT64, UINT8,
janani b9069eb42016-11-24 17:50:08 +053081 UINT16, UINT32, BOOLEAN, EMPTY));
82 private static final String TO_STRING = "toString";
janani b05614f12016-10-04 12:55:43 +053083
84 // No instantiation.
85 private YtbUtil() {
86 }
87
88 /**
89 * Returns the object of the node from the node info. Getting object for
90 * augment and case differs from other node.
91 *
92 * @param nodeInfo node info of the holder
93 * @param yangNode YANG node of the holder
94 * @return object of the parent
95 */
96 public static Object getParentObjectOfNode(YtbNodeInfo nodeInfo,
97 YangNode yangNode) {
98 Object object;
99 if (yangNode instanceof YangCase) {
100 object = nodeInfo.getCaseObject();
101 } else if (yangNode instanceof YangAugment) {
102 object = nodeInfo.getAugmentObject();
103 } else {
104 object = nodeInfo.getYangObject();
105 }
106 return object;
107 }
108
109 /**
janani b05614f12016-10-04 12:55:43 +0530110 * Returns the value of an attribute, in a class object. The attribute
111 * name is taken from the YANG node java name.
112 *
113 * @param nodeObj object of the node
114 * @param fieldName name of the attribute
115 * @return object of the attribute
116 * @throws NoSuchMethodException method not found exception
117 */
118 public static Object getAttributeOfObject(Object nodeObj, String fieldName)
119 throws NoSuchMethodException {
120 Class<?> nodeClass = nodeObj.getClass();
121 Method getterMethod;
122 try {
123 getterMethod = nodeClass.getDeclaredMethod(fieldName);
124 return getterMethod.invoke(nodeObj);
125 } catch (InvocationTargetException | IllegalAccessException e) {
126 throw new YtbException(e);
127 }
128 }
129
130 /**
131 * Returns the object of the declared method in parent class by invoking
132 * through the child class object.
133 *
janani b9069eb42016-11-24 17:50:08 +0530134 * @param childClass child class which inherits the parent class
135 * @param methodName name of the declared method
janani b05614f12016-10-04 12:55:43 +0530136 * @return value of the method
137 */
janani b9069eb42016-11-24 17:50:08 +0530138 public static Object getAttributeFromInheritance(Object childClass,
139 String methodName) {
140 Class<?> parentClass = childClass.getClass().getSuperclass();
janani b05614f12016-10-04 12:55:43 +0530141 Method getterMethod;
142 try {
143 getterMethod = parentClass.getDeclaredMethod(methodName);
144 return getterMethod.invoke(childClass);
145 } catch (InvocationTargetException | NoSuchMethodException |
146 IllegalAccessException e) {
147 throw new YtbException(e);
148 }
149 }
150
151 /**
152 * Returns interface class from an implementation class object.
153 *
janani b9069eb42016-11-24 17:50:08 +0530154 * @param obj implementation class object
janani b05614f12016-10-04 12:55:43 +0530155 * @return interface class
156 */
janani b9069eb42016-11-24 17:50:08 +0530157 public static Class<?> getInterfaceClassFromImplClass(Object obj) {
158 Class<?>[] interfaces = obj.getClass().getInterfaces();
janani b05614f12016-10-04 12:55:43 +0530159 if (interfaces.length > ONE) {
160 // TODO: Need to handle when impl class has more than one interface.
161 throw new YtbException("Implementation class having more than one" +
162 " interface is not handled");
163 }
164 return interfaces[0];
165 }
166
167 /**
168 * Returns the operation type value for a class object. If the operation
169 * type is not set, then none type is returned.
170 *
janani b9069eb42016-11-24 17:50:08 +0530171 * @param nodeObj node object
172 * @param typeName data type name
janani b05614f12016-10-04 12:55:43 +0530173 * @return operation type of the class
174 */
janani b9069eb42016-11-24 17:50:08 +0530175 public static YdtContextOperationType getNodeOpType(Object nodeObj,
176 String typeName) {
janani b05614f12016-10-04 12:55:43 +0530177 Object opTypeObj;
178 try {
janani b9069eb42016-11-24 17:50:08 +0530179 opTypeObj = getAttributeOfObject(nodeObj, typeName);
janani b05614f12016-10-04 12:55:43 +0530180 } catch (NoSuchMethodException e) {
181 return YdtContextOperationType.valueOf(STR_NONE);
182 }
183 String opTypeValue = String.valueOf(opTypeObj);
184 if (opTypeValue.equals(STR_NULL)) {
janani b9069eb42016-11-24 17:50:08 +0530185 return null;
janani b05614f12016-10-04 12:55:43 +0530186 }
187 return YdtContextOperationType.valueOf(opTypeValue);
188 }
189
190 /**
191 * Returns true, if data type of leaf is primitive data type; false
192 * otherwise.
193 *
194 * @param yangType leaf type
195 * @return true if data type is primitive; false otherwise
196 */
197 public static boolean isTypePrimitive(YangType yangType) {
198 if (yangType.getDataType() == LEAFREF) {
199 YangLeafRef leafRef =
200 (YangLeafRef) yangType.getDataTypeExtendedInfo();
201 return isPrimitiveDataType(leafRef.getEffectiveDataType()
202 .getDataType());
203 }
204 return isPrimitiveDataType(yangType.getDataType());
205 }
206
207 /**
208 * Returns the registered class from the YSR of the module node where
209 * augment is present.
210 *
211 * @param curNode current augment node
212 * @param registry schema registry
213 * @return class loader of module
214 */
215 public static Class<?> getClassLoaderForAugment(
216 YangNode curNode, YangSchemaRegistry registry) {
217 YangNode moduleNode = curNode.getParent();
218 String moduleName = moduleNode.getJavaClassNameOrBuiltInType();
219 String modulePackage = moduleNode.getJavaPackage();
sonu guptaeff184b2016-11-24 12:43:49 +0530220 return registry.getRegisteredClass(moduleNode
221 );
janani b05614f12016-10-04 12:55:43 +0530222 }
223
224 /**
225 * Returns the string true, if the leaf data is actually set; false
226 * otherwise.
227 *
janani b9069eb42016-11-24 17:50:08 +0530228 * @param holder leaf holder
janani b05614f12016-10-04 12:55:43 +0530229 * @param nodeObj object if the node
230 * @param javaName java name of the leaf
231 * @param methodName getter method name
232 * @return string value of the boolean method
janani b9069eb42016-11-24 17:50:08 +0530233 * @throws NoSuchMethodException if the method is not present
janani b05614f12016-10-04 12:55:43 +0530234 */
janani b9069eb42016-11-24 17:50:08 +0530235 public static String isValueOrSelectLeafSet(YangSchemaNode holder, Object nodeObj,
236 String javaName, String methodName)
237 throws NoSuchMethodException {
janani b05614f12016-10-04 12:55:43 +0530238
239 Class<?> nodeClass = nodeObj.getClass();
janani b05614f12016-10-04 12:55:43 +0530240
241 // Appends the enum inner package to the interface class package.
janani b9069eb42016-11-24 17:50:08 +0530242 String enumPackage = holder.getJavaPackage() + PERIOD +
243 getCapitalCase(holder.getJavaClassNameOrBuiltInType()) +
244 ENUM_LEAF_IDENTIFIER;
janani b05614f12016-10-04 12:55:43 +0530245
janani b9069eb42016-11-24 17:50:08 +0530246 ClassLoader classLoader = nodeClass.getClassLoader();
janani b05614f12016-10-04 12:55:43 +0530247 Class leafEnum;
248 try {
249 leafEnum = classLoader.loadClass(enumPackage);
250 Method getterMethod = nodeClass.getMethod(methodName, leafEnum);
251 // Gets the value of the enum.
252 Enum<?> value = Enum.valueOf(leafEnum, javaName.toUpperCase());
253 // Invokes the method with the value of enum as param.
254 return String.valueOf(getterMethod.invoke(nodeObj, value));
255 } catch (IllegalAccessException | InvocationTargetException |
janani b9069eb42016-11-24 17:50:08 +0530256 ClassNotFoundException e) {
janani b05614f12016-10-04 12:55:43 +0530257 throw new YtbException(e);
258 }
259 }
260
261 /**
262 * Returns the string value from the respective data types of the
263 * leaf/leaf-list.
janani b05614f12016-10-04 12:55:43 +0530264 *
janani b9069eb42016-11-24 17:50:08 +0530265 * @param holder leaf/leaf-list holder
266 * @param holderObj leaf/leaf-list holder object
267 * @param name leaf/leaf-list name
268 * @param fieldObj object of the leaf/leaf-list field
269 * @param dataType type of the leaf/leaf-list
janani b05614f12016-10-04 12:55:43 +0530270 * @return string value from the type
271 */
janani b9069eb42016-11-24 17:50:08 +0530272 public static String getStringFromType(YangSchemaNode holder, Object holderObj,
273 String name, Object fieldObj, YangType dataType) {
274
275 if (fieldObj == null) {
276 throw new YtbException("Value of " + holder.getName() + " is null");
277 }
278
janani b05614f12016-10-04 12:55:43 +0530279 YangDataTypes type = dataType.getDataType();
280 switch (type) {
281 case INT8:
282 case INT16:
283 case INT32:
284 case INT64:
285 case UINT8:
286 case UINT16:
287 case UINT32:
288 case UINT64:
289 case EMPTY:
janani b05614f12016-10-04 12:55:43 +0530290 case STRING:
291 case DECIMAL64:
292 case INSTANCE_IDENTIFIER:
293 case DERIVED:
294 case UNION:
janani b9069eb42016-11-24 17:50:08 +0530295 case ENUMERATION:
janani b05614f12016-10-04 12:55:43 +0530296 case BOOLEAN:
janani b9069eb42016-11-24 17:50:08 +0530297 return String.valueOf(fieldObj).trim();
298
janani b05614f12016-10-04 12:55:43 +0530299 case BITS:
janani b9069eb42016-11-24 17:50:08 +0530300 return getBitsValue(holder, holderObj, name, fieldObj).trim();
janani b05614f12016-10-04 12:55:43 +0530301
302 case BINARY:
303 return Base64.getEncoder().encodeToString((byte[]) fieldObj);
304
janani b9069eb42016-11-24 17:50:08 +0530305 case IDENTITYREF:
306 YangIdentityRef ir =
307 (YangIdentityRef) dataType.getDataTypeExtendedInfo();
308 if (ir.isInGrouping()) {
309 return String.valueOf(fieldObj).trim();
310 }
311 return getIdentityRefValue(fieldObj, ir, holderObj);
312
janani b05614f12016-10-04 12:55:43 +0530313 case LEAFREF:
314 YangLeafRef leafRef =
315 (YangLeafRef) dataType.getDataTypeExtendedInfo();
janani b9069eb42016-11-24 17:50:08 +0530316 return getStringFromType(holder, holderObj, name, fieldObj,
317 leafRef.getEffectiveDataType());
janani b05614f12016-10-04 12:55:43 +0530318
319 default:
320 throw new YtbException("Unsupported data type. Cannot be " +
321 "processed.");
322 }
323 }
324
325 /**
janani b9069eb42016-11-24 17:50:08 +0530326 * Returns the string values for the data type bits.
janani b05614f12016-10-04 12:55:43 +0530327 *
janani b9069eb42016-11-24 17:50:08 +0530328 * @param holder leaf/leaf-list holder
329 * @param holderObj leaf/leaf-list holder object
330 * @param name leaf/leaf-list name
331 * @param fieldObj object of the leaf/leaf-list field
332 * @return string value for bits type
janani b05614f12016-10-04 12:55:43 +0530333 */
janani b9069eb42016-11-24 17:50:08 +0530334 private static String getBitsValue(YangSchemaNode holder, Object holderObj,
335 String name, Object fieldObj) {
336
337 Class<?> holderClass = holderObj.getClass();
338 String interfaceName = holder.getJavaClassNameOrBuiltInType();
339 String className = interfaceName.toLowerCase() + PERIOD +
340 getCapitalCase(name);
341 String pkgName = holder.getJavaPackage() + PERIOD + className;
342 ClassLoader classLoader = holderClass.getClassLoader();
343
344 Class<?> bitClass;
345 try {
346 bitClass = classLoader.loadClass(pkgName);
347 Method getterMethod = bitClass.getDeclaredMethod(
348 TO_STRING, fieldObj.getClass());
349 return String.valueOf(getterMethod.invoke(null, fieldObj));
350 } catch (ClassNotFoundException | NoSuchMethodException |
351 InvocationTargetException | IllegalAccessException e) {
352 throw new YtbException(e);
janani b05614f12016-10-04 12:55:43 +0530353 }
janani b9069eb42016-11-24 17:50:08 +0530354 }
355
356 /**
357 * Returns the string value of the type identity-ref.
358 *
359 * @param fieldObj object of the leaf/leaf-list field
360 * @param ir YANG identity ref
361 * @param holderObj leaf/leaf-list holder object
362 * @return string value for identity ref type
363 */
364 private static String getIdentityRefValue(Object fieldObj, YangIdentityRef ir,
365 Object holderObj) {
366
367 YangIdentity id = ir.getReferredIdentity();
368 String idName = id.getJavaClassNameOrBuiltInType();
369 String idPkg = id.getJavaPackage() + PERIOD + getCapitalCase(idName);
370 String methodName = idName + getCapitalCase(TO_STRING);
371
372 Class<?> holderClass = holderObj.getClass();
373 ClassLoader classLoader = holderClass.getClassLoader();
374 Class<?> idClass;
375 try {
376 idClass = classLoader.loadClass(idPkg);
377 Method method = idClass.getDeclaredMethod(methodName, null);
378 return String.valueOf(method.invoke(fieldObj, null)).trim();
379 } catch (ClassNotFoundException | NoSuchMethodException |
380 InvocationTargetException | IllegalAccessException e) {
381 throw new YtbException(e);
382 }
janani b05614f12016-10-04 12:55:43 +0530383 }
384
385 /**
386 * Returns true, if the data type is primitive; false otherwise.
387 *
388 * @param dataType data type
389 * @return true if the data type is primitive; false otherwise
390 */
391 private static boolean isPrimitiveDataType(YangDataTypes dataType) {
392 return PRIMITIVE_TYPES.contains(dataType);
393 }
394
395 /**
396 * Returns true, if processing of the node is not required; false otherwise.
397 * For the nodes such as notification, RPC, augment there is a different
398 * flow, so these nodes are skipped in normal conditions.
399 *
400 * @param yangNode node to be checked
401 * @return true if node processing is not required; false otherwise.
402 */
403 public static boolean isNonProcessableNode(YangNode yangNode) {
404 return yangNode != null && (yangNode instanceof YangNotification) ||
405 (yangNode instanceof YangRpc) || (yangNode instanceof YangAugment);
406 }
407
408 /**
409 * Returns true, if multi instance node; false otherwise.
410 *
411 * @param yangNode YANG node
412 * @return true, if multi instance node; false otherwise.
413 */
414 public static boolean isMultiInstanceNode(YangNode yangNode) {
415 return yangNode.getYangSchemaNodeType() == YANG_MULTI_INSTANCE_NODE;
416 }
417
418 /**
419 * Returns true, if augment node; false otherwise.
420 *
421 * @param yangNode YANG node
422 * @return true, if augment node; false otherwise.
423 */
424 public static boolean isAugmentNode(YangNode yangNode) {
425 return yangNode.getYangSchemaNodeType() == YANG_AUGMENT_NODE;
426 }
427
428 /**
429 * Returns string for throwing error when empty object is given as input
430 * to YTB.
431 *
432 * @param objName name of the object
433 * @return error message
434 */
435 public static String emptyObjErrMsg(String objName) {
436 return "The " + objName + " given for tree creation cannot be null";
437 }
438
439 /**
440 * Returns the java name for the nodes, leaf/leaf-list.
441 *
442 * @param node YANG node
443 * @return node java name
444 */
445 public static String getJavaName(Object node) {
446 return ((JavaLeafInfoContainer) node).getJavaName(null);
447 }
448
449 /**
450 * Returns true, if the list is not null and non-empty; false otherwise.
451 *
janani b9069eb42016-11-24 17:50:08 +0530452 * @param c collection object
janani b05614f12016-10-04 12:55:43 +0530453 * @return true, if the list is not null and non-empty; false otherwise
454 */
janani b9069eb42016-11-24 17:50:08 +0530455 public static boolean nonEmpty(Collection<?> c) {
456 return c != null && !c.isEmpty();
janani b05614f12016-10-04 12:55:43 +0530457 }
458
459 /**
460 * Returns true, if the string is not null and non-empty; false otherwise.
461 *
462 * @param str string value
463 * @return true, if the string is not null and non-empty; false otherwise.
464 */
janani b9069eb42016-11-24 17:50:08 +0530465 public static boolean nonEmpty(String str) {
janani b05614f12016-10-04 12:55:43 +0530466 return str != null && !str.isEmpty();
467 }
468
469 /**
470 * Returns true when the node processing of RPC and notification is
471 * completed; false otherwise. For RPC and notification, processing of
472 * other nodes are invalid, so once node gets completed, it must be stopped.
473 *
474 * @param curNode current node
475 * @param curTraversal current traversal of the node
476 * @return true, if the node processing is completed; false otherwise.
477 */
478 public static boolean isNodeProcessCompleted(
479 YangNode curNode, TraversalType curTraversal) {
480 return (curTraversal == PARENT &&
481 curNode instanceof YangNotification) ||
482 curNode instanceof YangOutput;
483 }
484
janani b9069eb42016-11-24 17:50:08 +0530485 /**
486 * Returns the name of the operation type variable from the yang name.
487 *
488 * @param curNode YANG node
489 * @return name of operation type
490 */
491 public static String getOpTypeName(YangNode curNode) {
492 return YANG + getCapitalCase(curNode.getJavaClassNameOrBuiltInType()) +
493 OP_TYPE;
494 }
janani b05614f12016-10-04 12:55:43 +0530495}