b94a6b68ee33f77cf83d1b8142eee01708d2091a
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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.so.adapters.appc.orchestrator.client;
22
23 import java.beans.BeanInfo;
24 import java.beans.IntrospectionException;
25 import java.beans.Introspector;
26 import java.beans.PropertyDescriptor;
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 import org.onap.appc.client.lcm.api.LifeCycleManagerStateful;
30 import org.onap.appc.client.lcm.api.ResponseHandler;
31 import org.onap.appc.client.lcm.exceptions.AppcClientException;
32 import org.onap.appc.client.lcm.model.Status;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.springframework.stereotype.Component;
36 import com.fasterxml.jackson.annotation.JsonInclude.Include;
37 import com.fasterxml.jackson.core.JsonProcessingException;
38 import com.fasterxml.jackson.databind.ObjectMapper;
39 import com.fasterxml.jackson.databind.ObjectWriter;
40 import com.fasterxml.jackson.databind.SerializationFeature;
41
42
43 @Component
44 public class ApplicationControllerSupport {
45
46     private static final int ACCEPT_SERIES = 100;
47     private static final int ERROR_SERIES = 200;
48     private static final int REJECT_SERIES = 300;
49     private static final int SUCCESS_SERIES = 400;
50     private static final int SUCCESS_STATUS = SUCCESS_SERIES;
51     private static final int PARTIAL_SERIES = 500;
52     private static final int PARTIAL_SUCCESS_STATUS = PARTIAL_SERIES;
53     private static final int PARTIAL_FAILURE_STATUS = PARTIAL_SERIES + 1;
54
55     private static Logger logger = LoggerFactory.getLogger(ApplicationControllerSupport.class);
56     private static final ObjectMapper objectMapper;
57     private static final ObjectWriter writer;
58     private String lcmModelPackage = "org.onap.appc.client.lcm.model";
59
60     static {
61         objectMapper = new ObjectMapper();
62         objectMapper.setSerializationInclusion(Include.NON_NULL);
63         writer = objectMapper.writerWithDefaultPrettyPrinter();
64     }
65
66     /**
67      * @param action
68      * @return
69      * @throws ClassNotFoundException
70      * @throws InstantiationException
71      * @throws IllegalAccessException
72      */
73     public Object getInput(String action) {
74         try {
75             return getInputClass(action).newInstance();
76         } catch (IllegalAccessException | InstantiationException e) {
77             throw new RuntimeException(
78                     String.format("%s : %s", "Unable to instantiate viable LCM Kit input class for action", action), e);
79         }
80     }
81
82     /**
83      * @param action
84      * @return
85      * @throws ClassNotFoundException
86      */
87     public Method getAPIMethod(String action, LifeCycleManagerStateful lcmStateful, boolean async) {
88         Method[] methods = lcmStateful.getClass().getMethods();
89         for (Method method : methods) {
90             if (method.getName().equalsIgnoreCase(action)) {
91                 Class<?>[] methodParameterTypes = method.getParameterTypes();
92                 if (methodParameterTypes.length > 0) {
93                     if (getInputClass(action).equals(methodParameterTypes[0])) {
94                         if (async) {
95                             if (methodParameterTypes.length == 2
96                                     && ResponseHandler.class.isAssignableFrom(methodParameterTypes[1])) {
97                                 return method;
98                             }
99                         } else if (methodParameterTypes.length == 1) {
100                             return method;
101                         }
102                     }
103                 }
104             }
105         }
106         throw new RuntimeException(String.format("%s : %s, async=%b",
107                 "Unable to derive viable LCM Kit API method for action", action, async));
108     }
109
110     public Status getStatusFromGenericResponse(Object response) {
111         Method statusReader = getBeanPropertyMethodFor(response.getClass(), "status", false);
112         if (statusReader != null) {
113             try {
114                 return (Status) statusReader.invoke(response);
115             } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
116                 logger.error("Unable to obtain status from LCM Kit response", e);
117             }
118         }
119         return new Status();
120     }
121
122     public StatusCategory getCategoryOf(Status status) {
123         int codeSeries = status.getCode() - (status.getCode() % 100);
124         switch (codeSeries) {
125             case ACCEPT_SERIES:
126                 return StatusCategory.NORMAL;
127             case ERROR_SERIES:
128             case REJECT_SERIES:
129                 return StatusCategory.ERROR;
130             case SUCCESS_SERIES:
131                 return status.getCode() == SUCCESS_STATUS ? StatusCategory.NORMAL : StatusCategory.ERROR;
132             case PARTIAL_SERIES:
133                 switch (status.getCode()) {
134                     case PARTIAL_SUCCESS_STATUS:
135                         return StatusCategory.NORMAL;
136                     case PARTIAL_FAILURE_STATUS:
137                         return StatusCategory.ERROR;
138                     default:
139                         return StatusCategory.WARNING;
140                 }
141             default:
142                 return StatusCategory.WARNING;
143         }
144     }
145
146     public boolean getFinalityOf(Status status) {
147         int codeSeries = status.getCode() - (status.getCode() % 100);
148         switch (codeSeries) {
149             case ACCEPT_SERIES:
150             case PARTIAL_SERIES:
151                 return false;
152             case ERROR_SERIES:
153             case REJECT_SERIES:
154             case SUCCESS_SERIES:
155                 return true;
156             default:
157                 return true;
158         }
159     }
160
161     private Method getBeanPropertyMethodFor(Class<?> clazz, String propertyName, boolean isWriter) {
162         BeanInfo beanInfo;
163         try {
164             beanInfo = Introspector.getBeanInfo(clazz, Object.class);
165         } catch (IntrospectionException e) {
166             throw new RuntimeException(
167                     String.format("Unable to produce bean property method for class : %s, property : %s, writer=%b",
168                             clazz.getName(), propertyName, isWriter),
169                     e);
170         }
171         PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
172         for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
173             if (propertyDescriptor.getName().equals(propertyName)) {
174                 return isWriter ? propertyDescriptor.getWriteMethod() : propertyDescriptor.getReadMethod();
175             }
176         }
177         throw new RuntimeException(
178                 String.format("Unable to produce bean property method for class : %s, property : %s, writer=%b",
179                         clazz.getName(), propertyName, isWriter));
180     }
181
182     /**
183      * @param action
184      * @return
185      * @throws ClassNotFoundException
186      */
187     private Class<?> getInputClass(String action) {
188         try {
189             return Class.forName(lcmModelPackage + '.' + action + "Input");
190         } catch (ClassNotFoundException e) {
191             throw new RuntimeException(String.format("%s : %s using package : %s",
192                     "Unable to identify viable LCM Kit input class for action", action, lcmModelPackage), e);
193         }
194     }
195
196
197     public void logLCMMessage(Object message) {
198         String inputAsJSON;
199         try {
200             inputAsJSON = writer.writeValueAsString(message);
201             logger.info("LCM Kit input message follows: {}", inputAsJSON);
202         } catch (JsonProcessingException e) {
203             logger.error("Error in logging LCM Message", e);
204         }
205     }
206
207     public Status buildStatusFromAppcException(AppcClientException exception) {
208         Status exceptionStatus = new Status();
209         exceptionStatus.setCode(200);
210         exceptionStatus.setMessage("Exception on APPC request: " + exception.getMessage());
211         return exceptionStatus;
212     }
213 }