2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.ccsdk.sli.core.sli.provider;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.PrintStream;
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32 import java.lang.reflect.ParameterizedType;
33 import java.lang.reflect.Type;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Properties;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
44 import org.opendaylight.yangtools.yang.binding.Identifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class MdsalHelper {
50 private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class);
51 private static Properties yangMappingProperties = new Properties();
54 public static void setProperties(Properties input) {
55 setYangMappingProperties(input);
58 public static void setYangMappingProperties(Properties properties) {
59 for (Object propNameObj : properties.keySet()) {
60 String propName = (String) propNameObj;
61 MdsalHelper.yangMappingProperties.setProperty(propName, properties.getProperty(propName));
65 public static void loadProperties(String propertiesFile) {
66 File file = new File(propertiesFile);
67 Properties properties = new Properties();
68 if (file.isFile() && file.canRead()) {
69 try (InputStream input = new FileInputStream(file)) {
70 properties.load(input);
71 MdsalHelper.setYangMappingProperties(properties);
72 LOG.info("Loaded properties from " + propertiesFile);
73 } catch (Exception e) {
74 LOG.error("Failed to load properties " + propertiesFile + "\n", e);
77 LOG.error("Failed to load the properties file " + propertiesFile + "\n");
78 LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n");
82 public static Properties toProperties(Properties props, Object fromObj) {
83 Class fromClass = null;
85 if (fromObj != null) {
86 fromClass = fromObj.getClass();
88 return (toProperties(props, "", fromObj, fromClass));
91 public static Properties toProperties(Properties props, String pfx, Object fromObj) {
92 Class fromClass = null;
94 if (fromObj != null) {
95 fromClass = fromObj.getClass();
98 return (toProperties(props, pfx, fromObj, fromClass));
101 public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) {
103 if (fromObj == null) {
107 String simpleName = fromClass.getSimpleName();
109 LOG.trace("Extracting properties from " + fromClass.getName() + " class");
110 if (fromObj instanceof List) {
112 // Class is a List. List should contain yang-generated classes.
113 LOG.trace(fromClass.getName() + " is a List");
115 List fromList = (List) fromObj;
117 for (int i = 0; i < fromList.size(); i++) {
118 toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass);
120 props.setProperty(pfx + "_length", Integer.toString(fromList.size()));
122 } else if (isYangGenerated(fromClass)) {
123 // Class is yang generated.
124 LOG.trace(fromClass.getName() + " is a Yang-generated class");
126 String propNamePfx = null;
128 // If called from a list (so prefix ends in ']'), don't
129 // add class name again
130 if (pfx.endsWith("]")) {
133 if ((pfx != null) && (pfx.length() > 0)) {
136 propNamePfx = toLowerHyphen(fromClass.getSimpleName());
139 if (propNamePfx.endsWith("-builder")) {
140 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length());
143 if (propNamePfx.endsWith("-impl")) {
144 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
148 // Iterate through getter methods to figure out values we need to
152 String lastGetterName = null;
153 String propVal = null;
155 for (Method m : fromClass.getMethods()) {
159 lastGetterName = m.getName();
161 Class returnType = m.getReturnType();
163 if (m.getName().startsWith("get")) {
164 fieldName = toLowerHyphen(m.getName().substring(3));
167 fieldName = toLowerHyphen(m.getName().substring(2));
170 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
172 // Is the return type a yang generated class?
173 if (isYangGenerated(returnType)) {
175 if (returnType.isEnum()) {
176 // Return type is a typedef. Save its value.
178 boolean isAccessible = m.isAccessible();
180 m.setAccessible(true);
183 Object retValue = m.invoke(fromObj);
186 m.setAccessible(isAccessible);
188 if (retValue != null) {
189 String propName = propNamePfx + "." + fieldName;
190 propVal = retValue.toString();
191 props.setProperty(propName, mapEnumeratedValue(fieldName, propVal));
193 } catch (Exception e) {
194 LOG.error("Caught exception trying to convert Yang-generated enum returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
196 } else if (isIpv4Address(returnType)) {
199 String propName = propNamePfx + "." + fieldName;
200 boolean isAccessible = m.isAccessible();
202 m.setAccessible(true);
204 Ipv4Address retValue = (Ipv4Address) m.invoke(fromObj);
206 m.setAccessible(isAccessible);
209 if (retValue != null) {
210 propVal = retValue.getValue().toString();
211 LOG.debug("Setting property " + propName + " to " + propVal);
212 props.setProperty(propName, propVal);
215 } catch (Exception e) {
216 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
218 } else if (isIpv6Address(returnType)) {
221 String propName = propNamePfx + "." + fieldName;
222 boolean isAccessible = m.isAccessible();
224 m.setAccessible(true);
226 Ipv6Address retValue = (Ipv6Address) m.invoke(fromObj);
228 m.setAccessible(isAccessible);
231 if (retValue != null) {
232 propVal = retValue.getValue().toString();
233 LOG.debug("Setting property " + propName + " to " + propVal);
234 props.setProperty(propName, propVal);
237 } catch (Exception e) {
238 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
240 } else if (isIpAddress(returnType)) {
243 String propName = propNamePfx + "." + fieldName;
244 boolean isAccessible = m.isAccessible();
246 m.setAccessible(true);
248 IpAddress retValue = (IpAddress) m.invoke(fromObj);
250 m.setAccessible(isAccessible);
253 if (retValue != null) {
254 propVal = new String(retValue.getValue());
255 LOG.debug("Setting property " + propName + " to " + propVal);
256 props.setProperty(propName, propVal);
259 } catch (Exception e) {
260 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
262 } else if (isIpPrefix(returnType)) {
265 String propName = propNamePfx + "." + fieldName;
266 boolean isAccessible = m.isAccessible();
268 m.setAccessible(true);
270 IpPrefix retValue = (IpPrefix) m.invoke(fromObj);
272 m.setAccessible(isAccessible);
275 if (retValue != null) {
276 propVal = new String(retValue.getValue());
277 LOG.debug("Setting property " + propName + " to " + propVal);
278 props.setProperty(propName, propVal);
281 } catch (Exception e) {
282 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
286 boolean isAccessible = m.isAccessible();
288 m.setAccessible(true);
290 Object retValue = m.invoke(fromObj);
292 if (retValue instanceof byte[]) {
293 LOG.trace(m.getName() + " returns a byte[]");
294 retValue = new String((byte[]) retValue, "UTF-8");
295 LOG.trace("Converted byte array " + propNamePfx + "." + fieldName + "to string " + retValue);
298 m.setAccessible(isAccessible);
300 if (retValue != null) {
301 toProperties(props, propNamePfx + "." + fieldName, retValue, returnType);
303 } catch (Exception e) {
305 if (m.getName().equals("getKey")) {
306 LOG.trace("Caught " + e.getClass().getName() + " exception trying to convert results from getKey() - ignoring");
308 LOG.error("Caught exception trying to convert Yang-generated class returned by" + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
312 } else if (returnType.equals(Class.class)) {
314 LOG.trace(m.getName() + " returns a Class object - not interested");
316 } else if (List.class.isAssignableFrom(returnType)) {
318 // This getter method returns a list.
320 boolean isAccessible = m.isAccessible();
322 m.setAccessible(true);
324 Object retList = m.invoke(fromObj);
326 m.setAccessible(isAccessible);
328 // Figure out what type of elements are stored in
330 Type paramType = m.getGenericReturnType();
331 Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
332 toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType);
333 } catch (Exception e) {
334 LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
339 // Method returns something that is not a List and not
343 String propName = propNamePfx + "." + fieldName;
344 boolean isAccessible = m.isAccessible();
346 m.setAccessible(true);
348 Object propValObj = m.invoke(fromObj);
350 m.setAccessible(isAccessible);
353 if (propValObj != null) {
354 if (propValObj instanceof byte[]) {
355 LOG.trace(m.getName() + " returns a byte[]");
356 propVal = new String((byte[]) propValObj, "UTF-8");
357 LOG.trace("Converted byte array " + propNamePfx + "." + fieldName + "to string " + propVal);
360 propVal = propValObj.toString();
362 LOG.debug("Setting property " + propName + " to " + propVal);
363 props.setProperty(propName, propVal);
366 } catch (Exception e) {
367 if (m.getName().equals("getKey")) {
368 LOG.trace("Caught " + e.getClass().getName() + " exception trying to convert results from getKey() - ignoring");
370 LOG.error("Caught exception trying to convert value returned by" + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
378 // End of method loop. If there was only one getter, named
380 // set value identified by "prefix" to that one value.
381 if ((numGetters == 1) && ("getValue".equals(lastGetterName))) {
382 LOG.trace("getValueFIX : " + propNamePfx + " only has getValue() getter - setting " + propNamePfx + " = " + propVal);
383 props.setProperty(propNamePfx, propVal);
385 LOG.trace("getValueFIX : " + propNamePfx + " has " + numGetters + " getter(s), last one found was " + lastGetterName);
390 // Class is not yang generated and not a list
391 // It must be an element of a leaf list - set "prefix" to value
392 String fromVal = null;
393 if (fromObj instanceof byte[]) {
395 fromVal = new String((byte[]) fromObj, "UTF-8");
396 LOG.trace("Converted byte array " + pfx + "to string " + fromVal);
397 } catch (Exception e) {
398 LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e);
399 fromVal = fromObj.toString();
403 fromVal = fromObj.toString();
405 LOG.debug("Setting property " + pfx + " to " + fromVal);
406 props.setProperty(pfx, fromVal);
412 public static Object toBuilder(Properties props, Object toObj) {
414 return (toBuilder(props, "", toObj));
417 public static List toList(Properties props, String pfx, List toObj, Class elemType) {
420 boolean foundValue = false;
422 LOG.trace("Saving properties to List<" + elemType.getName() + "> from " + pfx);
424 if (props.contains(pfx + "_length")) {
426 int listLength = Integer.parseInt(props.getProperty(pfx + "_length"));
428 if (listLength > 0) {
429 maxIdx = listLength - 1;
431 } catch (Exception e) {
437 // Figure out array size
438 for (Object pNameObj : props.keySet()) {
439 String key = (String) pNameObj;
441 if (key.startsWith(pfx + "[")) {
442 String idxStr = key.substring(pfx.length() + 1);
443 int endloc = idxStr.indexOf("]");
445 idxStr = idxStr.substring(0, endloc);
449 int curIdx = Integer.parseInt(idxStr);
450 if (curIdx > maxIdx) {
453 } catch (Exception e) {
454 LOG.error("Illegal subscript in property " + key);
461 LOG.trace(pfx + " has max index of " + maxIdx);
462 for (int i = 0; i <= maxIdx; i++) {
464 String curBase = pfx + "[" + i + "]";
466 if (isYangGenerated(elemType)) {
467 String builderName = elemType.getName() + "Builder";
469 Class builderClass = Class.forName(builderName);
470 Object builderObj = builderClass.newInstance();
471 Method buildMethod = builderClass.getMethod("build");
472 builderObj = toBuilder(props, curBase, builderObj, true);
473 if (builderObj != null) {
474 LOG.trace("Calling " + builderObj.getClass().getName() + "." + buildMethod.getName() + "()");
475 Object builtObj = buildMethod.invoke(builderObj);
480 } catch (ClassNotFoundException e) {
481 LOG.warn("Could not find builder class " + builderName, e);
482 } catch (Exception e) {
483 LOG.error("Caught exception trying to populate list from " + pfx);
486 // Must be a leaf list
487 String curValue = props.getProperty(curBase, "");
491 if ((curValue != null) && (curValue.length() > 0)) {
506 public static Object toBuilder(Properties props, String pfx, Object toObj) {
507 return (toBuilder(props, pfx, toObj, false));
510 public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) {
511 Class toClass = toObj.getClass();
512 boolean foundValue = false;
514 LOG.trace("Saving properties to " + toClass.getName() + " class from " + pfx);
518 if (isYangGenerated(toClass)) {
519 // Class is yang generated.
520 LOG.trace(toClass.getName() + " is a Yang-generated class");
522 String propNamePfx = null;
527 if ((pfx != null) && (pfx.length() > 0)) {
528 propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
530 propNamePfx = toLowerHyphen(toClass.getSimpleName());
533 if (propNamePfx.endsWith("-builder")) {
534 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length());
537 if (propNamePfx.endsWith("-impl")) {
538 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
542 if (toObj instanceof Identifier) {
543 LOG.trace(toClass.getName() + " is a Key - skipping");
547 // Iterate through getter methods to figure out values we need to
550 for (Method m : toClass.getMethods()) {
552 Class paramTypes[] = m.getParameterTypes();
553 Class paramClass = paramTypes[0];
555 String fieldName = toLowerHyphen(m.getName().substring(3));
556 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
558 String propName = propNamePfx + "." + fieldName;
560 String paramValue = props.getProperty(propName);
561 if (paramValue == null) {
562 LOG.trace(propName + " is unset");
564 LOG.trace(propName + " = " + paramValue);
567 // Is the return type a yang generated class?
568 if (isYangGenerated(paramClass)) {
570 if (paramClass.isEnum()) {
572 LOG.trace(m.getName() + " expects an Enum");
573 // Param type is a typedef.
574 if ((paramValue != null) && (paramValue.length() > 0)) {
575 Object paramObj = null;
578 paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue));
579 } catch (Exception e) {
580 LOG.error("Caught exception trying to convert field " + propName + " to enum " + paramClass.getName(), e);
584 boolean isAccessible = m.isAccessible();
586 m.setAccessible(true);
589 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
590 m.invoke(toObj, paramObj);
593 m.setAccessible(isAccessible);
597 } catch (Exception e) {
598 LOG.error("Caught exception trying to create Yang-generated enum expected by" + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
603 String simpleName = paramClass.getSimpleName();
605 if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName)) {
607 if ((paramValue != null) && (paramValue.length() > 0)) {
609 IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue);
611 if ("Ipv4Address".equals(simpleName)) {
612 m.invoke(toObj, ipAddr.getIpv4Address());
613 } else if ("Ipv6Address".equals(simpleName)) {
614 m.invoke(toObj, ipAddr.getIpv6Address());
617 m.invoke(toObj, ipAddr);
620 } catch (Exception e) {
621 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + "(" + paramValue + ")", e);
626 boolean isAccessible = m.isAccessible();
628 m.setAccessible(true);
630 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
631 m.invoke(toObj, paramValue);
633 m.setAccessible(isAccessible);
637 } catch (Exception e) {
638 LOG.error("Caught exception trying to call " + toClass.getName() + "." + m.getName() + "() with Properties entry", e);
641 } else if ("IpPrefix".equals(simpleName)) {
642 if ((paramValue != null) && (paramValue.length() > 0)) {
644 IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue);
645 m.invoke(toObj, ipPrefix);
647 } catch (Exception e) {
648 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + "(" + paramValue + ")", e);
652 // setter expects a yang-generated class. Need
654 // create a builder to set it.
656 String builderName = paramClass.getName() + "Builder";
657 Class builderClass = null;
658 Object builderObj = null;
659 Object paramObj = null;
661 Object constObj = null;
663 LOG.trace(m.getName() + " expects a yang-generated class - looking for builder " + builderName);
665 builderClass = Class.forName(builderName);
666 builderObj = builderClass.newInstance();
667 paramObj = toBuilder(props, propNamePfx, builderObj);
668 } catch (ClassNotFoundException e) {
670 if (paramValue == null) {
672 boolean isAccessible = m.isAccessible();
674 m.setAccessible(true);
676 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(null)");
677 m.invoke(toObj, new Object[] { null });
679 m.setAccessible(isAccessible);
683 } catch (Exception e1) {
684 LOG.error("Caught exception trying to cally" + toClass.getName() + "." + m.getName() + "() with Properties entry", e1);
688 // See if I can find a constructor I
691 Constructor[] constructors = paramClass.getConstructors();
692 // Is there a String constructor?
693 for (Constructor c : constructors) {
694 Class[] cParms = c.getParameterTypes();
695 if ((cParms != null) && (cParms.length == 1)) {
696 if (String.class.isAssignableFrom(cParms[0])) {
697 constObj = c.newInstance(paramValue);
702 if (constObj == null) {
703 // Is there a Long constructor?
704 for (Constructor c : constructors) {
705 Class[] cParms = c.getParameterTypes();
706 if ((cParms != null) && (cParms.length == 1)) {
707 if (Long.class.isAssignableFrom(cParms[0])) {
708 constObj = c.newInstance(Long.parseLong(paramValue));
715 if (constObj == null) {
717 // Last chance - see if
718 // parameter class has a static
720 // getDefaultInstance(String)
722 Method gm = paramClass.getMethod("getDefaultInstance", String.class);
724 int gmodifier = gm.getModifiers();
725 if (Modifier.isStatic(gmodifier)) {
727 // getDefaultInstance(String)
728 paramObj = gm.invoke(null, paramValue);
731 } catch (Exception gme) {
736 } catch (Exception e1) {
737 LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
740 if (constObj == null) {
741 LOG.warn("Could not find builder class " + builderName + " and could not find a String or Long constructor or static getDefaultInstance(String) - trying just to set passing paramValue");
745 } catch (Exception e) {
746 LOG.error("Caught exception trying to create builder " + builderName, e);
749 if (paramObj != null) {
753 Method buildMethod = builderClass.getMethod("build");
754 LOG.trace("Calling " + paramObj.getClass().getName() + "." + buildMethod.getName() + "()");
755 Object builtObj = buildMethod.invoke(paramObj);
757 boolean isAccessible = m.isAccessible();
759 m.setAccessible(true);
762 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "()");
763 m.invoke(toObj, builtObj);
765 m.setAccessible(isAccessible);
769 } catch (Exception e) {
770 LOG.error("Caught exception trying to set Yang-generated class expected by" + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
774 boolean isAccessible = m.isAccessible();
776 m.setAccessible(true);
779 if (constObj != null) {
781 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + constObj.toString() + ")");
782 m.invoke(toObj, constObj);
784 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
785 m.invoke(toObj, paramValue);
789 m.setAccessible(isAccessible);
793 } catch (Exception e) {
794 LOG.error("Caught exception trying to convert value returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
801 // Setter's argument is not a yang-generated class. See
804 if (List.class.isAssignableFrom(paramClass)) {
806 LOG.trace("Parameter class " + paramClass.getName() + " is a List");
808 // Figure out what type of args are in List and pass
811 Type paramType = m.getGenericParameterTypes()[0];
812 Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
813 Object paramObj = new LinkedList();
815 paramObj = toList(props, propName, (List) paramObj, (Class) elementType);
816 } catch (Exception e) {
817 LOG.error("Caught exception trying to create list expected as argument to " + toClass.getName() + "." + m.getName());
820 if (paramObj != null) {
822 boolean isAccessible = m.isAccessible();
824 m.setAccessible(true);
826 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
827 m.invoke(toObj, paramObj);
829 m.setAccessible(isAccessible);
833 } catch (Exception e) {
834 LOG.error("Caught exception trying to convert List returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
839 // Setter expects something that is not a List and
840 // not yang-generated. Just pass the parameter value
842 LOG.trace("Parameter class " + paramClass.getName() + " is not a yang-generated class or a List");
844 if ((paramValue != null) && (paramValue.length() > 0)) {
846 Object constObj = null;
849 // See if I can find a constructor I can use
850 Constructor[] constructors = paramClass.getConstructors();
851 // Is there a String constructor?
852 for (Constructor c : constructors) {
853 Class[] cParms = c.getParameterTypes();
854 if ((cParms != null) && (cParms.length == 1)) {
855 if (String.class.isAssignableFrom(cParms[0])) {
856 constObj = c.newInstance(paramValue);
861 if (constObj == null) {
862 // Is there a Long constructor?
863 for (Constructor c : constructors) {
864 Class[] cParms = c.getParameterTypes();
865 if ((cParms != null) && (cParms.length == 1)) {
866 if (Long.class.isAssignableFrom(cParms[0])) {
867 constObj = c.newInstance(Long.parseLong(paramValue));
874 if (constObj != null) {
876 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + constObj + ")");
877 m.invoke(toObj, constObj);
879 } catch (Exception e2) {
880 LOG.error("Caught exception trying to call " + m.getName(), e2);
884 boolean isAccessible = m.isAccessible();
886 m.setAccessible(true);
888 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
889 m.invoke(toObj, paramValue);
891 m.setAccessible(isAccessible);
895 } catch (Exception e) {
896 LOG.error("Caught exception trying to convert value returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
899 } catch (Exception e1) {
900 LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
906 } // End of section handling "setter" method
907 } // End of loop through Methods
908 } // End of section handling yang-generated class
917 public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) {
918 boolean foundValue = false;
920 LOG.trace("Analyzing " + toClass.getName() + " class : pfx " + pfx);
922 if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) {
923 // Class is yang generated.
924 LOG.trace(toClass.getName() + " is a Yang-generated class");
926 if (toClass.getName().endsWith("Key")) {
927 if (Identifier.class.isAssignableFrom(toClass)) {
928 LOG.trace(Identifier.class.getName() + " is assignable from " + toClass.getName());
931 LOG.trace(Identifier.class.getName() + " is NOT assignable from " + toClass.getName());
935 String propNamePfx = null;
936 if (pfx.endsWith("]")) {
940 if ((pfx != null) && (pfx.length() > 0)) {
941 propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
943 propNamePfx = toLowerHyphen(toClass.getSimpleName());
946 if (propNamePfx.endsWith("-builder")) {
947 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length());
950 if (propNamePfx.endsWith("-impl")) {
951 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
955 // Iterate through getter methods to figure out values we need to
958 for (Method m : toClass.getMethods()) {
959 LOG.trace("Is " + m.getName() + " method a getter?");
961 LOG.trace(m.getName() + " is a getter");
962 Class returnClass = m.getReturnType();
964 String fieldName = toLowerHyphen(m.getName().substring(3));
965 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
967 String propName = propNamePfx + "." + fieldName;
969 // Is the return type a yang generated class?
970 if (isYangGenerated(returnClass)) {
972 if (returnClass.isEnum()) {
974 LOG.trace(m.getName() + " is an Enum");
975 pstr.print("\n\n * " + propName);
979 String simpleName = returnClass.getSimpleName();
981 if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName) || "IpPrefix".equals(simpleName)) {
982 LOG.trace(m.getName() + " is an " + simpleName);
983 pstr.print("\n\n * " + propName);
985 printPropertyList(pstr, propNamePfx, returnClass);
991 // Setter's argument is not a yang-generated class. See
994 if (List.class.isAssignableFrom(returnClass)) {
996 LOG.trace("Parameter class " + returnClass.getName() + " is a List");
998 // Figure out what type of args are in List and pass
1001 Type returnType = m.getGenericReturnType();
1002 Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
1003 Class elementClass = (Class) elementType;
1004 LOG.trace("Calling printPropertyList on list type (" + elementClass.getName() + "), pfx is (" + pfx + "), toClass is (" + toClass.getName() + ")");
1005 printPropertyList(pstr, propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]", elementClass);
1007 } else if (!returnClass.equals(Class.class)) {
1009 // Setter expects something that is not a List and
1010 // not yang-generated. Just pass the parameter value
1012 LOG.trace("Parameter class " + returnClass.getName() + " is not a yang-generated class or a List");
1014 pstr.print("\n\n * " + propName);
1018 } // End of section handling "setter" method
1019 } // End of loop through Methods
1020 } // End of section handling yang-generated class
1024 public static boolean isYangGenerated(Class c) {
1028 return (c.getName().startsWith("org.opendaylight.yang.gen."));
1032 public static boolean isIpPrefix(Class c) {
1037 String simpleName = c.getSimpleName();
1038 return ("IpPrefix".equals(simpleName));
1041 public static boolean isIpv4Address(Class c) {
1046 String simpleName = c.getSimpleName();
1047 return ("Ipv4Address".equals(simpleName));
1050 public static boolean isIpv6Address(Class c) {
1055 String simpleName = c.getSimpleName();
1056 return ("Ipv6Address".equals(simpleName));
1059 public static boolean isIpAddress(Class c) {
1064 String simpleName = c.getSimpleName();
1065 return ("IpAddress".equals(simpleName));
1068 public static String toLowerHyphen(String inStr) {
1069 if (inStr == null) {
1073 String str = inStr.substring(0, 1).toLowerCase();
1074 if (inStr.length() > 1) {
1075 str = str + inStr.substring(1);
1078 String regex = "(([a-z0-9])([A-Z]))";
1079 String replacement = "$2-$3";
1081 String retval = str.replaceAll(regex, replacement).toLowerCase();
1083 LOG.trace("Converting " + inStr + " => " + str + " => " + retval);
1087 //This is called when mapping the yang value back to a valid java enumeration
1088 public static String toJavaEnum(String inStr) {
1089 if (inStr == null) {
1091 } else if (inStr.length() == 0) {
1095 //This will strip out all periods, which cannot be in a java enum
1096 inStr = inStr.replaceAll("\\.", "");
1098 String[] terms = inStr.split("-");
1099 StringBuffer sbuff = new StringBuffer();
1101 //appends an _ if the string starts with a digit to make it a valid java enum
1102 if (Character.isDigit(inStr.charAt(0))) {
1105 //If the string contains hyphens it will convert the string to upperCamelCase without hyphens
1106 for (String term : terms) {
1107 sbuff.append(term.substring(0, 1).toUpperCase());
1108 if (term.length() > 1) {
1109 sbuff.append(term.substring(1));
1112 return (sbuff.toString());
1116 public static boolean isGetter(Method m) {
1121 if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) {
1122 if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) {
1123 if (!"getClass".equals(m.getName())) {
1128 if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) {
1132 if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) {
1140 public static boolean isSetter(Method m) {
1145 if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) {
1146 if (m.getName().matches("^set[A-Z].*")) {
1147 Class[] paramTypes = m.getParameterTypes();
1148 if (paramTypes[0].isAssignableFrom(Identifier.class) || Identifier.class.isAssignableFrom(paramTypes[0])) {
1160 public static String getFullPropertiesPath(String propertiesFileName) {
1161 return "/opt/bvc/controller/configuration/" + propertiesFileName;
1164 //This is called when mapping a valid java enumeration back to the yang model value
1165 public static String mapEnumeratedValue(String propertyName, String propertyValue) {
1166 LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue);
1167 String mappingKey = "yang." + propertyName + "." + propertyValue;
1168 if (yangMappingProperties.containsKey(mappingKey)) {
1169 return (yangMappingProperties.getProperty(mappingKey));
1171 LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value.");
1172 return propertyValue;