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