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