Initial add of APPC client libraries
[appc.git] / appc-client / client-simulator / src / main / java / org / openecomp / appc / simulator / client / impl / JsonRequestHandler.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.openecomp.appc.simulator.client.impl;
26
27 import org.openecomp.appc.client.lcm.api.*;
28 import org.openecomp.appc.client.lcm.exceptions.*;
29 import org.openecomp.appc.simulator.client.RequestHandler;
30
31 import com.att.eelf.configuration.EELFLogger;
32 import com.att.eelf.configuration.EELFManager;
33 import com.fasterxml.jackson.databind.JsonNode;
34 import com.fasterxml.jackson.databind.ObjectMapper;
35 import com.fasterxml.jackson.databind.node.ObjectNode;
36
37 import java.io.*;
38 import java.lang.reflect.Method;
39 import java.util.HashMap;
40 import java.util.Properties;
41
42 public class JsonRequestHandler implements RequestHandler {
43
44     private enum modeT {
45         SYNCH,
46         ASYNCH
47     }
48
49     public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
50     private String rpcName = null;
51     private String inputClassName = null;
52     private String actionName = null;
53     private String methodName = null;
54     String packageName = null;
55     private LifeCycleManagerStateful service = null;
56     private Properties properties;
57     HashMap<String, String> exceptRpcMap = null;
58     private final EELFLogger LOG = EELFManager.getInstance().getLogger(JsonRequestHandler.class);
59     private AppcLifeCycleManagerServiceFactory appcLifeCycleManagerServiceFactory = null;
60
61
62     public JsonRequestHandler(Properties prop) throws AppcClientException {
63         properties = prop;
64         packageName = properties.getProperty("ctx.model.package") + ".";
65         try {
66             service = createService();
67         } catch (AppcClientException e) {
68             e.printStackTrace();
69         }
70         exceptRpcMap = prepareExceptionsMap();
71     }
72
73     private HashMap<String,String> prepareExceptionsMap() {
74         exceptRpcMap = new HashMap<String, String>();
75
76         String line;
77         BufferedReader reader = null;
78         try {
79             reader = new BufferedReader(new FileReader(properties.getProperty("client.rpc.exceptions.map.file")));
80         } catch (FileNotFoundException e) {
81             return exceptRpcMap;
82         }
83
84         try {
85             while ((line = reader.readLine()) != null)
86             {
87                 String[] parts = line.split(":", 2);
88                 if (parts.length >= 2)
89                 {
90                     String key = parts[0];
91                     String value = parts[1];
92                     exceptRpcMap.put(key, value);
93                 } else {
94                     System.out.println("ignoring line: " + line);
95                 }
96             }
97         } catch (IOException e) {
98             e.printStackTrace();
99         }
100
101         try {
102             reader.close();
103         } catch (IOException e) {
104             e.printStackTrace();
105         }
106         return exceptRpcMap;
107     }
108
109     @Override
110     public void proceedFile(File source, File log) throws IOException {
111         final JsonNode inputNode = OBJECT_MAPPER.readTree(source);
112
113         try {
114             // proceed with inputNode and get some xxxInput object, depends on action
115             prepareNames(inputNode);
116
117             Object input = prepareObject(inputNode);
118
119             JsonResponseHandler response = new JsonResponseHandler();
120             response.setFile(source.getPath().toString());
121             switch (isSyncMode(inputNode)) {
122                 case SYNCH: {
123                     LOG.debug("Received input request will be processed in synchronously mode");
124                     Method rpc = LifeCycleManagerStateful.class.getDeclaredMethod(methodName, input.getClass());
125                     response.onResponse(rpc.invoke(service, input));
126                     break;
127                 }
128                 case ASYNCH: {
129                     LOG.debug("Received input request will be processed in asynchronously mode");
130                     Method rpc = LifeCycleManagerStateful.class.getDeclaredMethod(methodName, input.getClass(), ResponseHandler.class);
131                     rpc.invoke(service, input, response);
132                     break;
133                 }
134                 default: {
135                     throw new RuntimeException("Unrecognized request mode");
136                 }
137             }
138         }
139         catch(Exception ex){
140             //ex.printStackTrace();
141         }
142
143         LOG.debug("Action <" + actionName + "> from input file <" + source.getPath().toString() + "> processed");
144     }
145
146     private modeT isSyncMode(JsonNode inputNode) {
147         // The following solution is for testing purposes only
148         // the sync/async decision logic may change upon request
149         try {
150             int mode = Integer.parseInt(inputNode.findValue("input").findValue("common-header").findValue("sub-request-id").asText());
151             if ((mode % 2) == 0) {
152                 return modeT.SYNCH;
153             }
154         }catch (Throwable ex) {
155             //use ASYNC as default, if value is not integer.
156         }
157         return modeT.ASYNCH;
158     }
159
160     private LifeCycleManagerStateful createService() throws AppcClientException {
161         appcLifeCycleManagerServiceFactory = AppcClientServiceFactoryProvider.getFactory(AppcLifeCycleManagerServiceFactory.class);
162         return appcLifeCycleManagerServiceFactory.createLifeCycleManagerStateful(new ApplicationContext(), properties);
163     }
164
165     public void shutdown(boolean isForceShutdown){
166         appcLifeCycleManagerServiceFactory.shutdownLifeCycleManager(isForceShutdown);
167     }
168
169     public Object prepareObject(JsonNode input) {
170         try {
171             Class cls = Class.forName(inputClassName);
172             try {
173                 // since payload is not mandatory field and not all actions contains payload
174                 // so we have to check that during input parsing
175                 alignPayload(input);
176             } catch (NoSuchFieldException e) {
177                 LOG.debug("In " + actionName + " no payload defined");
178             }
179
180             return OBJECT_MAPPER.treeToValue(input.get("input"), cls);
181         }
182         catch(Exception ex){
183             //ex.printStackTrace();
184         }
185         return null;
186     }
187
188     private void prepareNames(JsonNode input) throws NoSuchFieldException {
189         JsonNode inputNode = input.findValue("input");
190         actionName = inputNode.findValue("action").asText();
191         if (actionName.isEmpty()) {
192             throw new NoSuchFieldException("Input doesn't contains field <action>");
193         }
194
195         rpcName = prepareRpcFromAction(actionName);
196         inputClassName = packageName + actionName + "Input";
197         methodName = prepareMethodName(rpcName);
198     }
199
200     private void alignPayload(JsonNode input) throws NoSuchFieldException {
201         JsonNode inputNode = input.findValue("input");
202         JsonNode payload = inputNode.findValue("payload");
203         if (payload == null || payload.asText().isEmpty() || payload.toString().isEmpty())
204             throw new NoSuchFieldException("Input doesn't contains field <payload>");
205
206         String payloadData = payload.asText();
207         if (payloadData.isEmpty())
208             payloadData = payload.toString();
209         ((ObjectNode)inputNode).put("payload", payloadData);
210     }
211
212     private String prepareRpcFromAction(String action) {
213         String rpc = checkExceptionalRpcList(action);
214         if (rpc!= null && !rpc.isEmpty()) {
215             return rpc; // we found exceptional rpc, so no need to format it
216         }
217
218         rpc = "";
219         boolean makeItLowerCase = true;
220         for(int i = 0; i < action.length(); i++)
221         {
222             if(makeItLowerCase) // first character will make lower case
223             {
224                 rpc+=Character.toLowerCase(action.charAt(i));
225                 makeItLowerCase = false;
226             }
227             else  if((i+1 < action.length()) && Character.isUpperCase(action.charAt(i+1)))
228             {
229                 rpc+=action.charAt(i) + "-";
230                 makeItLowerCase = true;
231             }
232             else
233             {
234                 rpc+=action.charAt(i);
235                 makeItLowerCase = false;
236             }
237         }
238         return rpc;
239     }
240
241     private String checkExceptionalRpcList(String action) {
242         if (exceptRpcMap.isEmpty()) {
243             return null;
244         }
245         return exceptRpcMap.get(action);
246     }
247
248     private String prepareMethodName(String inputRpcName) {
249         boolean makeItUpperCase = false;
250         String method = "";
251
252         for(int i = 0; i < inputRpcName.length(); i++)  //to check the characters of string..
253         {
254             if(Character.isLowerCase(inputRpcName.charAt(i)) && makeItUpperCase) // skip first character if it lower case
255             {
256                 method+=Character.toUpperCase(inputRpcName.charAt(i));
257                 makeItUpperCase = false;
258             }
259             else  if(inputRpcName.charAt(i) == '-')
260             {
261                 makeItUpperCase = true;
262             }
263             else
264             {
265                 method+=inputRpcName.charAt(i);
266                 makeItUpperCase = false;
267             }
268         }
269         return method;
270     }
271
272 }