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