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