blob: d72edc176a57229c176952816d06e700ee3672d1 [file] [log] [blame]
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +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.yob;
18
19import org.onosproject.yangutils.datamodel.RpcNotificationContainer;
Vidyashree Ramaf463dc52016-10-06 12:46:33 +053020import org.onosproject.yangutils.datamodel.YangBit;
21import org.onosproject.yangutils.datamodel.YangBits;
22import org.onosproject.yangutils.datamodel.YangLeaf;
23import org.onosproject.yangutils.datamodel.YangLeafRef;
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +053024import org.onosproject.yangutils.datamodel.YangNode;
25import org.onosproject.yangutils.datamodel.YangSchemaNode;
26import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
27import org.onosproject.yangutils.datamodel.YangType;
28import org.onosproject.yms.app.ydt.YdtExtendedContext;
29import org.onosproject.yms.app.yob.exception.YobException;
30import org.onosproject.yms.app.ysr.YangSchemaRegistry;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import java.lang.reflect.Constructor;
35import java.lang.reflect.InvocationTargetException;
36import java.lang.reflect.Method;
37import java.math.BigDecimal;
38import java.math.BigInteger;
Vidyashree Ramaf463dc52016-10-06 12:46:33 +053039import java.util.Base64;
40import java.util.BitSet;
41import java.util.Map;
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +053042
43import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_AUGMENT_NODE;
44import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
45import static org.onosproject.yms.app.ydt.AppType.YOB;
46import static org.onosproject.yms.app.yob.YobConstants.DEFAULT;
47import static org.onosproject.yms.app.yob.YobConstants.E_DATA_TYPE_NOT_SUPPORT;
48import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_LOAD_CONSTRUCTOR;
49import static org.onosproject.yms.app.yob.YobConstants.E_INVALID_DATA_TREE;
50import static org.onosproject.yms.app.yob.YobConstants.FROM_STRING;
51import static org.onosproject.yms.app.yob.YobConstants.L_FAIL_TO_LOAD_CLASS;
52import static org.onosproject.yms.app.yob.YobConstants.OF;
53import static org.onosproject.yms.app.yob.YobConstants.OP_PARAM;
54import static org.onosproject.yms.app.yob.YobConstants.PERIOD;
Vidyashree Ramaf463dc52016-10-06 12:46:33 +053055import static org.onosproject.yms.app.yob.YobConstants.SPACE;
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +053056
57/**
58 * Utils to support object creation.
59 */
60final class YobUtils {
61
62 private static final Logger log = LoggerFactory.getLogger(YobUtils.class);
63
64 // no instantiation
65 private YobUtils() {
66 }
67
68 /**
69 * Sets data from string value in parent method.
70 *
71 * @param type refers to YANG type
72 * @param leafValue leafValue argument is used to set the value
73 * in method
74 * @param parentSetterMethod Invokes the underlying method represented
75 * by this parentSetterMethod
76 * @param parentBuilderObject the parentBuilderObject is to invoke the
77 * underlying method
78 * @param ydtExtendedContext ydtExtendedContext is used to get
79 * application related
80 * information maintained in YDT
81 * @throws InvocationTargetException if failed to invoke method
82 * @throws IllegalAccessException if member cannot be accessed
83 * @throws NoSuchMethodException if method is not found
84 */
85 static void setDataFromStringValue(YangType<?> type, String leafValue,
86 Method parentSetterMethod,
87 Object parentBuilderObject,
88 YdtExtendedContext ydtExtendedContext)
89 throws InvocationTargetException, IllegalAccessException,
90 NoSuchMethodException {
91 switch (type.getDataType()) {
92 case INT8:
93 parentSetterMethod.invoke(parentBuilderObject,
94 Byte.parseByte(leafValue));
95 break;
96
97 case UINT8:
98 case INT16:
99 parentSetterMethod.invoke(parentBuilderObject,
100 Short.parseShort(leafValue));
101 break;
102
103 case UINT16:
104 case INT32:
105 parentSetterMethod.invoke(parentBuilderObject,
106 Integer.parseInt(leafValue));
107 break;
108
109 case UINT32:
110 case INT64:
111 parentSetterMethod.invoke(parentBuilderObject,
112 Long.parseLong(leafValue));
113 break;
114
115 case UINT64:
116 parentSetterMethod.invoke(parentBuilderObject,
117 new BigInteger(leafValue));
118 break;
119
120 case EMPTY:
121 case BOOLEAN:
122 parentSetterMethod.invoke(parentBuilderObject,
123 Boolean.parseBoolean(leafValue));
124 break;
125
126 case STRING:
127 parentSetterMethod.invoke(parentBuilderObject, leafValue);
128 break;
129
130 case BINARY:
Vidyashree Ramaf463dc52016-10-06 12:46:33 +0530131 byte[] value = Base64.getDecoder().decode(leafValue);
132 parentSetterMethod.invoke(parentBuilderObject, value);
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530133 break;
134
135 case BITS:
Vidyashree Ramaf463dc52016-10-06 12:46:33 +0530136 YangBits yangBits = (YangBits) type.getDataTypeExtendedInfo();
137 parentSetterMethod.invoke(parentBuilderObject,
138 getBitSetValueFromString(yangBits,
139 leafValue));
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530140 break;
141
142 case DECIMAL64:
143 parentSetterMethod.invoke(parentBuilderObject,
144 new BigDecimal(leafValue));
145 break;
146
147 case DERIVED:
148 parseDerivedTypeInfo(ydtExtendedContext, parentSetterMethod,
149 parentBuilderObject, leafValue, false);
150 break;
151
152 case UNION:
Vidyashree Ramaf463dc52016-10-06 12:46:33 +0530153 parseDerivedTypeInfo(ydtExtendedContext, parentSetterMethod,
154 parentBuilderObject, leafValue, false);
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530155 break;
156
157 case LEAFREF:
Vidyashree Ramaf463dc52016-10-06 12:46:33 +0530158 parseLeafRefTypeInfo(ydtExtendedContext, parentSetterMethod,
159 parentBuilderObject, leafValue);
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530160 break;
161
162 case ENUMERATION:
163 parseDerivedTypeInfo(ydtExtendedContext, parentSetterMethod,
164 parentBuilderObject, leafValue, true);
165 break;
166
167 default:
168 log.error(E_DATA_TYPE_NOT_SUPPORT);
169 }
170 }
171
172 /**
173 * To set data into parent setter method from string value for derived type.
174 *
175 * @param leafValue leafValue argument is used to set the value
176 * in method
177 * @param parentSetterMethod Invokes the underlying method represented
178 * by this parentSetterMethod
179 * @param parentBuilderObject the parentBuilderObject is to invoke the
180 * underlying method
181 * @param ydtExtendedContext ydtExtendedContext is used to get
182 * application related
183 * information maintained in YDT
184 * @param isEnum isEnum parameter is used to check whether
185 * type is enum or derived
186 * information maintained in YDT
187 * @throws InvocationTargetException if failed to invoke method
188 * @throws IllegalAccessException if member cannot be accessed
189 * @throws NoSuchMethodException if the required method is not found
190 */
191 private static void parseDerivedTypeInfo(YdtExtendedContext ydtExtendedContext,
192 Method parentSetterMethod,
193 Object parentBuilderObject,
194 String leafValue, boolean isEnum)
195 throws InvocationTargetException, IllegalAccessException,
196 NoSuchMethodException {
197 Class<?> childSetClass = null;
198 Constructor<?> childConstructor = null;
199 Object childValue = null;
200 Object childObject = null;
201 Method childMethod = null;
202
203 YangSchemaNode yangJavaModule = ydtExtendedContext.getYangSchemaNode();
204 String qualifiedClassName = yangJavaModule.getJavaPackage() + PERIOD +
205 getCapitalCase(yangJavaModule.getJavaClassNameOrBuiltInType());
206 ClassLoader classLoader = getClassLoader(null, qualifiedClassName,
207 ydtExtendedContext, null);
208 try {
209 childSetClass = classLoader.loadClass(qualifiedClassName);
210 } catch (ClassNotFoundException e) {
211 log.error(L_FAIL_TO_LOAD_CLASS, qualifiedClassName);
212 }
213 if (!isEnum) {
214
215 if (childSetClass != null) {
216 childConstructor = childSetClass.getDeclaredConstructor();
217 }
218
219 if (childConstructor != null) {
220 childConstructor.setAccessible(true);
221 }
222 try {
223 if (childConstructor != null) {
224 childObject = childConstructor.newInstance();
225 }
226 } catch (InstantiationException e) {
227 log.error(E_FAIL_TO_LOAD_CONSTRUCTOR, qualifiedClassName);
228 }
229 if (childSetClass != null) {
230 childMethod = childSetClass
231 .getDeclaredMethod(FROM_STRING, String.class);
232 }
233 } else {
234 if (childSetClass != null) {
235 childMethod = childSetClass.getDeclaredMethod(OF, String.class);
236 }
237 //leafValue = JavaIdentifierSyntax.getEnumJavaAttribute(leafValue);
238 //leafValue = leafValue.toUpperCase();
239 }
240 if (childMethod != null) {
241 childValue = childMethod.invoke(childObject, leafValue);
242 }
243
244 parentSetterMethod.invoke(parentBuilderObject, childValue);
245 }
246
247 /**
Vidyashree Ramaf463dc52016-10-06 12:46:33 +0530248 * To set data into parent setter method from string value for leafref type.
249 *
250 * @param leafValue leaf value to be set
251 * @param parentSetterMethod the parent setter method to be invoked
252 * @param parentBuilderObject the parent build object on which to invoke
253 * the method
254 * @param ydtExtendedContext application context
255 * @throws InvocationTargetException if method could not be invoked
256 * @throws IllegalAccessException if method could not be accessed
257 * @throws NoSuchMethodException if method does not exist
258 */
259 private static void parseLeafRefTypeInfo(YdtExtendedContext ydtExtendedContext,
260 Method parentSetterMethod,
261 Object parentBuilderObject,
262 String leafValue)
263 throws InvocationTargetException, IllegalAccessException,
264 NoSuchMethodException {
265 YangSchemaNode schemaNode = ydtExtendedContext.getYangSchemaNode();
266 YangLeafRef leafRef = (YangLeafRef) ((YangLeaf) schemaNode)
267 .getDataType().getDataTypeExtendedInfo();
268 YobUtils.setDataFromStringValue(leafRef.getEffectiveDataType(),
269 leafValue, parentSetterMethod,
270 parentBuilderObject, ydtExtendedContext);
271 }
272
273 /**
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530274 * Updates class loader for all the classes.
275 *
276 * @param registry YANG schema registry
277 * @param qualifiedClassName qualified class name
278 * @param curNode YDT context
279 * @param rootNode application root node
280 * @return current class loader
281 * @throws YobException if the YDT is an invalid tree
282 */
283 static ClassLoader getClassLoader(YangSchemaRegistry registry,
284 String qualifiedClassName,
285 YdtExtendedContext curNode,
286 YdtExtendedContext rootNode) {
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530287 if (rootNode != null && curNode == rootNode) {
288 YangSchemaNode curSchemaNode = curNode.getYangSchemaNode();
289 while (!(curSchemaNode instanceof RpcNotificationContainer)) {
290 curNode = (YdtExtendedContext) curNode.getParent();
291 if (curNode == null) {
292 throw new YobException(E_INVALID_DATA_TREE);
293 }
294 curSchemaNode = curNode.getYangSchemaNode();
295
296 }
297
298 Class<?> regClass = registry.getRegisteredClass(curSchemaNode,
299 qualifiedClassName);
300 return regClass.getClassLoader();
301
302 }
303
304 YdtExtendedContext parent =
305 (YdtExtendedContext) curNode.getParent();
306 YobWorkBench parentBuilderContainer =
307 (YobWorkBench) parent.getAppInfo(YOB);
308 Object parentObj =
309 parentBuilderContainer.getParentBuilder(curNode, registry);
310 return parentObj.getClass().getClassLoader();
311 }
312
313 /**
314 * Returns the class loader to be used for the switched context schema node.
315 *
316 * @param curLoader current context class loader
317 * @param context switched context
318 * @param registry schema registry
319 * @return class loader to be used for the switched context schema node
320 */
321 static ClassLoader getTargetClassLoader(
322 ClassLoader curLoader,
323 YangSchemaNodeContextInfo context,
324 YangSchemaRegistry registry) {
325 YangSchemaNode augmentSchemaNode = context.getContextSwitchedNode();
326 if (augmentSchemaNode.getYangSchemaNodeType() == YANG_AUGMENT_NODE) {
327 YangSchemaNode moduleNode =
328 ((YangNode) augmentSchemaNode).getParent();
329
330 Class<?> moduleClass = registry.getRegisteredClass(
331 moduleNode, getCapitalCase(
332 moduleNode.getJavaClassNameOrBuiltInType()));
333 return moduleClass.getClassLoader();
334 }
335
336 return curLoader;
337 }
338
339 /**
340 * Returns the qualified default / op param class.
341 *
342 * @param schemaNode schema node of the required class
343 * @return qualified default / op param class name
344 */
345 static String getQualifiedDefaultClass(YangSchemaNode schemaNode) {
346 String packageName = schemaNode.getJavaPackage();
347 String className = getCapitalCase(
348 schemaNode.getJavaClassNameOrBuiltInType());
349
350 if (schemaNode instanceof RpcNotificationContainer) {
351 return packageName + PERIOD + className + OP_PARAM;
352 }
353
354 return packageName + PERIOD + DEFAULT + className;
355 }
356
357 /**
358 * Returns the qualified interface name.
359 *
360 * @param schemaNode schema node of the required class
361 * @return qualified interface name
362 */
363 static String getQualifiedinterface(YangSchemaNode schemaNode) {
364 String packageName = schemaNode.getJavaPackage();
365 String className = getCapitalCase(
366 schemaNode.getJavaClassNameOrBuiltInType());
367
368 return packageName + PERIOD + className;
369 }
Vidyashree Ramaf463dc52016-10-06 12:46:33 +0530370
371 /**
372 * Returns BitSet value from string.
373 *
374 * @param yangBits schema node of the YANG bits
375 * @param leafValue leaf value from RESTCONF
376 * @return BitSet value
377 */
378 private static BitSet getBitSetValueFromString(YangBits yangBits,
379 String leafValue) {
380 String[] bitNames = leafValue.trim().split(SPACE);
381 Map<String, YangBit> bitNameMap = yangBits.getBitNameMap();
382 BitSet bitDataSet = new BitSet();
383 YangBit bit;
384 for (String bitName : bitNames) {
385 bit = bitNameMap.get(bitName);
386 if (bit == null) {
387 throw new YobException("Unable to find corresponding bit" +
388 " position for bit : " + bitName);
389 }
390 bitDataSet.set(bit.getPosition());
391 }
392 return bitDataSet;
393 }
VinodKumarS-Huawei7b1733c2016-10-25 13:44:26 +0530394}