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.openecomp.sdnc.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 InputStream input = null;
69 if (file.isFile() && file.canRead()) {
71 input = new FileInputStream(file);
72 properties.load(input);
73 MdsalHelper.setYangMappingProperties(properties);
74 LOG.info("Loaded properties from " + propertiesFile);
75 } catch (Exception e) {
76 LOG.error("Failed to load properties " + propertiesFile + "\n", e);
81 } catch (IOException e) {
82 LOG.error("Failed to close properties file " + propertiesFile + "\n", e);
87 LOG.error("Failed to load the properties file " + propertiesFile + "\n");
88 LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n");
92 public static Properties toProperties(Properties props, Object fromObj) {
93 Class fromClass = null;
95 if (fromObj != null) {
96 fromClass = fromObj.getClass();
98 return (toProperties(props, "", fromObj, fromClass));
101 public static Properties toProperties(Properties props, String pfx, Object fromObj) {
102 Class fromClass = null;
104 if (fromObj != null) {
105 fromClass = fromObj.getClass();
108 return (toProperties(props, pfx, fromObj, fromClass));
111 public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) {
113 if (fromObj == null) {
117 String simpleName = fromClass.getSimpleName();
119 LOG.trace("Extracting properties from " + fromClass.getName() + " class");
120 if (fromObj instanceof List) {
122 // Class is a List. List should contain yang-generated classes.
123 LOG.trace(fromClass.getName() + " is a List");
125 List fromList = (List) fromObj;
127 for (int i = 0; i < fromList.size(); i++) {
128 toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass);
130 props.setProperty(pfx + "_length", "" + fromList.size());
132 } else if (isYangGenerated(fromClass)) {
133 // Class is yang generated.
134 LOG.trace(fromClass.getName() + " is a Yang-generated class");
136 String propNamePfx = null;
138 // If called from a list (so prefix ends in ']'), don't
139 // add class name again
140 if (pfx.endsWith("]")) {
143 if ((pfx != null) && (pfx.length() > 0)) {
146 propNamePfx = toLowerHyphen(fromClass.getSimpleName());
149 if (propNamePfx.endsWith("-builder")) {
150 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length());
153 if (propNamePfx.endsWith("-impl")) {
154 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
158 // Iterate through getter methods to figure out values we need to
162 String lastGetterName = null;
163 String propVal = null;
165 for (Method m : fromClass.getMethods()) {
169 lastGetterName = m.getName();
171 Class returnType = m.getReturnType();
173 if (m.getName().startsWith("get")) {
174 fieldName = toLowerHyphen(m.getName().substring(3));
177 fieldName = toLowerHyphen(m.getName().substring(2));
180 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
182 // Is the return type a yang generated class?
183 if (isYangGenerated(returnType)) {
185 if (returnType.isEnum()) {
186 // Return type is a typedef. Save its value.
188 boolean isAccessible = m.isAccessible();
190 m.setAccessible(true);
193 Object retValue = m.invoke(fromObj);
196 m.setAccessible(isAccessible);
198 if (retValue != null) {
199 String propName = propNamePfx + "." + fieldName;
200 propVal = retValue.toString();
201 props.setProperty(propName, mapEnumeratedValue(fieldName, propVal));
203 } catch (Exception e) {
204 LOG.error("Caught exception trying to convert Yang-generated enum returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
206 } else if (isIpv4Address(returnType)) {
209 String propName = propNamePfx + "." + fieldName;
210 boolean isAccessible = m.isAccessible();
212 m.setAccessible(true);
214 Ipv4Address retValue = (Ipv4Address) m.invoke(fromObj);
216 m.setAccessible(isAccessible);
219 if (retValue != null) {
220 propVal = retValue.getValue().toString();
221 LOG.debug("Setting property " + propName + " to " + propVal);
222 props.setProperty(propName, propVal);
225 } catch (Exception e) {
226 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
228 } else if (isIpv6Address(returnType)) {
231 String propName = propNamePfx + "." + fieldName;
232 boolean isAccessible = m.isAccessible();
234 m.setAccessible(true);
236 Ipv6Address retValue = (Ipv6Address) m.invoke(fromObj);
238 m.setAccessible(isAccessible);
241 if (retValue != null) {
242 propVal = retValue.getValue().toString();
243 LOG.debug("Setting property " + propName + " to " + propVal);
244 props.setProperty(propName, propVal);
247 } catch (Exception e) {
248 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
250 } else if (isIpAddress(returnType)) {
253 String propName = propNamePfx + "." + fieldName;
254 boolean isAccessible = m.isAccessible();
256 m.setAccessible(true);
258 IpAddress retValue = (IpAddress) m.invoke(fromObj);
260 m.setAccessible(isAccessible);
263 if (retValue != null) {
264 propVal = new String(retValue.getValue());
265 LOG.debug("Setting property " + propName + " to " + propVal);
266 props.setProperty(propName, propVal);
269 } catch (Exception e) {
270 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
272 } else if (isIpPrefix(returnType)) {
275 String propName = propNamePfx + "." + fieldName;
276 boolean isAccessible = m.isAccessible();
278 m.setAccessible(true);
280 IpPrefix retValue = (IpPrefix) m.invoke(fromObj);
282 m.setAccessible(isAccessible);
285 if (retValue != null) {
286 propVal = new String(retValue.getValue());
287 LOG.debug("Setting property " + propName + " to " + propVal);
288 props.setProperty(propName, propVal);
291 } catch (Exception e) {
292 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
296 boolean isAccessible = m.isAccessible();
298 m.setAccessible(true);
300 Object retValue = m.invoke(fromObj);
302 if (retValue instanceof byte[]) {
303 LOG.trace(m.getName() + " returns a byte[]");
304 retValue = new String((byte[]) retValue, "UTF-8");
305 LOG.trace("Converted byte array " + propNamePfx + "." + fieldName + "to string " + retValue);
308 m.setAccessible(isAccessible);
310 if (retValue != null) {
311 toProperties(props, propNamePfx + "." + fieldName, retValue, returnType);
313 } catch (Exception e) {
315 if (m.getName().equals("getKey")) {
316 LOG.trace("Caught " + e.getClass().getName() + " exception trying to convert results from getKey() - ignoring");
318 LOG.error("Caught exception trying to convert Yang-generated class returned by" + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
322 } else if (returnType.equals(Class.class)) {
324 LOG.trace(m.getName() + " returns a Class object - not interested");
326 } else if (List.class.isAssignableFrom(returnType)) {
328 // This getter method returns a list.
330 boolean isAccessible = m.isAccessible();
332 m.setAccessible(true);
334 Object retList = m.invoke(fromObj);
336 m.setAccessible(isAccessible);
338 // Figure out what type of elements are stored in
340 Type paramType = m.getGenericReturnType();
341 Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
342 toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType);
343 } catch (Exception e) {
344 LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
349 // Method returns something that is not a List and not
353 String propName = propNamePfx + "." + fieldName;
354 boolean isAccessible = m.isAccessible();
356 m.setAccessible(true);
358 Object propValObj = m.invoke(fromObj);
360 m.setAccessible(isAccessible);
363 if (propValObj != null) {
364 if (propValObj instanceof byte[]) {
365 LOG.trace(m.getName() + " returns a byte[]");
366 propVal = new String((byte[]) propValObj, "UTF-8");
367 LOG.trace("Converted byte array " + propNamePfx + "." + fieldName + "to string " + propVal);
370 propVal = propValObj.toString();
372 LOG.debug("Setting property " + propName + " to " + propVal);
373 props.setProperty(propName, propVal);
376 } catch (Exception e) {
377 if (m.getName().equals("getKey")) {
378 LOG.trace("Caught " + e.getClass().getName() + " exception trying to convert results from getKey() - ignoring");
380 LOG.error("Caught exception trying to convert value returned by" + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
388 // End of method loop. If there was only one getter, named
390 // set value identified by "prefix" to that one value.
391 if ((numGetters == 1) && ("getValue".equals(lastGetterName))) {
392 LOG.trace("getValueFIX : " + propNamePfx + " only has getValue() getter - setting " + propNamePfx + " = " + propVal);
393 props.setProperty(propNamePfx, propVal);
395 LOG.trace("getValueFIX : " + propNamePfx + " has " + numGetters + " getter(s), last one found was " + lastGetterName);
400 // Class is not yang generated and not a list
401 // It must be an element of a leaf list - set "prefix" to value
402 String fromVal = null;
403 if (fromObj instanceof byte[]) {
405 fromVal = new String((byte[]) fromObj, "UTF-8");
406 LOG.trace("Converted byte array " + pfx + "to string " + fromVal);
407 } catch (Exception e) {
408 LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e);
409 fromVal = fromObj.toString();
413 fromVal = fromObj.toString();
415 LOG.debug("Setting property " + pfx + " to " + fromVal);
416 props.setProperty(pfx, fromVal);
422 public static Object toBuilder(Properties props, Object toObj) {
424 return (toBuilder(props, "", toObj));
427 public static List toList(Properties props, String pfx, List toObj, Class elemType) {
430 boolean foundValue = false;
432 LOG.trace("Saving properties to List<" + elemType.getName() + "> from " + pfx);
434 if (props.contains(pfx + "_length")) {
436 int listLength = Integer.parseInt(props.getProperty(pfx + "_length"));
438 if (listLength > 0) {
439 maxIdx = listLength - 1;
441 } catch (Exception e) {
447 // Figure out array size
448 for (Object pNameObj : props.keySet()) {
449 String key = (String) pNameObj;
451 if (key.startsWith(pfx + "[")) {
452 String idxStr = key.substring(pfx.length() + 1);
453 int endloc = idxStr.indexOf("]");
455 idxStr = idxStr.substring(0, endloc);
459 int curIdx = Integer.parseInt(idxStr);
460 if (curIdx > maxIdx) {
463 } catch (Exception e) {
464 LOG.error("Illegal subscript in property " + key);
471 LOG.trace(pfx + " has max index of " + maxIdx);
472 for (int i = 0; i <= maxIdx; i++) {
474 String curBase = pfx + "[" + i + "]";
476 if (isYangGenerated(elemType)) {
477 String builderName = elemType.getName() + "Builder";
479 Class builderClass = Class.forName(builderName);
480 Object builderObj = builderClass.newInstance();
481 Method buildMethod = builderClass.getMethod("build");
482 builderObj = toBuilder(props, curBase, builderObj, true);
483 if (builderObj != null) {
484 LOG.trace("Calling " + builderObj.getClass().getName() + "." + buildMethod.getName() + "()");
485 Object builtObj = buildMethod.invoke(builderObj);
490 } catch (ClassNotFoundException e) {
491 LOG.warn("Could not find builder class " + builderName, e);
492 } catch (Exception e) {
493 LOG.error("Caught exception trying to populate list from " + pfx);
496 // Must be a leaf list
497 String curValue = props.getProperty(curBase, "");
501 if ((curValue != null) && (curValue.length() > 0)) {
516 public static Object toBuilder(Properties props, String pfx, Object toObj) {
517 return (toBuilder(props, pfx, toObj, false));
520 public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) {
521 Class toClass = toObj.getClass();
522 boolean foundValue = false;
524 LOG.trace("Saving properties to " + toClass.getName() + " class from " + pfx);
528 if (isYangGenerated(toClass)) {
529 // Class is yang generated.
530 LOG.trace(toClass.getName() + " is a Yang-generated class");
532 String propNamePfx = null;
537 if ((pfx != null) && (pfx.length() > 0)) {
538 propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
540 propNamePfx = toLowerHyphen(toClass.getSimpleName());
543 if (propNamePfx.endsWith("-builder")) {
544 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length());
547 if (propNamePfx.endsWith("-impl")) {
548 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
552 if (toObj instanceof Identifier) {
553 LOG.trace(toClass.getName() + " is a Key - skipping");
557 // Iterate through getter methods to figure out values we need to
560 for (Method m : toClass.getMethods()) {
562 Class paramTypes[] = m.getParameterTypes();
563 Class paramClass = paramTypes[0];
565 String fieldName = toLowerHyphen(m.getName().substring(3));
566 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
568 String propName = propNamePfx + "." + fieldName;
570 String paramValue = props.getProperty(propName);
571 if (paramValue == null) {
572 LOG.trace(propName + " is unset");
574 LOG.trace(propName + " = " + paramValue);
577 // Is the return type a yang generated class?
578 if (isYangGenerated(paramClass)) {
580 if (paramClass.isEnum()) {
582 LOG.trace(m.getName() + " expects an Enum");
583 // Param type is a typedef.
584 if ((paramValue != null) && (paramValue.length() > 0)) {
585 Object paramObj = null;
588 paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue));
589 } catch (Exception e) {
590 LOG.error("Caught exception trying to convert field " + propName + " to enum " + paramClass.getName(), e);
594 boolean isAccessible = m.isAccessible();
596 m.setAccessible(true);
599 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
600 m.invoke(toObj, paramObj);
603 m.setAccessible(isAccessible);
607 } catch (Exception e) {
608 LOG.error("Caught exception trying to create Yang-generated enum expected by" + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
613 String simpleName = paramClass.getSimpleName();
615 if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName)) {
617 if ((paramValue != null) && (paramValue.length() > 0)) {
619 IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue);
621 if ("Ipv4Address".equals(simpleName)) {
622 m.invoke(toObj, ipAddr.getIpv4Address());
623 } else if ("Ipv6Address".equals(simpleName)) {
624 m.invoke(toObj, ipAddr.getIpv6Address());
627 m.invoke(toObj, ipAddr);
630 } catch (Exception e) {
631 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + "(" + paramValue + ")", e);
636 boolean isAccessible = m.isAccessible();
638 m.setAccessible(true);
640 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
641 m.invoke(toObj, paramValue);
643 m.setAccessible(isAccessible);
647 } catch (Exception e) {
648 LOG.error("Caught exception trying to call " + toClass.getName() + "." + m.getName() + "() with Properties entry", e);
651 } else if ("IpPrefix".equals(simpleName)) {
652 if ((paramValue != null) && (paramValue.length() > 0)) {
654 IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue);
655 m.invoke(toObj, ipPrefix);
657 } catch (Exception e) {
658 LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName() + "(" + paramValue + ")", e);
662 // setter expects a yang-generated class. Need
664 // create a builder to set it.
666 String builderName = paramClass.getName() + "Builder";
667 Class builderClass = null;
668 Object builderObj = null;
669 Object paramObj = null;
671 Object constObj = null;
673 LOG.trace(m.getName() + " expects a yang-generated class - looking for builder " + builderName);
675 builderClass = Class.forName(builderName);
676 builderObj = builderClass.newInstance();
677 paramObj = toBuilder(props, propNamePfx, builderObj);
678 } catch (ClassNotFoundException e) {
680 if (paramValue == null) {
682 boolean isAccessible = m.isAccessible();
684 m.setAccessible(true);
686 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(null)");
687 m.invoke(toObj, new Object[] { null });
689 m.setAccessible(isAccessible);
693 } catch (Exception e1) {
694 LOG.error("Caught exception trying to cally" + toClass.getName() + "." + m.getName() + "() with Properties entry", e1);
698 // See if I can find a constructor I
701 Constructor[] constructors = paramClass.getConstructors();
702 // Is there a String constructor?
703 for (Constructor c : constructors) {
704 Class[] cParms = c.getParameterTypes();
705 if ((cParms != null) && (cParms.length == 1)) {
706 if (String.class.isAssignableFrom(cParms[0])) {
707 constObj = c.newInstance(paramValue);
712 if (constObj == null) {
713 // Is there a Long constructor?
714 for (Constructor c : constructors) {
715 Class[] cParms = c.getParameterTypes();
716 if ((cParms != null) && (cParms.length == 1)) {
717 if (Long.class.isAssignableFrom(cParms[0])) {
718 constObj = c.newInstance(Long.parseLong(paramValue));
725 if (constObj == null) {
727 // Last chance - see if
728 // parameter class has a static
730 // getDefaultInstance(String)
732 Method gm = paramClass.getMethod("getDefaultInstance", String.class);
734 int gmodifier = gm.getModifiers();
735 if (Modifier.isStatic(gmodifier)) {
737 // getDefaultInstance(String)
738 paramObj = gm.invoke(null, paramValue);
741 } catch (Exception gme) {
746 } catch (Exception e1) {
747 LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
750 if (constObj == null) {
751 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");
755 } catch (Exception e) {
756 LOG.error("Caught exception trying to create builder " + builderName, e);
759 if (paramObj != null) {
763 Method buildMethod = builderClass.getMethod("build");
764 LOG.trace("Calling " + paramObj.getClass().getName() + "." + buildMethod.getName() + "()");
765 Object builtObj = buildMethod.invoke(paramObj);
767 boolean isAccessible = m.isAccessible();
769 m.setAccessible(true);
772 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "()");
773 m.invoke(toObj, builtObj);
775 m.setAccessible(isAccessible);
779 } catch (Exception e) {
780 LOG.error("Caught exception trying to set Yang-generated class expected by" + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
784 boolean isAccessible = m.isAccessible();
786 m.setAccessible(true);
789 if (constObj != null) {
791 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + constObj.toString() + ")");
792 m.invoke(toObj, constObj);
794 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
795 m.invoke(toObj, paramValue);
799 m.setAccessible(isAccessible);
803 } catch (Exception e) {
804 LOG.error("Caught exception trying to convert value returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
811 // Setter's argument is not a yang-generated class. See
814 if (List.class.isAssignableFrom(paramClass)) {
816 LOG.trace("Parameter class " + paramClass.getName() + " is a List");
818 // Figure out what type of args are in List and pass
821 Type paramType = m.getGenericParameterTypes()[0];
822 Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
823 Object paramObj = new LinkedList();
825 paramObj = toList(props, propName, (List) paramObj, (Class) elementType);
826 } catch (Exception e) {
827 LOG.error("Caught exception trying to create list expected as argument to " + toClass.getName() + "." + m.getName());
830 if (paramObj != null) {
832 boolean isAccessible = m.isAccessible();
834 m.setAccessible(true);
836 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
837 m.invoke(toObj, paramObj);
839 m.setAccessible(isAccessible);
843 } catch (Exception e) {
844 LOG.error("Caught exception trying to convert List returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
849 // Setter expects something that is not a List and
850 // not yang-generated. Just pass the parameter value
852 LOG.trace("Parameter class " + paramClass.getName() + " is not a yang-generated class or a List");
854 if ((paramValue != null) && (paramValue.length() > 0)) {
856 Object constObj = null;
859 // See if I can find a constructor I can use
860 Constructor[] constructors = paramClass.getConstructors();
861 // Is there a String constructor?
862 for (Constructor c : constructors) {
863 Class[] cParms = c.getParameterTypes();
864 if ((cParms != null) && (cParms.length == 1)) {
865 if (String.class.isAssignableFrom(cParms[0])) {
866 constObj = c.newInstance(paramValue);
871 if (constObj == null) {
872 // Is there a Long constructor?
873 for (Constructor c : constructors) {
874 Class[] cParms = c.getParameterTypes();
875 if ((cParms != null) && (cParms.length == 1)) {
876 if (Long.class.isAssignableFrom(cParms[0])) {
877 constObj = c.newInstance(Long.parseLong(paramValue));
884 if (constObj != null) {
886 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + constObj + ")");
887 m.invoke(toObj, constObj);
889 } catch (Exception e2) {
890 LOG.error("Caught exception trying to call " + m.getName(), e2);
894 boolean isAccessible = m.isAccessible();
896 m.setAccessible(true);
898 LOG.trace("Calling " + toObj.getClass().getName() + "." + m.getName() + "(" + paramValue + ")");
899 m.invoke(toObj, paramValue);
901 m.setAccessible(isAccessible);
905 } catch (Exception e) {
906 LOG.error("Caught exception trying to convert value returned by" + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
909 } catch (Exception e1) {
910 LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
916 } // End of section handling "setter" method
917 } // End of loop through Methods
918 } // End of section handling yang-generated class
927 public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) {
928 boolean foundValue = false;
930 LOG.trace("Analyzing " + toClass.getName() + " class : pfx " + pfx);
932 if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) {
933 // Class is yang generated.
934 LOG.trace(toClass.getName() + " is a Yang-generated class");
936 if (toClass.getName().endsWith("Key")) {
937 if (Identifier.class.isAssignableFrom(toClass)) {
938 LOG.trace(Identifier.class.getName() + " is assignable from " + toClass.getName());
941 LOG.trace(Identifier.class.getName() + " is NOT assignable from " + toClass.getName());
945 String propNamePfx = null;
946 if (pfx.endsWith("]")) {
950 if ((pfx != null) && (pfx.length() > 0)) {
951 propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
953 propNamePfx = toLowerHyphen(toClass.getSimpleName());
956 if (propNamePfx.endsWith("-builder")) {
957 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-builder".length());
960 if (propNamePfx.endsWith("-impl")) {
961 propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
965 // Iterate through getter methods to figure out values we need to
968 for (Method m : toClass.getMethods()) {
969 LOG.trace("Is " + m.getName() + " method a getter?");
971 LOG.trace(m.getName() + " is a getter");
972 Class returnClass = m.getReturnType();
974 String fieldName = toLowerHyphen(m.getName().substring(3));
975 fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
977 String propName = propNamePfx + "." + fieldName;
979 // Is the return type a yang generated class?
980 if (isYangGenerated(returnClass)) {
982 if (returnClass.isEnum()) {
984 LOG.trace(m.getName() + " is an Enum");
985 pstr.print("\n\n * " + propName);
989 String simpleName = returnClass.getSimpleName();
991 if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName) || "IpPrefix".equals(simpleName)) {
992 LOG.trace(m.getName() + " is an " + simpleName);
993 pstr.print("\n\n * " + propName);
995 printPropertyList(pstr, propNamePfx, returnClass);
1001 // Setter's argument is not a yang-generated class. See
1004 if (List.class.isAssignableFrom(returnClass)) {
1006 LOG.trace("Parameter class " + returnClass.getName() + " is a List");
1008 // Figure out what type of args are in List and pass
1009 // that to toList().
1011 Type returnType = m.getGenericReturnType();
1012 Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
1013 Class elementClass = (Class) elementType;
1014 LOG.trace("Calling printPropertyList on list type (" + elementClass.getName() + "), pfx is (" + pfx + "), toClass is (" + toClass.getName() + ")");
1015 printPropertyList(pstr, propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]", elementClass);
1017 } else if (!returnClass.equals(Class.class)) {
1019 // Setter expects something that is not a List and
1020 // not yang-generated. Just pass the parameter value
1022 LOG.trace("Parameter class " + returnClass.getName() + " is not a yang-generated class or a List");
1024 pstr.print("\n\n * " + propName);
1028 } // End of section handling "setter" method
1029 } // End of loop through Methods
1030 } // End of section handling yang-generated class
1034 public static boolean isYangGenerated(Class c) {
1038 return (c.getName().startsWith("org.opendaylight.yang.gen."));
1042 public static boolean isIpPrefix(Class c) {
1047 String simpleName = c.getSimpleName();
1048 return ("IpPrefix".equals(simpleName));
1051 public static boolean isIpv4Address(Class c) {
1056 String simpleName = c.getSimpleName();
1057 return ("Ipv4Address".equals(simpleName));
1060 public static boolean isIpv6Address(Class c) {
1065 String simpleName = c.getSimpleName();
1066 return ("Ipv6Address".equals(simpleName));
1069 public static boolean isIpAddress(Class c) {
1074 String simpleName = c.getSimpleName();
1075 return ("IpAddress".equals(simpleName));
1078 public static String toLowerHyphen(String inStr) {
1079 if (inStr == null) {
1083 String str = inStr.substring(0, 1).toLowerCase();
1084 if (inStr.length() > 1) {
1085 str = str + inStr.substring(1);
1088 String regex = "(([a-z0-9])([A-Z]))";
1089 String replacement = "$2-$3";
1091 String retval = str.replaceAll(regex, replacement).toLowerCase();
1093 LOG.trace("Converting " + inStr + " => " + str + " => " + retval);
1097 //This is called when mapping the yang value back to a valid java enumeration
1098 public static String toJavaEnum(String inStr) {
1099 if (inStr == null) {
1101 } else if (inStr.length() == 0) {
1105 //This will strip out all periods, which cannot be in a java enum
1106 inStr = inStr.replaceAll("\\.", "");
1108 String[] terms = inStr.split("-");
1109 StringBuffer sbuff = new StringBuffer();
1111 //appends an _ if the string starts with a digit to make it a valid java enum
1112 if (Character.isDigit(inStr.charAt(0))) {
1115 //If the string contains hyphens it will convert the string to upperCamelCase without hyphens
1116 for (String term : terms) {
1117 sbuff.append(term.substring(0, 1).toUpperCase());
1118 if (term.length() > 1) {
1119 sbuff.append(term.substring(1));
1122 return (sbuff.toString());
1126 public static boolean isGetter(Method m) {
1131 if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) {
1132 if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) {
1133 if (!"getClass".equals(m.getName())) {
1138 if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) {
1142 if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) {
1150 public static boolean isSetter(Method m) {
1155 if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) {
1156 if (m.getName().matches("^set[A-Z].*")) {
1157 Class[] paramTypes = m.getParameterTypes();
1158 if (paramTypes[0].isAssignableFrom(Identifier.class) || Identifier.class.isAssignableFrom(paramTypes[0])) {
1170 public static String getFullPropertiesPath(String propertiesFileName) {
1171 return "/opt/bvc/controller/configuration/" + propertiesFileName;
1174 //This is called when mapping a valid java enumeration back to the yang model value
1175 public static String mapEnumeratedValue(String propertyName, String propertyValue) {
1176 LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue);
1177 String mappingKey = "yang." + propertyName + "." + propertyValue;
1178 if (yangMappingProperties.containsKey(mappingKey)) {
1179 return (yangMappingProperties.getProperty(mappingKey));
1181 LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value.");
1182 return propertyValue;