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