37d7aa4ad0401f0d280d8352be0cab3550f83d0a
[ccsdk/features.git] /
1 /*******************************************************************************
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.yangtools;
19
20 import java.lang.reflect.Field;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26
27 import javax.annotation.Nullable;
28
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class YangToolsCloner2 {
33
34         private static final Logger LOG = LoggerFactory.getLogger(YangToolsCloner2.class);
35
36     public enum Accessor {
37         ACCESSOR_FIELD,
38         ACCESSOR_METHOD;
39     }
40
41         private Accessor accessor;
42
43         public YangToolsCloner2() {
44                 LOG.info("Provide new {}",this.getClass().getName());
45                 this.accessor = Accessor.ACCESSOR_METHOD;
46         }
47
48         YangToolsCloner2 setAcessor(Accessor accessor) {
49                 this.accessor = accessor;
50                 return this;
51         }
52
53         Accessor getAccessor() {
54                 return accessor;
55         }
56
57         public interface Builder<T> {
58                 T build();
59         }
60
61         /**
62          *
63          * @param source source object
64          * @param clazz Class of return object
65          * @attrList filter for attribute Names to clone
66          * @return list of cloned object
67          * @throws Exception
68          */
69         public <S, T> List<T> cloneList(List<S> source, Builder<T> builder, String ... attrList) throws Exception {
70                 if (source == null) {
71                         return null;
72                 }
73                 List<T> list = new ArrayList<T>();
74                 for (S s : source) {
75                         list.add(copyAttributes(s, builder.build(), attrList));
76                 }
77                 return list;
78         }
79
80         /**
81          * Copy attributes from source to destination object.
82          * Copy the references.
83          * @param source source object
84          * @param clazz Class of return object
85          * @attrList attribute Names NOT to clone.
86          * @return cloned object
87          * @throws Exception
88          */
89         @SuppressWarnings("null")
90         public @Nullable <S, T> T copyAttributes(S source, T destination, String ... attributeArray) throws Exception {
91
92                 LOG.debug("copyAttributes source.class {} destination.class {} attributes {}", source, destination, attributeArray.length);
93
94                 if (destination == null || source == null)
95                         return null;
96
97                 List<String> attributeList = Arrays.asList(attributeArray);
98                 LOG.debug("copyAttributes 2 attributes {}", attributeList);
99
100                 Field[] destinationAttributeFields = source.getClass().getDeclaredFields();
101                 String destinationName;
102                 Class<?> destinationType;
103                 for (Field destinationAttributeField : destinationAttributeFields) {
104                         destinationName = destinationAttributeField.getName();
105                         destinationType = destinationAttributeField.getType();
106                         LOG.debug("Field: {}", destinationName);
107                         // check if attr is in exclusion list
108                         if (attributeList.contains(destinationName)) {
109                                 continue;
110                         }
111                         // ignore QNAME
112                         if (destinationName.equals("QNAME")) {
113                                 continue;
114                         }
115
116                         destinationAttributeField.setAccessible(true);
117                         Object sourceData = null;
118                         Class<?> sourceType = null;
119                         Class<?> sourceListType = null;
120                         try {
121                                 if (accessor == Accessor.ACCESSOR_FIELD) {
122                                         Field sourceField;
123                                         sourceField = source.getClass().getDeclaredField(destinationName);
124                                         sourceField.setAccessible(true);
125                                         sourceType = sourceField.getType();
126                                         sourceData = sourceField.get(source);
127                                         sourceListType = getListClass(sourceType, sourceData);
128
129                                 } else if (accessor == Accessor.ACCESSOR_METHOD) {
130                                         Method sourceMethod;
131                                         sourceMethod = source.getClass().getDeclaredMethod(getter(destinationName));
132                                         sourceMethod.setAccessible(true);
133                                         sourceType = sourceMethod.getReturnType();
134                                         sourceData = sourceMethod.invoke(source);
135                                         sourceListType = getListClass(sourceType, sourceData);
136                                 }
137                                 LOG.info("Handle {} {} {}", destinationName, destinationType, sourceType);
138                                 if (destinationType == sourceType) {
139                                         destinationAttributeField.set(destination, sourceData);
140                                 } else {
141                                         throw new Exception(
142                                                         "Problem to copy attribute " + destinationName
143                                                         +" Sourceclass:" +sourceType
144                                                         +" Destinationclass:" + destinationType
145                                                         +" Method:"+accessor.name());
146                                 }
147                         } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
148                                         | NoSuchMethodException | InvocationTargetException e) {
149                                 throw e;
150                         }
151                 }
152                 return destination;
153
154         }
155
156         private static String getter(String name) {
157                 if (name == null || name.length() == 0) {
158                         return null;
159                 } else if (name.length() == 1) {
160                         return String.format("%s%s", "get", name.substring(1, 2).toUpperCase());
161                 } else { // >= 2
162                         return String.format("%s%s%s", "get", name.substring(1, 2).toUpperCase(), name.substring(2));
163                 }
164         }
165
166         private static Class<?> getListClass(Class<?> sourceType, Object sourceData) {
167                 if (sourceData != null && sourceType.equals(List.class)) {
168                         List<Object> sourceDataList = (List<Object>)sourceData;
169                         if (sourceDataList.size() > 0) {
170                                 LOG.info("Is list with type"+sourceDataList.get(0).getClass().getName());
171                         } else {
172                                 LOG.info("Is empty list");
173                         }
174                 }
175             return(sourceType);
176         }
177
178 }