3b6151c917ed09a6f5f96abe98288edd92afff93
[ccsdk/sli/core.git] / sli / provider / src / main / java / org / onap / ccsdk / sli / core / sli / provider / MdsalHelper.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : CCSDK
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                         reserved.
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
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
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=========================================================
22  */
23
24 package org.onap.ccsdk.sli.core.sli.provider;
25
26 import java.io.File;
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.yangtools.yang.binding.Identifier;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 public class MdsalHelper {
51
52     private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class);
53     private static Properties yangMappingProperties = new Properties();
54     private static final String IP_ADDRESS="IpAddress";
55     private static final String IPV4_ADDRESS="Ipv4Address";
56     private static final String IPV6_ADDRESS="Ipv6Address";
57     
58     private static final String IP_PREFIX="IpPrefix";
59     private static final String SETTING_PROPERTY="Setting property ";
60     private static final String BUILDER="-builder";
61     
62     @Deprecated
63     public static void setProperties(Properties input) {
64         setYangMappingProperties(input);
65     }
66
67     @Deprecated
68     public static void setYangMappingProperties(Properties properties) {
69         for (Object propNameObj : properties.keySet()) {
70             String propName = (String) propNameObj;
71             MdsalHelper.yangMappingProperties.setProperty(propName, properties.getProperty(propName));
72         }
73     }
74
75     @Deprecated
76     public static void loadProperties(String propertiesFile) {
77         File file = new File(propertiesFile);
78         Properties properties = new Properties();
79         if (file.isFile() && file.canRead()) {
80             try (InputStream input = new FileInputStream(file)) {
81                 properties.load(input);
82                 MdsalHelper.setYangMappingProperties(properties);
83                 LOG.info("Loaded properties from " + propertiesFile);
84             } catch (Exception e) {
85                 LOG.error("Failed to load properties " + propertiesFile + "\n", e);
86             }
87         } else {
88             LOG.error("Failed to load the properties file " + propertiesFile + "\n");
89             LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n");
90         }
91     }
92
93     public static Properties toProperties(Properties props, Object fromObj) {
94         return toProperties(props, fromObj, false);
95     }
96
97     public static Properties toProperties(Properties props, Object fromObj, Boolean useLegacyEnumerationMapping) {
98         Class fromClass = null;
99
100         if (fromObj != null) {
101             fromClass = fromObj.getClass();
102         }
103         return toProperties(props, "", fromObj, fromClass, useLegacyEnumerationMapping);
104     }
105
106     public static Properties toProperties(Properties props, String pfx, Object fromObj) {
107         return toProperties(props, pfx, fromObj, false);
108     }
109
110     public static Properties toProperties(Properties props, String pfx, Object fromObj, Boolean useLegacyEnumerationMapping) {
111         Class fromClass = null;
112
113         if (fromObj != null) {
114             fromClass = fromObj.getClass();
115         }
116
117         return toProperties(props, pfx, fromObj, fromClass, useLegacyEnumerationMapping);
118     }
119
120     public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) {
121         return toProperties(props, pfx, fromObj, fromClass, false);
122     }
123
124     public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass, Boolean useLegacyEnumerationMapping) {
125
126         if (fromObj == null) {
127             return props;
128         }
129         String simpleTypeName = fromObj.getClass().getTypeName();
130         simpleTypeName = simpleTypeName.substring(simpleTypeName.lastIndexOf(".") + 1);
131         
132         if (classHasSpecialHandling(simpleTypeName)) {
133             try {
134
135                 Method m = fromClass.getMethod(getStringValueMethod(simpleTypeName), null);
136                 boolean isAccessible = m.isAccessible();
137                 if (!isAccessible) {
138                     m.setAccessible(true);
139                 }
140                 Object retValue = m.invoke(fromObj);
141                 if (retValue != null) {
142                     String propVal = null;
143                     if (IP_ADDRESS.equals(simpleTypeName) || IP_PREFIX.equals(simpleTypeName)
144                                 || IPV4_ADDRESS.equals(simpleTypeName) || IPV6_ADDRESS.equals(simpleTypeName)) {
145                         propVal = (String) retValue;
146                     } else if ("Dscp".equals(simpleTypeName)) {
147                         propVal = String.valueOf((short) retValue);
148                     } else if ("PortNumber".equals(simpleTypeName)) {
149                         propVal = String.valueOf((Integer) retValue);
150                     }
151                     LOG.debug(SETTING_PROPERTY + pfx + " to " + propVal);
152                     props.setProperty(pfx, propVal);
153                 }
154             } catch (Exception e) {
155                 LOG.error("Caught exception trying to convert value returned by " + fromClass.getName()
156                         + ".getValue() to Properties entry", e);
157             }
158         } else if (fromObj instanceof List) {
159             List fromList = (List) fromObj;
160
161             for (int i = 0; i < fromList.size(); i++) {
162                 toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass, useLegacyEnumerationMapping);
163             }
164             props.setProperty(pfx + "_length", Integer.toString(fromList.size()));
165
166         } else if (isYangGenerated(fromClass)) {
167             // Class is yang generated.
168
169             String propNamePfx = null;
170
171             // If called from a list (so prefix ends in ']'), don't
172             // add class name again
173             if (pfx.endsWith("]")) {
174                 propNamePfx = pfx;
175             } else {
176                 if ((pfx != null) && (pfx.length() > 0)) {
177                     propNamePfx = pfx;
178                 } else {
179                     propNamePfx = toLowerHyphen(fromClass.getSimpleName());
180                 }
181
182                 if (propNamePfx.endsWith(BUILDER)) {
183                     propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
184                 }
185
186                 if (propNamePfx.endsWith("-impl")) {
187                     propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
188                 }
189             }
190
191             // Iterate through getter methods to figure out values we need to
192             // save from
193
194             int numGetters = 0;
195             String lastGetterName = null;
196             String propVal = null;
197
198             for (Method m : fromClass.getMethods()) {
199                 if (isGetter(m)) {
200
201                     numGetters++;
202                     lastGetterName = m.getName();
203
204                     Class returnType = m.getReturnType();
205                     String fieldName;
206                     if (m.getName().startsWith("get")) {
207                         fieldName = toLowerHyphen(m.getName().substring(3));
208                     } else {
209
210                         fieldName = toLowerHyphen(m.getName().substring(2));
211                     }
212
213                     fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
214
215                     // Is the return type a yang generated class?
216                     if (isYangGenerated(returnType)) {
217                         // Is it an enum?
218                         if (returnType.isEnum()) {
219                             // Return type is a typedef. Save its value.
220                             try {
221                                 boolean isAccessible = m.isAccessible();
222                                 if (!isAccessible) {
223                                     m.setAccessible(true);
224                                 }
225
226                                 Object retValue = m.invoke(fromObj);
227
228                                 if (!isAccessible) {
229                                     m.setAccessible(isAccessible);
230                                 }
231                                 if (retValue != null) {
232                                     String propName = propNamePfx + "." + fieldName;
233                                     if (useLegacyEnumerationMapping) {
234                                         propVal = retValue.toString();
235                                         props.setProperty(propName, mapEnumeratedValue(fieldName, propVal));
236                                     } else {
237                                         Method method = retValue.getClass().getMethod("getName");
238                                         String yangValue = (String) method.invoke(retValue);
239                                         props.setProperty(propName, yangValue);
240                                     }
241
242                                 }
243                             } catch (Exception e) {
244                                 LOG.error(
245                                         "Caught exception trying to convert Yang-generated enum returned by "
246                                                 + fromClass.getName() + "." + m.getName() + "() to Properties entry",
247                                         e);
248                             }
249                         } else {
250                             try {
251                                 boolean isAccessible = m.isAccessible();
252                                 if (!isAccessible) {
253                                     m.setAccessible(true);
254                                 }
255                                 Object retValue = m.invoke(fromObj);
256
257                                 if (retValue instanceof byte[]) {
258                                     retValue = new String((byte[]) retValue, "UTF-8");
259                                 }
260                                 if (!isAccessible) {
261                                     m.setAccessible(isAccessible);
262                                 }
263                                 if (retValue != null) {
264                                     toProperties(props, propNamePfx + "." + fieldName, retValue, returnType, useLegacyEnumerationMapping);
265                                 }
266                             } catch (Exception e) {
267
268                                 if (m.getName().equals("getKey")) {
269                                     LOG.trace("Caught " + e.getClass().getName()
270                                             + " exception trying to convert results from getKey() - ignoring");
271                                 } else {
272                                     LOG.error("Caught exception trying to convert Yang-generated class returned by"
273                                             + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
274                                 }
275                             }
276                         }
277                     } else if (returnType.equals(Class.class)) {
278
279                     } else if (List.class.isAssignableFrom(returnType)) {
280
281                         // This getter method returns a list.
282                         try {
283                             boolean isAccessible = m.isAccessible();
284                             if (!isAccessible) {
285                                 m.setAccessible(true);
286                             }
287                             Object retList = m.invoke(fromObj);
288                             if (!isAccessible) {
289                                 m.setAccessible(isAccessible);
290                             }
291                             // Figure out what type of elements are stored in
292                             // this array.
293                             Type paramType = m.getGenericReturnType();
294                             Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
295                             toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType, useLegacyEnumerationMapping);
296                         } catch (Exception e) {
297                             LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "."
298                                     + m.getName() + "() to Properties entry", e);
299                         }
300
301                     } else {
302
303                         // Method returns something that is not a List and not
304                         // yang-generated.
305                         // Save its value
306                         try {
307                             String propName = propNamePfx + "." + fieldName;
308                             boolean isAccessible = m.isAccessible();
309                             if (!isAccessible) {
310                                 m.setAccessible(true);
311                             }
312                             Object propValObj = m.invoke(fromObj);
313                             if (!isAccessible) {
314                                 m.setAccessible(isAccessible);
315                             }
316
317                             if (propValObj != null) {
318                                 if (propValObj instanceof byte[]) {
319                                     propVal = new String((byte[]) propValObj, "UTF-8");
320                                 } else {
321                                     propVal = propValObj.toString();
322                                 }
323                                 LOG.debug(SETTING_PROPERTY + propName + " to " + propVal);
324                                 props.setProperty(propName, propVal);
325
326                             }
327                         } catch (Exception e) {
328                             if (m.getName().equals("getKey")) {
329                                 LOG.trace("Caught " + e.getClass().getName()
330                                         + " exception trying to convert results from getKey() - ignoring");
331                             } else {
332                                 LOG.error("Caught exception trying to convert value returned by" + fromClass.getName()
333                                         + "." + m.getName() + "() to Properties entry", e);
334                             }
335                         }
336                     }
337
338                 }
339             }
340
341             // End of method loop. If there was only one getter, named
342             // "getValue", then
343             // set value identified by "prefix" to that one value.
344             if ((numGetters == 1) && ("getValue".equals(lastGetterName))) {
345                 LOG.trace("getValueFIX : " + propNamePfx + " only has getValue() getter - setting " + propNamePfx
346                         + " = " + propVal);
347                 props.setProperty(propNamePfx, propVal);
348             } else {
349                 LOG.trace("getValueFIX : " + propNamePfx + " has " + numGetters + " getter(s), last one found was "
350                         + lastGetterName);
351
352             }
353
354         } else {
355             // Class is not yang generated and not a list
356             // It must be an element of a leaf list - set "prefix" to value
357             String fromVal = null;
358             if (fromObj instanceof byte[]) {
359                 try {
360                     fromVal = new String((byte[]) fromObj, "UTF-8");
361                 } catch (Exception e) {
362                     LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e);
363                     fromVal = fromObj.toString();
364                 }
365
366             } else {
367                 fromVal = fromObj.toString();
368             }
369             LOG.debug(SETTING_PROPERTY + pfx + " to " + fromVal);
370             props.setProperty(pfx, fromVal);
371         }
372
373         return (props);
374     }
375
376     public static Object toBuilder(Properties props, Object toObj) {
377
378         return (toBuilder(props, "", toObj));
379     }
380
381     public static List toList(Properties props, String pfx, List toObj, Class elemType) {
382
383         int maxIdx = -1;
384         boolean foundValue = false;
385
386         if (props.containsKey(pfx + "_length")) {
387             try {
388                 int listLength = Integer.parseInt(props.getProperty(pfx + "_length"));
389
390                 if (listLength > 0) {
391                     maxIdx = listLength - 1;
392                 }
393             } catch (NumberFormatException e) {
394                 LOG.info("Invalid input for length ", e);
395             }
396         }
397
398         String arrayKey = pfx + "[";
399         int arrayKeyLength = arrayKey.length();
400         if (maxIdx == -1) {
401             // Figure out array size
402             for (Object pNameObj : props.keySet()) {
403                 String key = (String) pNameObj;
404
405                 if (key.startsWith(arrayKey)) {
406                     String idxStr = key.substring(arrayKeyLength);
407                     int endloc = idxStr.indexOf("]");
408                     if (endloc != -1) {
409                         idxStr = idxStr.substring(0, endloc);
410                     }
411                     try {
412                         int curIdx = Integer.parseInt(idxStr);
413                         if (curIdx > maxIdx) {
414                             maxIdx = curIdx;
415                         }
416                     } catch (Exception e) {
417                         LOG.error("Illegal subscript in property {}", key, e);
418                     }
419
420                 }
421             }
422         }
423
424         for (int i = 0; i <= maxIdx; i++) {
425
426             String curBase = pfx + "[" + i + "]";
427
428             if (isYangGenerated(elemType)) {
429
430                 if (isIpAddress(elemType)) {
431
432                     String curValue = props.getProperty(curBase, "");
433
434                     if ((curValue != null) && (curValue.length() > 0)) {
435                         toObj.add(IpAddressBuilder.getDefaultInstance(curValue));
436                         foundValue = true;
437                     }
438                 } else if (isIpv4Address(elemType)) {
439                     String curValue = props.getProperty(curBase, "");
440
441                     if ((curValue != null) && (curValue.length() > 0)) {
442                         toObj.add(new Ipv4Address(curValue));
443                         foundValue = true;
444                     }
445
446                 } else if (isIpv6Address(elemType)) {
447                     String curValue = props.getProperty(curBase, "");
448
449                     if ((curValue != null) && (curValue.length() > 0)) {
450                         toObj.add(new Ipv6Address(curValue));
451                         foundValue = true;
452                     }
453                 } else if (isIpPrefix(elemType)) {
454
455                     String curValue = props.getProperty(curBase, "");
456
457                     if ((curValue != null) && (curValue.length() > 0)) {
458                         toObj.add(IpPrefixBuilder.getDefaultInstance(curValue));
459                         foundValue = true;
460                     }
461                 } else if (isPortNumber(elemType)) {
462
463                     String curValue = props.getProperty(curBase, "");
464
465                     if ((curValue != null) && (curValue.length() > 0)) {
466                         toObj.add(PortNumber.getDefaultInstance(curValue));
467                         foundValue = true;
468                     }
469                 } else if (isDscp(elemType)) {
470
471                     String curValue = props.getProperty(curBase, "");
472
473                     if ((curValue != null) && (curValue.length() > 0)) {
474                         toObj.add(Dscp.getDefaultInstance(curValue));
475                         foundValue = true;
476                     }
477                 } else {
478                     String builderName = elemType.getName() + "Builder";
479                     try {
480                         Class builderClass = Class.forName(builderName);
481                         Object builderObj = builderClass.newInstance();
482                         Method buildMethod = builderClass.getMethod("build");
483                         builderObj = toBuilder(props, curBase, builderObj, true);
484                         if (builderObj != null) {
485                             Object builtObj = buildMethod.invoke(builderObj);
486                             toObj.add(builtObj);
487                             foundValue = true;
488                         }
489
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, e);
494                     }
495                 }
496             } else {
497                 // Must be a leaf list
498                 String curValue = props.getProperty(curBase, "");
499
500                 toObj.add(curValue);
501
502                 if ((curValue != null) && (curValue.length() > 0)) {
503                     foundValue = true;
504                 }
505             }
506
507         }
508
509         if (foundValue) {
510             return (toObj);
511         } else {
512             return (null);
513         }
514
515     }
516
517     public static Object toBuilder(Properties props, String pfx, Object toObj) {
518         return (toBuilder(props, pfx, toObj, false));
519     }
520
521     public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) {
522
523         Class toClass = toObj.getClass();
524         boolean foundValue = false;
525
526         Ipv4Address addr;
527
528         if (isYangGenerated(toClass)) {
529             // Class is yang generated.
530             String propNamePfx = null;
531             if (preservePfx) {
532                 propNamePfx = pfx;
533             } else {
534
535                 if ((pfx != null) && (pfx.length() > 0)) {
536                     propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
537                 } else {
538                     propNamePfx = toLowerHyphen(toClass.getSimpleName());
539                 }
540
541                 if (propNamePfx.endsWith(BUILDER)) {
542                     propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
543                 }
544
545                 if (propNamePfx.endsWith("-impl")) {
546                     propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
547                 }
548             }
549
550             if (toObj instanceof Identifier) {
551                 return (toObj);
552             }
553
554             // Iterate through getter methods to figure out values we need to
555             // set
556
557             for (Method m : toClass.getMethods()) {
558                 if (isSetter(m)) {
559                     Class paramTypes[] = m.getParameterTypes();
560                     Class paramClass = paramTypes[0];
561
562                     String fieldName = toLowerHyphen(m.getName().substring(3));
563                     fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
564
565                     String propName = propNamePfx + "." + fieldName;
566
567                     String paramValue = props.getProperty(propName);
568                     if (paramValue == null) {
569
570                     } else if ("".equals(paramValue)) {
571                         LOG.trace(propName + " was set to the empty string, setting it to null");
572                         paramValue = null;
573                     } else {
574
575                     }
576
577                     // Is the return type a yang generated class?
578                     if (isYangGenerated(paramClass)) {
579                         // Is it an enum?
580                         if (paramClass.isEnum()) {
581
582                             // Param type is a typedef.
583                             if ((paramValue != null) && (paramValue.length() > 0)) {
584                                 Object paramObj = null;
585
586                                 try {
587                                     paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue));
588                                 } catch (Exception e) {
589                                     LOG.error("Caught exception trying to convert field " + propName + " to enum "
590                                             + paramClass.getName(), e);
591                                 }
592
593                                 try {
594                                     boolean isAccessible = m.isAccessible();
595                                     if (!isAccessible) {
596                                         m.setAccessible(true);
597                                     }
598
599                                     m.invoke(toObj, paramObj);
600
601                                     if (!isAccessible) {
602                                         m.setAccessible(isAccessible);
603                                     }
604                                     foundValue = true;
605
606                                 } catch (Exception e) {
607                                     LOG.error("Caught exception trying to create Yang-generated enum expected by"
608                                             + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
609                                 }
610                             }
611                         } else {
612
613                             String simpleName = paramClass.getSimpleName();
614
615                             if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
616                                     || IP_ADDRESS.equals(simpleName)) {
617                                 
618
619                                 if ((paramValue != null) && (paramValue.length() > 0)) {
620                                     try {
621                                         IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue);
622
623                                         if (IPV4_ADDRESS.equals(simpleName)) {
624                                             m.invoke(toObj, ipAddr.getIpv4Address());
625                                         } else if (IPV6_ADDRESS.equals(simpleName)) {
626                                             m.invoke(toObj, ipAddr.getIpv6Address());
627
628                                         } else {
629                                             m.invoke(toObj, ipAddr);
630                                         }
631                                         foundValue = true;
632                                     } catch (Exception e) {
633                                         LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
634                                                 + "(" + paramValue + ")", e);
635
636                                     }
637                                 } else {
638                                     try {
639                                         boolean isAccessible = m.isAccessible();
640                                         if (!isAccessible) {
641                                             m.setAccessible(true);
642                                         }
643
644                                         m.invoke(toObj, paramValue);
645                                         if (!isAccessible) {
646                                             m.setAccessible(isAccessible);
647                                         }
648                                         foundValue = true;
649
650                                     } catch (Exception e) {
651                                         LOG.error("Caught exception trying to call " + toClass.getName() + "."
652                                                 + m.getName() + "() with Properties entry", e);
653                                     }
654                                 }
655                             } else if (IP_PREFIX.equals(simpleName)) {
656                                 if ((paramValue != null) && (paramValue.length() > 0)) {
657                                     try {
658                                         IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue);
659                                         m.invoke(toObj, ipPrefix);
660                                         foundValue = true;
661                                     } catch (Exception e) {
662                                         LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
663                                                 + "(" + paramValue + ")", e);
664                                     }
665                                 }
666                             } else if ("PortNumber".equals(simpleName)) {
667                                 if ((paramValue != null) && (paramValue.length() > 0)) {
668                                     try {
669                                         PortNumber portNumber = PortNumber.getDefaultInstance(paramValue);
670                                         m.invoke(toObj, portNumber);
671                                         foundValue = true;
672                                     } catch (Exception e) {
673                                         LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
674                                                 + "(" + paramValue + ")", e);
675                                     }
676                                 }
677                             } else if ("Dscp".equals(simpleName)) {
678                                 if ((paramValue != null) && (paramValue.length() > 0)) {
679                                     try {
680                                         Dscp dscp = Dscp.getDefaultInstance(paramValue);
681                                         m.invoke(toObj, dscp);
682                                         foundValue = true;
683                                     } catch (Exception e) {
684                                         LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
685                                                 + "(" + paramValue + ")", e);
686                                     }
687                                 }
688                             } else {
689                                 // setter expects a yang-generated class. Need
690                                 // to
691                                 // create a builder to set it.
692
693                                 String builderName = paramClass.getName() + "Builder";
694                                 Class builderClass = null;
695                                 Object builderObj = null;
696                                 Object paramObj = null;
697
698                                 Object constObj = null;
699
700                                 try {
701                                     builderClass = Class.forName(builderName);
702                                     builderObj = builderClass.newInstance();
703                                     paramObj = toBuilder(props, propNamePfx, builderObj);
704                                 } catch (ClassNotFoundException e) {
705                                     LOG.info("Builder class {} not found ", builderName, e);
706                                     if (paramValue == null) {
707                                         try {
708                                             boolean isAccessible = m.isAccessible();
709                                             if (!isAccessible) {
710                                                 m.setAccessible(true);
711                                             }
712
713                                             m.invoke(toObj, new Object[] { null });
714                                             if (!isAccessible) {
715                                                 m.setAccessible(isAccessible);
716                                             }
717                                             foundValue = true;
718
719                                         } catch (Exception e1) {
720                                             LOG.error("Caught exception trying to cally" + toClass.getName() + "."
721                                                     + m.getName() + "() with Properties entry", e1);
722                                         }
723                                     } else {
724                                         try {
725                                             // See if I can find a constructor I
726                                             // can
727                                             // use
728                                             Constructor[] constructors = paramClass.getConstructors();
729                                             // Is there a String constructor?
730                                             for (Constructor c : constructors) {
731                                                 Class[] cParms = c.getParameterTypes();
732                                                 if ((cParms != null) && (cParms.length == 1)) {
733                                                     if (String.class.isAssignableFrom(cParms[0])) {
734                                                         constObj = c.newInstance(paramValue);
735                                                     }
736                                                 }
737                                             }
738
739                                             if (constObj == null) {
740                                                 // Is there a Long constructor?
741                                                 for (Constructor c : constructors) {
742                                                     Class[] cParms = c.getParameterTypes();
743                                                     if ((cParms != null) && (cParms.length == 1)) {
744                                                         if (Long.class.isAssignableFrom(cParms[0])) {
745                                                             constObj = c.newInstance(Long.parseLong(paramValue));
746                                                         }
747                                                     }
748                                                 }
749
750                                             }
751
752                                             if (constObj == null) {
753
754                                                 // Last chance - see if
755                                                 // parameter class has a static
756                                                 // method
757                                                 // getDefaultInstance(String)
758                                                 try {
759                                                     Method gm =
760                                                             paramClass.getMethod("getDefaultInstance", String.class);
761
762                                                     int gmodifier = gm.getModifiers();
763                                                     if (Modifier.isStatic(gmodifier)) {
764                                                         // Invoke static
765                                                         // getDefaultInstance(String)
766                                                         paramObj = gm.invoke(null, paramValue);
767                                                     }
768
769                                                 } catch (Exception gme) {
770                                                     LOG.info("Unable to find static method getDefaultInstance for "
771                                                             + "class {}", paramClass.getSimpleName(), gme);
772                                                 }
773                                             }
774
775                                         } catch (Exception e1) {
776                                             LOG.warn(
777                                                     "Could not find a suitable constructor for " + paramClass.getName(),
778                                                     e1);
779                                         }
780
781                                         if (constObj == null) {
782                                             LOG.warn("Could not find builder class " + builderName
783                                                     + " and could not find a String or Long constructor or static "
784                                                     + "getDefaultInstance(String) - trying just to set passing paramValue");
785
786                                         }
787                                     }
788                                 } catch (Exception e) {
789                                     LOG.error("Caught exception trying to create builder " + builderName, e);
790                                 }
791
792                                 if (paramObj != null && builderClass != null) {
793
794                                     try {
795                                         Method buildMethod = builderClass.getMethod("build");
796
797                                         Object builtObj = buildMethod.invoke(paramObj);
798
799                                         boolean isAccessible = m.isAccessible();
800                                         if (!isAccessible) {
801                                             m.setAccessible(true);
802                                         }
803
804                                         m.invoke(toObj, builtObj);
805                                         if (!isAccessible) {
806                                             m.setAccessible(isAccessible);
807                                         }
808                                         foundValue = true;
809
810                                     } catch (Exception e) {
811                                         LOG.error("Caught exception trying to set Yang-generated class expected by"
812                                                 + toClass.getName() + "." + m.getName() + "() from Properties entry",
813                                                 e);
814                                     }
815                                 } else {
816                                     try {
817                                         boolean isAccessible = m.isAccessible();
818                                         if (!isAccessible) {
819                                             m.setAccessible(true);
820                                         }
821
822                                         if (constObj != null) {
823                                             m.invoke(toObj, constObj);
824                                         } else {
825                                             m.invoke(toObj, paramValue);
826                                         }
827                                         if (!isAccessible) {
828                                             m.setAccessible(isAccessible);
829                                         }
830                                         foundValue = true;
831
832                                     } catch (Exception e) {
833                                         LOG.error("Caught exception trying to convert value returned by"
834                                                 + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
835                                     }
836                                 }
837                             }
838                         }
839                     } else {
840
841                         // Setter's argument is not a yang-generated class. See
842                         // if it is a List.
843
844                         if (List.class.isAssignableFrom(paramClass)) {
845                             // Figure out what type of args are in List and pass
846                             // that to toList().
847
848                             Type paramType = m.getGenericParameterTypes()[0];
849                             Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
850                             Object paramObj = new LinkedList();
851                             try {
852                                 paramObj = toList(props, propName, (List) paramObj, (Class) elementType);
853                             } catch (Exception e) {
854                                 LOG.error("Caught exception trying to create list expected as argument to {}.{}",
855                                         toClass.getName(), m.getName(), e);
856                             }
857
858                             if (paramObj != null) {
859                                 try {
860                                     boolean isAccessible = m.isAccessible();
861                                     if (!isAccessible) {
862                                         m.setAccessible(true);
863                                     }
864                                     m.invoke(toObj, paramObj);
865                                     if (!isAccessible) {
866                                         m.setAccessible(isAccessible);
867                                     }
868                                     foundValue = true;
869
870                                 } catch (Exception e) {
871                                     LOG.error("Caught exception trying to convert List returned by" + toClass.getName()
872                                             + "." + m.getName() + "() to Properties entry", e);
873                                 }
874                             }
875                         } else {
876
877                             // Setter expects something that is not a List and
878                             // not yang-generated. Just pass the parameter value
879                             if ((paramValue != null) && (paramValue.length() > 0)) {
880
881                                 Object constObj = null;
882
883                                 try {
884                                     // See if I can find a constructor I can use
885                                     Constructor[] constructors = paramClass.getConstructors();
886                                     // Is there a String constructor?
887                                     for (Constructor c : constructors) {
888                                         Class[] cParms = c.getParameterTypes();
889                                         if ((cParms != null) && (cParms.length == 1)) {
890                                             if (String.class.isAssignableFrom(cParms[0])) {
891                                                 constObj = c.newInstance(paramValue);
892                                             }
893                                         }
894                                     }
895
896                                     if (constObj == null) {
897                                         // Is there a Long constructor?
898                                         for (Constructor c : constructors) {
899                                             Class[] cParms = c.getParameterTypes();
900                                             if ((cParms != null) && (cParms.length == 1)) {
901                                                 if (Long.class.isAssignableFrom(cParms[0])) {
902                                                     constObj = c.newInstance(Long.parseLong(paramValue));
903                                                 }
904                                             }
905                                         }
906
907                                     }
908
909                                     if (constObj != null) {
910                                         try {
911                                             m.invoke(toObj, constObj);
912                                             foundValue = true;
913                                         } catch (Exception e2) {
914                                             LOG.error("Caught exception trying to call " + m.getName(), e2);
915                                         }
916                                     } else {
917                                         try {
918                                             boolean isAccessible = m.isAccessible();
919                                             if (!isAccessible) {
920                                                 m.setAccessible(true);
921                                             }
922                                             m.invoke(toObj, paramValue);
923                                             if (!isAccessible) {
924                                                 m.setAccessible(isAccessible);
925                                             }
926                                             foundValue = true;
927
928                                         } catch (Exception e) {
929                                             LOG.error("Caught exception trying to convert value returned by"
930                                                     + toClass.getName() + "." + m.getName() + "() to Properties entry",
931                                                     e);
932                                         }
933                                     }
934                                 } catch (Exception e1) {
935                                     LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
936                                 }
937
938                             }
939                         }
940                     }
941                 } // End of section handling "setter" method
942             } // End of loop through Methods
943         } // End of section handling yang-generated class
944
945         if (foundValue) {
946             return (toObj);
947         } else {
948             return (null);
949         }
950     }
951
952     private static boolean classHasSpecialHandling(String simpleName) {
953         if (IP_ADDRESS.equals(simpleName) || IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
954                 || IP_PREFIX.equals(simpleName) || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) {
955             return true;
956         }
957         return false;
958     }
959     
960     private static String getStringValueMethod(String simpleName){
961         if (IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)) {
962                 return("stringValue");
963         } else {
964                 return("getValue");
965         }
966     }
967
968     public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) {
969         boolean foundValue = false;
970
971         if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) {
972             // Class is yang generated.
973             String propNamePfx = null;
974             if (pfx.endsWith("]")) {
975                 propNamePfx = pfx;
976             } else {
977
978                 if ((pfx != null) && (pfx.length() > 0)) {
979                     propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
980                 } else {
981                     propNamePfx = toLowerHyphen(toClass.getSimpleName());
982                 }
983
984                 if (propNamePfx.endsWith(BUILDER)) {
985                     propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
986                 }
987
988                 if (propNamePfx.endsWith("-impl")) {
989                     propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
990                 }
991             }
992
993             // Iterate through getter methods to figure out values we need to
994             // set
995
996             for (Method m : toClass.getMethods()) {
997                 if (isGetter(m)) {
998                     Class returnClass = m.getReturnType();
999
1000                     String fieldName = toLowerHyphen(m.getName().substring(3));
1001                     if (fieldName != null) {
1002                         fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
1003                     } else {
1004                         fieldName = "";
1005                     }
1006                     String propName = propNamePfx + "." + fieldName;
1007
1008                     // Is the return type a yang generated class?
1009                     if (isYangGenerated(returnClass)) {
1010                         // Is it an enum?
1011                         if (returnClass.isEnum()) {
1012                             pstr.print("\n\n     * " + propName);
1013                         } else {
1014
1015                             String simpleName = returnClass.getSimpleName();
1016
1017                             if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
1018                                     || IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)
1019                                     || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) {
1020                                 pstr.print("\n\n     * " + propName);
1021                             } else {
1022                                 printPropertyList(pstr, propNamePfx, returnClass);
1023                             }
1024
1025                         }
1026                     } else {
1027
1028                         // Setter's argument is not a yang-generated class. See
1029                         // if it is a List.
1030
1031                         if (List.class.isAssignableFrom(returnClass)) {
1032                             // Figure out what type of args are in List and pass
1033                             // that to toList().
1034
1035                             Type returnType = m.getGenericReturnType();
1036                             Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
1037                             Class elementClass = (Class) elementType;
1038                             printPropertyList(pstr,
1039                                     propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]",
1040                                     elementClass);
1041
1042                         } else if (!returnClass.equals(Class.class)) {
1043
1044                             // Setter expects something that is not a List and
1045                             // not yang-generated. Just pass the parameter value
1046                             pstr.print("\n\n     * " + propName);
1047                         }
1048                     }
1049                 } // End of section handling "setter" method
1050             } // End of loop through Methods
1051         } // End of section handling yang-generated class
1052
1053     }
1054
1055     public static boolean isYangGenerated(Class c) {
1056         if (c != null) {
1057             return (c.getName().startsWith("org.opendaylight.yang.gen."));
1058         }
1059         return false;
1060     }
1061
1062     public static boolean isIpPrefix(Class c) {
1063
1064         if (c == null) {
1065             return (false);
1066         }
1067         if (!isIetfInet(c)) {
1068             return (false);
1069         }
1070         String simpleName = c.getSimpleName();
1071         return (IP_PREFIX.equals(simpleName));
1072     }
1073
1074     public static boolean isIpv4Address(Class c) {
1075
1076         if (c == null) {
1077             return (false);
1078         }
1079         if (!isIetfInet(c)) {
1080             return (false);
1081         }
1082         String simpleName = c.getSimpleName();
1083         return (IPV4_ADDRESS.equals(simpleName));
1084     }
1085
1086     public static boolean isIpv6Address(Class c) {
1087
1088         if (c == null) {
1089             return (false);
1090         }
1091         if (!isIetfInet(c)) {
1092             return (false);
1093         }
1094         String simpleName = c.getSimpleName();
1095         return (IPV6_ADDRESS.equals(simpleName));
1096     }
1097
1098     public static boolean isIpAddress(Class c) {
1099
1100         if (c == null) {
1101             return (false);
1102         }
1103         if (!isIetfInet(c)) {
1104             return (false);
1105         }
1106         String simpleName = c.getSimpleName();
1107         return (IP_ADDRESS.equals(simpleName));
1108     }
1109
1110     public static boolean isPortNumber(Class c) {
1111
1112         if (c == null) {
1113             return (false);
1114         }
1115         if (!isIetfInet(c)) {
1116             return (false);
1117         }
1118
1119         String simpleName = c.getSimpleName();
1120         return ("PortNumber".equals(simpleName));
1121     }
1122
1123     public static boolean isDscp(Class c) {
1124
1125         if (c == null) {
1126             return (false);
1127         }
1128         if (!isIetfInet(c)) {
1129             return (false);
1130         }
1131         String simpleName = c.getSimpleName();
1132         return ("Dscp".equals(simpleName));
1133     }
1134
1135     public static boolean isIetfInet(Class c) {
1136
1137         Package p = c.getPackage();
1138         if (p != null) {
1139             String pkgName = p.getName();
1140
1141             if ((pkgName != null) && (pkgName.indexOf("yang.ietf.inet.types") > -1)) {
1142                 return (true);
1143             }
1144         }
1145
1146         return (false);
1147     }
1148
1149     public static String toLowerHyphen(String inStr) {
1150         if (inStr == null) {
1151             return (null);
1152         }
1153
1154         String str = inStr.substring(0, 1).toLowerCase();
1155         if (inStr.length() > 1) {
1156             str = str + inStr.substring(1);
1157         }
1158
1159         String regex = "(([a-z0-9])([A-Z]))";
1160         String replacement = "$2-$3";
1161
1162         String retval = str.replaceAll(regex, replacement).toLowerCase();
1163
1164         return (retval);
1165     }
1166
1167     // This is called when mapping the yang value back to a valid java enumeration
1168     public static String toJavaEnum(String inStr) {
1169         if (inStr == null) {
1170             return (null);
1171         } else if (inStr.length() == 0) {
1172             return (inStr);
1173         }
1174
1175         // This is needed for enums containing under scores
1176         inStr = inStr.replaceAll("_", "");
1177
1178         // This will strip out all periods, which cannot be in a java enum
1179         inStr = inStr.replaceAll("\\.", "");
1180
1181         // This is needed for enums containing spaces
1182         inStr = inStr.replaceAll(" ", "");
1183
1184         String[] terms = inStr.split("-");
1185         StringBuffer sbuff = new StringBuffer();
1186
1187         // appends an _ if the string starts with a digit to make it a valid java enum
1188         if (Character.isDigit(inStr.charAt(0))) {
1189             sbuff.append('_');
1190         }
1191         // If the string contains hyphens it will convert the string to upperCamelCase without hyphens
1192         for (String term : terms) {
1193             sbuff.append(term.substring(0, 1).toUpperCase());
1194             if (term.length() > 1) {
1195                 sbuff.append(term.substring(1));
1196             }
1197         }
1198         return (sbuff.toString());
1199
1200     }
1201
1202     public static boolean isGetter(Method m) {
1203         if (m == null) {
1204             return (false);
1205         }
1206
1207         if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) {
1208             if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) {
1209                 if (!"getClass".equals(m.getName())) {
1210                     return (true);
1211                 }
1212             }
1213
1214             if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) {
1215                 return (true);
1216             }
1217
1218             if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) {
1219                 return (true);
1220             }
1221         }
1222
1223         return (false);
1224     }
1225
1226     public static boolean isSetter(Method m) {
1227         if (m == null) {
1228             return (false);
1229         }
1230
1231         if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) {
1232             if (m.getName().matches("^set[A-Z].*")) {
1233                 Class[] paramTypes = m.getParameterTypes();
1234                 if (paramTypes[0].isAssignableFrom(Identifier.class)
1235                         || Identifier.class.isAssignableFrom(paramTypes[0])) {
1236                     return (false);
1237                 } else {
1238                     return (true);
1239                 }
1240             }
1241
1242         }
1243
1244         return (false);
1245     }
1246
1247     @Deprecated
1248     public static String getFullPropertiesPath(String propertiesFileName) {
1249         String karafHome = System.getProperty("karaf.home","/opt/lsc/controller");
1250         return karafHome + "/configuration/" + propertiesFileName;
1251     }
1252
1253     // This is called when mapping a valid java enumeration back to the yang model value
1254     @Deprecated
1255     public static String mapEnumeratedValue(String propertyName, String propertyValue) {
1256         LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue);
1257         String mappingKey = "yang." + propertyName + "." + propertyValue;
1258         if (yangMappingProperties.containsKey(mappingKey)) {
1259             return (yangMappingProperties.getProperty(mappingKey));
1260         } else {
1261             LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value.");
1262             return propertyValue;
1263         }
1264     }
1265
1266 }