2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Modifications Copyright (C) 2018 IBM.
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.ccsdk.sli.core.sli.provider;
27 import java.io.FileInputStream;
28 import java.io.InputStream;
29 import java.io.PrintStream;
30 import java.lang.reflect.Constructor;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.Modifier;
33 import java.lang.reflect.ParameterizedType;
34 import java.lang.reflect.Type;
35 import java.util.LinkedList;
36 import java.util.List;
37 import java.util.Properties;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisherBuilder;
48 import org.opendaylight.yangtools.yang.binding.Identifier;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class MdsalHelper {
54 private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class);
55 private static Properties yangMappingProperties = new Properties();
56 private static final String IP_ADDRESS="IpAddress";
57 private static final String IPV4_ADDRESS="Ipv4Address";
58 private static final String IPV6_ADDRESS="Ipv6Address";
60 private static final String IP_PREFIX="IpPrefix";
61 private static final String SETTING_PROPERTY="Setting property ";
62 private static final String BUILDER="-builder";
65 public static void setProperties(Properties input) {
66 setYangMappingProperties(input);
70 public static void setYangMappingProperties(Properties properties) {
71 for (Object propNameObj : properties.keySet()) {
72 String propName = (String) propNameObj;
73 MdsalHelper.yangMappingProperties.setProperty(propName, properties.getProperty(propName));
78 public static void loadProperties(String propertiesFile) {
79 File file = new File(propertiesFile);
80 Properties properties = new Properties();
81 if (file.isFile() && file.canRead()) {
82 try (InputStream input = new FileInputStream(file)) {
83 properties.load(input);
84 MdsalHelper.setYangMappingProperties(properties);
85 LOG.info("Loaded properties from " + propertiesFile);
86 } catch (Exception e) {
87 LOG.error("Failed to load properties " + propertiesFile + "\n", e);
90 LOG.error("Failed to load the properties file " + propertiesFile + "\n");
91 LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n");
95 public static Properties toProperties(Properties props, Object fromObj) {
96 return toProperties(props, fromObj, false);
99 public static Properties toProperties(Properties props, Object fromObj, Boolean useLegacyEnumerationMapping) {
100 Class fromClass = null;
102 if (fromObj != null) {
103 fromClass = fromObj.getClass();
105 return toProperties(props, "", fromObj, fromClass, useLegacyEnumerationMapping);
108 public static Properties toProperties(Properties props, String pfx, Object fromObj) {
109 return toProperties(props, pfx, fromObj, false);
112 public static Properties toProperties(Properties props, String pfx, Object fromObj, Boolean useLegacyEnumerationMapping) {
113 Class fromClass = null;
115 if (fromObj != null) {
116 fromClass = fromObj.getClass();
119 return toProperties(props, pfx, fromObj, fromClass, useLegacyEnumerationMapping);
122 public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) {
123 return toProperties(props, pfx, fromObj, fromClass, false);
126 public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass, Boolean useLegacyEnumerationMapping) {
128 if (fromObj == null) {
131 String simpleTypeName = fromObj.getClass().getTypeName();
132 simpleTypeName = simpleTypeName.substring(simpleTypeName.lastIndexOf(".") + 1);
134 if (classHasSpecialHandling(simpleTypeName)) {
137 Method m = fromClass.getMethod(getStringValueMethod(simpleTypeName), null);
138 boolean isAccessible = m.isAccessible();
140 m.setAccessible(true);
142 Object retValue = m.invoke(fromObj);
143 if (retValue != null) {
144 String propVal = null;
145 if (IP_ADDRESS.equals(simpleTypeName) || IP_PREFIX.equals(simpleTypeName)
146 || IPV4_ADDRESS.equals(simpleTypeName) || IPV6_ADDRESS.equals(simpleTypeName)) {
147 propVal = (String) retValue;
148 } else if ("Dscp".equals(simpleTypeName)) {
149 propVal = String.valueOf((short) retValue);
150 } else if ("PortNumber".equals(simpleTypeName)) {
151 propVal = String.valueOf((Integer) retValue);
153 LOG.debug(SETTING_PROPERTY + pfx + " to " + propVal);
154 props.setProperty(pfx, propVal);
156 } catch (Exception e) {
157 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName()
158 + ".getValue() to Properties entry", e);
160 } else if (fromObj instanceof List) {
161 List fromList = (List) fromObj;
163 for (int i = 0; i < fromList.size(); i++) {
164 toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass, useLegacyEnumerationMapping);
166 props.setProperty(pfx + "_length", Integer.toString(fromList.size()));
168 } else if (isYangGenerated(fromClass)) {
169 // Class is yang generated.
171 String propNamePfx = null;
173 // If called from a list (so prefix ends in ']'), don't
174 // add class name again
175 if (pfx.endsWith("]")) {
178 if ((pfx != null) && (pfx.length() > 0)) {
181 propNamePfx = toLowerHyphen(fromClass.getSimpleName());
184 if (propNamePfx.endsWith(BUILDER)) {
185 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
188 if (propNamePfx.endsWith("-impl")) {
189 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
193 // Iterate through getter methods to figure out values we need to
197 String lastGetterName = null;
198 String propVal = null;
200 for (Method m : fromClass.getMethods()) {
204 lastGetterName = m.getName();
206 Class returnType = m.getReturnType();
208 if (m.getName().startsWith("get")) {
209 fieldName = toLowerHyphen(m.getName().substring(3));
212 fieldName = toLowerHyphen(m.getName().substring(2));
215 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
217 // Is the return type a yang generated class?
218 if (isYangGenerated(returnType)) {
220 if (returnType.isEnum()) {
221 // Return type is a typedef. Save its value.
223 boolean isAccessible = m.isAccessible();
225 m.setAccessible(true);
228 Object retValue = m.invoke(fromObj);
231 m.setAccessible(isAccessible);
233 if (retValue != null) {
234 String propName = propNamePfx + "." + fieldName;
235 if (useLegacyEnumerationMapping) {
236 propVal = retValue.toString();
237 props.setProperty(propName, mapEnumeratedValue(fieldName, propVal));
239 Method method = retValue.getClass().getMethod("getName");
240 String yangValue = (String) method.invoke(retValue);
241 props.setProperty(propName, yangValue);
245 } catch (Exception e) {
247 "Caught exception trying to convert Yang-generated enum returned by "
248 + fromClass.getName() + "." + m.getName() + "() to Properties entry",
253 boolean isAccessible = m.isAccessible();
255 m.setAccessible(true);
257 Object retValue = m.invoke(fromObj);
259 if (retValue instanceof byte[]) {
260 retValue = new String((byte[]) retValue, "UTF-8");
263 m.setAccessible(isAccessible);
265 if (retValue != null) {
266 toProperties(props, propNamePfx + "." + fieldName, retValue, returnType, useLegacyEnumerationMapping);
268 } catch (Exception e) {
270 if (m.getName().equals("getKey")) {
271 LOG.trace("Caught " + e.getClass().getName()
272 + " exception trying to convert results from getKey() - ignoring");
274 LOG.error("Caught exception trying to convert Yang-generated class returned by"
275 + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
279 } else if (returnType.equals(Class.class)) {
281 } else if (List.class.isAssignableFrom(returnType)) {
283 // This getter method returns a list.
285 boolean isAccessible = m.isAccessible();
287 m.setAccessible(true);
289 Object retList = m.invoke(fromObj);
291 m.setAccessible(isAccessible);
293 // Figure out what type of elements are stored in
295 Type paramType = m.getGenericReturnType();
296 Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
297 toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType, useLegacyEnumerationMapping);
298 } catch (Exception e) {
299 LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "."
300 + m.getName() + "() to Properties entry", e);
305 // Method returns something that is not a List and not
309 String propName = propNamePfx + "." + fieldName;
310 boolean isAccessible = m.isAccessible();
312 m.setAccessible(true);
314 Object propValObj = m.invoke(fromObj);
316 m.setAccessible(isAccessible);
319 if (propValObj != null) {
320 if (propValObj instanceof byte[]) {
321 propVal = new String((byte[]) propValObj, "UTF-8");
323 propVal = propValObj.toString();
325 LOG.debug(SETTING_PROPERTY + propName + " to " + propVal);
326 props.setProperty(propName, propVal);
329 } catch (Exception e) {
330 if (m.getName().equals("getKey")) {
331 LOG.trace("Caught " + e.getClass().getName()
332 + " exception trying to convert results from getKey() - ignoring");
334 LOG.error("Caught exception trying to convert value returned by" + fromClass.getName()
335 + "." + m.getName() + "() to Properties entry", e);
343 // End of method loop. If there was only one getter, named
345 // set value identified by "prefix" to that one value.
346 if ((numGetters == 1) && ("getValue".equals(lastGetterName))) {
347 props.setProperty(propNamePfx, propVal);
350 // Class is not yang generated and not a list
351 // It must be an element of a leaf list - set "prefix" to value
352 String fromVal = null;
353 if (fromObj instanceof byte[]) {
355 fromVal = new String((byte[]) fromObj, "UTF-8");
356 } catch (Exception e) {
357 LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e);
358 fromVal = fromObj.toString();
362 fromVal = fromObj.toString();
364 LOG.debug(SETTING_PROPERTY + pfx + " to " + fromVal);
365 props.setProperty(pfx, fromVal);
371 public static Object toBuilder(Properties props, Object toObj) {
373 return (toBuilder(props, "", toObj));
376 public static List toList(Properties props, String pfx, List toObj, Class elemType) {
379 boolean foundValue = false;
381 if (props.containsKey(pfx + "_length")) {
383 int listLength = Integer.parseInt(props.getProperty(pfx + "_length"));
385 if (listLength > 0) {
386 maxIdx = listLength - 1;
388 } catch (NumberFormatException e) {
389 LOG.info("Invalid input for length ", e);
393 String arrayKey = pfx + "[";
394 int arrayKeyLength = arrayKey.length();
396 // Figure out array size
397 for (Object pNameObj : props.keySet()) {
398 String key = (String) pNameObj;
400 if (key.startsWith(arrayKey)) {
401 String idxStr = key.substring(arrayKeyLength);
402 int endloc = idxStr.indexOf("]");
404 idxStr = idxStr.substring(0, endloc);
407 int curIdx = Integer.parseInt(idxStr);
408 if (curIdx > maxIdx) {
411 } catch (Exception e) {
412 LOG.error("Illegal subscript in property {}", key, e);
419 for (int i = 0; i <= maxIdx; i++) {
421 String curBase = pfx + "[" + i + "]";
423 if (isYangGenerated(elemType)) {
425 if (isIpAddress(elemType)) {
427 String curValue = props.getProperty(curBase, "");
429 if ((curValue != null) && (curValue.length() > 0)) {
430 toObj.add(IpAddressBuilder.getDefaultInstance(curValue));
433 } else if (isIpv4Address(elemType)) {
434 String curValue = props.getProperty(curBase, "");
436 if ((curValue != null) && (curValue.length() > 0)) {
437 toObj.add(new Ipv4Address(curValue));
441 } else if (isIpv6Address(elemType)) {
442 String curValue = props.getProperty(curBase, "");
444 if ((curValue != null) && (curValue.length() > 0)) {
445 toObj.add(new Ipv6Address(curValue));
448 } else if (isIpPrefix(elemType)) {
450 String curValue = props.getProperty(curBase, "");
452 if ((curValue != null) && (curValue.length() > 0)) {
453 toObj.add(IpPrefixBuilder.getDefaultInstance(curValue));
456 } else if (isPortNumber(elemType)) {
458 String curValue = props.getProperty(curBase, "");
460 if ((curValue != null) && (curValue.length() > 0)) {
461 toObj.add(PortNumber.getDefaultInstance(curValue));
464 } else if (isDscp(elemType)) {
466 String curValue = props.getProperty(curBase, "");
468 if ((curValue != null) && (curValue.length() > 0)) {
469 toObj.add(Dscp.getDefaultInstance(curValue));
473 String builderName = elemType.getName() + "Builder";
475 Class builderClass = Class.forName(builderName);
476 Object builderObj = builderClass.newInstance();
477 Method buildMethod = builderClass.getMethod("build");
478 builderObj = toBuilder(props, curBase, builderObj, true);
479 if (builderObj != null) {
480 Object builtObj = buildMethod.invoke(builderObj);
485 } catch (ClassNotFoundException e) {
486 LOG.warn("Could not find builder class {}", builderName, e);
487 } catch (Exception e) {
488 LOG.error("Caught exception trying to populate list from {}", pfx, e);
492 // Must be a leaf list
493 String curValue = props.getProperty(curBase, "");
497 if ((curValue != null) && (curValue.length() > 0)) {
512 public static Object toBuilder(Properties props, String pfx, Object toObj) {
513 return (toBuilder(props, pfx, toObj, false));
516 public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) {
518 Class toClass = toObj.getClass();
519 boolean foundValue = false;
523 if (isYangGenerated(toClass)) {
524 // Class is yang generated.
525 String propNamePfx = null;
530 if ((pfx != null) && (pfx.length() > 0)) {
531 propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
533 propNamePfx = toLowerHyphen(toClass.getSimpleName());
536 if (propNamePfx.endsWith(BUILDER)) {
537 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
540 if (propNamePfx.endsWith("-impl")) {
541 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
545 if (toObj instanceof Identifier) {
549 // Iterate through getter methods to figure out values we need to
552 for (Method m : toClass.getMethods()) {
554 Class paramTypes[] = m.getParameterTypes();
555 Class paramClass = paramTypes[0];
557 String fieldName = toLowerHyphen(m.getName().substring(3));
558 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
560 String propName = propNamePfx + "." + fieldName;
562 String paramValue = props.getProperty(propName);
563 if (paramValue == null) {
565 } else if ("".equals(paramValue)) {
566 LOG.trace(propName + " was set to the empty string, setting it to null");
572 // Is the return type a yang generated class?
573 if (isYangGenerated(paramClass)) {
575 if (paramClass.isEnum()) {
577 // Param type is a typedef.
578 if ((paramValue != null) && (paramValue.length() > 0)) {
579 Object paramObj = null;
582 paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue));
583 } catch (Exception e) {
584 LOG.error("Caught exception trying to convert field " + propName + " to enum "
585 + paramClass.getName(), e);
589 boolean isAccessible = m.isAccessible();
591 m.setAccessible(true);
594 m.invoke(toObj, paramObj);
597 m.setAccessible(isAccessible);
601 } catch (Exception e) {
602 LOG.error("Caught exception trying to create Yang-generated enum expected by"
603 + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
608 String simpleName = paramClass.getSimpleName();
610 if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
611 || IP_ADDRESS.equals(simpleName)) {
614 if ((paramValue != null) && (paramValue.length() > 0)) {
616 IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue);
618 if (IPV4_ADDRESS.equals(simpleName)) {
619 m.invoke(toObj, ipAddr.getIpv4Address());
620 } else if (IPV6_ADDRESS.equals(simpleName)) {
621 m.invoke(toObj, ipAddr.getIpv6Address());
624 m.invoke(toObj, ipAddr);
627 } catch (Exception e) {
628 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
629 + "(" + paramValue + ")", e);
634 boolean isAccessible = m.isAccessible();
636 m.setAccessible(true);
639 m.invoke(toObj, paramValue);
641 m.setAccessible(isAccessible);
645 } catch (Exception e) {
646 LOG.error("Caught exception trying to call " + toClass.getName() + "."
647 + m.getName() + "() with Properties entry", e);
650 } else if (IP_PREFIX.equals(simpleName)) {
651 if ((paramValue != null) && (paramValue.length() > 0)) {
653 IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue);
654 m.invoke(toObj, ipPrefix);
656 } catch (Exception e) {
657 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
658 + "(" + paramValue + ")", e);
661 } else if ("PortNumber".equals(simpleName)) {
662 if ((paramValue != null) && (paramValue.length() > 0)) {
664 PortNumber portNumber = PortNumber.getDefaultInstance(paramValue);
665 m.invoke(toObj, portNumber);
667 } catch (Exception e) {
668 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
669 + "(" + paramValue + ")", e);
672 } else if ("Dscp".equals(simpleName)) {
673 if ((paramValue != null) && (paramValue.length() > 0)) {
675 Dscp dscp = Dscp.getDefaultInstance(paramValue);
676 m.invoke(toObj, dscp);
678 } catch (Exception e) {
679 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
680 + "(" + paramValue + ")", e);
683 } else if ("RouteDistinguisher".equals(simpleName)) {
684 if ((paramValue != null) && (paramValue.length() > 0)) {
686 RouteDistinguisher routeDistinguisher = RouteDistinguisherBuilder.getDefaultInstance(paramValue);
687 m.invoke(toObj, routeDistinguisher);
689 } catch (Exception e) {
690 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
691 + "(" + paramValue + ")", e);
696 // setter expects a yang-generated class. Need
698 // create a builder to set it.
700 String builderName = paramClass.getName() + "Builder";
701 Class builderClass = null;
702 Object builderObj = null;
703 Object paramObj = null;
705 Object constObj = null;
708 builderClass = Class.forName(builderName);
709 builderObj = builderClass.newInstance();
710 paramObj = toBuilder(props, propNamePfx, builderObj);
711 } catch (ClassNotFoundException e) {
712 LOG.trace("Builder class {} not found catching ClassNotFoundException and trying other methods",
714 if (paramValue == null) {
716 boolean isAccessible = m.isAccessible();
718 m.setAccessible(true);
721 m.invoke(toObj, new Object[] { null });
723 m.setAccessible(isAccessible);
727 } catch (Exception e1) {
728 LOG.error("Caught exception trying to cally" + toClass.getName() + "."
729 + m.getName() + "() with Properties entry", e1);
733 // See if I can find a constructor I
736 Constructor[] constructors = paramClass.getConstructors();
737 // Is there a String constructor?
738 for (Constructor c : constructors) {
739 Class[] cParms = c.getParameterTypes();
740 if ((cParms != null) && (cParms.length == 1)) {
741 if (String.class.isAssignableFrom(cParms[0])) {
742 constObj = c.newInstance(paramValue);
747 if (constObj == null) {
748 // Is there a Long constructor?
749 for (Constructor c : constructors) {
750 Class[] cParms = c.getParameterTypes();
751 if ((cParms != null) && (cParms.length == 1)) {
752 if (Long.class.isAssignableFrom(cParms[0])) {
753 constObj = c.newInstance(Long.parseLong(paramValue));
760 if (constObj == null) {
762 // Last chance - see if
763 // parameter class has a static
765 // getDefaultInstance(String)
768 paramClass.getMethod("getDefaultInstance", String.class);
770 int gmodifier = gm.getModifiers();
771 if (Modifier.isStatic(gmodifier)) {
773 // getDefaultInstance(String)
774 paramObj = gm.invoke(null, paramValue);
777 } catch (Exception gme) {
778 LOG.info("Unable to find static method getDefaultInstance for "
779 + "class {}", paramClass.getSimpleName(), gme);
783 } catch (Exception e1) {
785 "Could not find a suitable constructor for " + paramClass.getName(),
789 if (constObj == null) {
790 LOG.warn("Could not find builder class " + builderName
791 + " and could not find a String or Long constructor or static "
792 + "getDefaultInstance(String) - trying just to set passing paramValue");
796 } catch (Exception e) {
797 LOG.error("Caught exception trying to create builder " + builderName, e);
800 if (paramObj != null && builderClass != null) {
803 Method buildMethod = builderClass.getMethod("build");
805 Object builtObj = buildMethod.invoke(paramObj);
807 boolean isAccessible = m.isAccessible();
809 m.setAccessible(true);
812 m.invoke(toObj, builtObj);
814 m.setAccessible(isAccessible);
818 } catch (Exception e) {
819 LOG.error("Caught exception trying to set Yang-generated class expected by"
820 + toClass.getName() + "." + m.getName() + "() from Properties entry",
825 boolean isAccessible = m.isAccessible();
827 m.setAccessible(true);
830 if (constObj != null) {
831 m.invoke(toObj, constObj);
833 m.invoke(toObj, paramValue);
836 m.setAccessible(isAccessible);
840 } catch (Exception e) {
841 LOG.error("Caught exception trying to convert value returned by"
842 + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
849 // Setter's argument is not a yang-generated class. See
852 if (List.class.isAssignableFrom(paramClass)) {
853 // Figure out what type of args are in List and pass
856 Type paramType = m.getGenericParameterTypes()[0];
857 Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
858 Object paramObj = new LinkedList();
860 paramObj = toList(props, propName, (List) paramObj, (Class) elementType);
861 } catch (Exception e) {
862 LOG.error("Caught exception trying to create list expected as argument to {}.{}",
863 toClass.getName(), m.getName(), e);
866 if (paramObj != null) {
868 boolean isAccessible = m.isAccessible();
870 m.setAccessible(true);
872 m.invoke(toObj, paramObj);
874 m.setAccessible(isAccessible);
878 } catch (Exception e) {
879 LOG.error("Caught exception trying to convert List returned by" + toClass.getName()
880 + "." + m.getName() + "() to Properties entry", e);
885 // Setter expects something that is not a List and
886 // not yang-generated. Just pass the parameter value
887 if ((paramValue != null) && (paramValue.length() > 0)) {
889 Object constObj = null;
892 // See if I can find a constructor I can use
893 Constructor[] constructors = paramClass.getConstructors();
894 // Is there a String constructor?
895 for (Constructor c : constructors) {
896 Class[] cParms = c.getParameterTypes();
897 if ((cParms != null) && (cParms.length == 1)) {
898 if (String.class.isAssignableFrom(cParms[0])) {
899 constObj = c.newInstance(paramValue);
904 if (constObj == null) {
905 // Is there a Long constructor?
906 for (Constructor c : constructors) {
907 Class[] cParms = c.getParameterTypes();
908 if ((cParms != null) && (cParms.length == 1)) {
909 if (Long.class.isAssignableFrom(cParms[0])) {
910 constObj = c.newInstance(Long.parseLong(paramValue));
917 if (constObj != null) {
919 m.invoke(toObj, constObj);
921 } catch (Exception e2) {
922 LOG.error("Caught exception trying to call " + m.getName(), e2);
926 boolean isAccessible = m.isAccessible();
928 m.setAccessible(true);
930 m.invoke(toObj, paramValue);
932 m.setAccessible(isAccessible);
936 } catch (Exception e) {
937 LOG.error("Caught exception trying to convert value returned by"
938 + toClass.getName() + "." + m.getName() + "() to Properties entry",
942 } catch (Exception e1) {
943 LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
949 } // End of section handling "setter" method
950 } // End of loop through Methods
951 } // End of section handling yang-generated class
960 private static boolean classHasSpecialHandling(String simpleName) {
961 if (IP_ADDRESS.equals(simpleName) || IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
962 || IP_PREFIX.equals(simpleName) || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) {
968 private static String getStringValueMethod(String simpleName){
969 if (IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)) {
970 return("stringValue");
976 public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) {
977 boolean foundValue = false;
979 if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) {
980 // Class is yang generated.
981 String propNamePfx = null;
982 if (pfx.endsWith("]")) {
986 if ((pfx != null) && (pfx.length() > 0)) {
987 propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
989 propNamePfx = toLowerHyphen(toClass.getSimpleName());
992 if (propNamePfx.endsWith(BUILDER)) {
993 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
996 if (propNamePfx.endsWith("-impl")) {
997 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
1001 // Iterate through getter methods to figure out values we need to
1004 for (Method m : toClass.getMethods()) {
1006 Class returnClass = m.getReturnType();
1008 String fieldName = toLowerHyphen(m.getName().substring(3));
1009 if (fieldName != null) {
1010 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
1014 String propName = propNamePfx + "." + fieldName;
1016 // Is the return type a yang generated class?
1017 if (isYangGenerated(returnClass)) {
1019 if (returnClass.isEnum()) {
1020 pstr.print("\n\n * " + propName);
1023 String simpleName = returnClass.getSimpleName();
1025 if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
1026 || IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)
1027 || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) {
1028 pstr.print("\n\n * " + propName);
1030 printPropertyList(pstr, propNamePfx, returnClass);
1036 // Setter's argument is not a yang-generated class. See
1039 if (List.class.isAssignableFrom(returnClass)) {
1040 // Figure out what type of args are in List and pass
1041 // that to toList().
1043 Type returnType = m.getGenericReturnType();
1044 Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
1045 Class elementClass = (Class) elementType;
1046 printPropertyList(pstr,
1047 propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]",
1050 } else if (!returnClass.equals(Class.class)) {
1052 // Setter expects something that is not a List and
1053 // not yang-generated. Just pass the parameter value
1054 pstr.print("\n\n * " + propName);
1057 } // End of section handling "setter" method
1058 } // End of loop through Methods
1059 } // End of section handling yang-generated class
1063 public static boolean isYangGenerated(Class c) {
1065 return (c.getName().startsWith("org.opendaylight.yang.gen."));
1070 public static boolean isIpPrefix(Class c) {
1075 if (!isIetfInet(c)) {
1078 String simpleName = c.getSimpleName();
1079 return (IP_PREFIX.equals(simpleName));
1082 public static boolean isIpv4Address(Class c) {
1087 if (!isIetfInet(c)) {
1090 String simpleName = c.getSimpleName();
1091 return (IPV4_ADDRESS.equals(simpleName));
1094 public static boolean isIpv6Address(Class c) {
1099 if (!isIetfInet(c)) {
1102 String simpleName = c.getSimpleName();
1103 return (IPV6_ADDRESS.equals(simpleName));
1106 public static boolean isIpAddress(Class c) {
1111 if (!isIetfInet(c)) {
1114 String simpleName = c.getSimpleName();
1115 return (IP_ADDRESS.equals(simpleName));
1118 public static boolean isPortNumber(Class c) {
1123 if (!isIetfInet(c)) {
1127 String simpleName = c.getSimpleName();
1128 return ("PortNumber".equals(simpleName));
1131 public static boolean isDscp(Class c) {
1136 if (!isIetfInet(c)) {
1139 String simpleName = c.getSimpleName();
1140 return ("Dscp".equals(simpleName));
1143 public static boolean isIetfInet(Class c) {
1145 Package p = c.getPackage();
1147 String pkgName = p.getName();
1149 if ((pkgName != null) && (pkgName.indexOf("yang.ietf.inet.types") > -1)) {
1157 public static String toLowerHyphen(String inStr) {
1158 if (inStr == null) {
1162 String str = inStr.substring(0, 1).toLowerCase();
1163 if (inStr.length() > 1) {
1164 str = str + inStr.substring(1);
1167 String regex = "([a-z0-9A-Z])(?=[A-Z])";
1168 String replacement = "$1-";
1170 String retval = str.replaceAll(regex, replacement).toLowerCase();
1175 // This is called when mapping the yang value back to a valid java enumeration
1176 public static String toJavaEnum(String inStr) {
1177 if (inStr == null) {
1179 } else if (inStr.length() == 0) {
1183 // This is needed for enums containing under scores
1184 inStr = inStr.replaceAll("_", "");
1186 // This will strip out all periods, which cannot be in a java enum
1187 inStr = inStr.replaceAll("\\.", "");
1189 // This is needed for enums containing spaces
1190 inStr = inStr.replaceAll(" ", "");
1192 String[] terms = inStr.split("-");
1193 StringBuffer sbuff = new StringBuffer();
1195 // appends an _ if the string starts with a digit to make it a valid java enum
1196 if (Character.isDigit(inStr.charAt(0))) {
1199 // If the string contains hyphens it will convert the string to upperCamelCase without hyphens
1200 for (String term : terms) {
1201 sbuff.append(term.substring(0, 1).toUpperCase());
1202 if (term.length() > 1) {
1203 sbuff.append(term.substring(1));
1206 return (sbuff.toString());
1210 public static boolean isGetter(Method m) {
1215 if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) {
1216 if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) {
1217 if (!"getClass".equals(m.getName())) {
1222 if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) {
1226 if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) {
1234 public static boolean isSetter(Method m) {
1239 if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) {
1240 if (m.getName().matches("^set[A-Z].*")) {
1241 Class[] paramTypes = m.getParameterTypes();
1242 if (paramTypes[0].isAssignableFrom(Identifier.class)
1243 || Identifier.class.isAssignableFrom(paramTypes[0])) {
1256 public static String getFullPropertiesPath(String propertiesFileName) {
1257 String karafHome = System.getProperty("karaf.home","/opt/lsc/controller");
1258 return karafHome + "/configuration/" + propertiesFileName;
1261 // This is called when mapping a valid java enumeration back to the yang model value
1263 public static String mapEnumeratedValue(String propertyName, String propertyValue) {
1264 LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue);
1265 String mappingKey = "yang." + propertyName + "." + propertyValue;
1266 if (yangMappingProperties.containsKey(mappingKey)) {
1267 return (yangMappingProperties.getProperty(mappingKey));
1269 LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value.");
1270 return propertyValue;