Replace ecomp references
[portal.git] / ecomp-portal-BE-common / src / main / java / org / onap / portalapp / portal / controller / SharedContextRestController.java
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software 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  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * 
37  */
38 package org.onap.portalapp.portal.controller;
39
40 import java.io.IOException;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45
46 import javax.servlet.http.HttpServletRequest;
47 import javax.servlet.http.HttpServletResponse;
48
49 import org.onap.portalapp.controller.EPRestrictedRESTfulBaseController;
50 import org.onap.portalapp.portal.domain.SharedContext;
51 import org.onap.portalapp.portal.logging.aop.EPAuditLog;
52 import org.onap.portalapp.portal.service.SharedContextService;
53 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
54 import org.onap.portalapp.portal.utils.PortalConstants;
55 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
56 import org.springframework.beans.factory.annotation.Autowired;
57 import org.springframework.context.annotation.Configuration;
58 import org.springframework.context.annotation.EnableAspectJAutoProxy;
59 import org.springframework.http.HttpStatus;
60 import org.springframework.web.bind.annotation.ExceptionHandler;
61 import org.springframework.web.bind.annotation.RequestBody;
62 import org.springframework.web.bind.annotation.RequestMapping;
63 import org.springframework.web.bind.annotation.RequestMethod;
64 import org.springframework.web.bind.annotation.RequestParam;
65 import org.springframework.web.bind.annotation.RestController;
66
67 import com.fasterxml.jackson.core.JsonProcessingException;
68 import com.fasterxml.jackson.databind.ObjectMapper;
69
70 import io.swagger.annotations.ApiOperation;
71
72 /**
73  * The shared-context feature allows onboarded applications to share data among
74  * themselves easily for a given session. It basically implements a Java map:
75  * put or get a key-value pair within a map identified by a session ID.
76  * 
77  * This REST endpoint listens on the Portal app server and answers requests made
78  * by back-end application servers. Reads and writes values to the database
79  * using a Hibernate service to ensure all servers in a high-availability
80  * cluster see the same data.
81  */
82 @Configuration
83 @RestController
84 @RequestMapping(PortalConstants.REST_AUX_API + "/context")
85 @EnableAspectJAutoProxy
86 @EPAuditLog
87 public class SharedContextRestController extends EPRestrictedRESTfulBaseController {
88
89         /**
90          * Model for a one-element JSON object returned by many methods.
91          */
92         class SharedContextJsonResponse {
93                 String response;
94         }
95
96         /**
97          * Access to the database
98          */
99         @Autowired
100         private SharedContextService contextService;
101
102         /**
103          * Logger for debug etc.
104          */
105         private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SharedContextRestController.class);
106
107         /**
108          * Reusable JSON (de)serializer
109          */
110         private final ObjectMapper mapper = new ObjectMapper();
111
112         /**
113          * Gets a value for the specified context and key (RESTful service method).
114          * 
115          * @param request
116          *            HTTP servlet request
117          * @param context_id
118          *            ID that identifies the context, usually the ONAP Portal
119          *            session key.
120          * @param ckey
121          *            Key for the key-value pair to fetch
122          * @return JSON with shared context object; response=null if not found.
123          * @throws Exception
124          *             on bad arguments
125          */
126         @ApiOperation(value = "Gets a value for the specified context and key.", response = SharedContext.class)
127         @RequestMapping(value = { "/get" }, method = RequestMethod.GET, produces = "application/json")
128         public String getContext(HttpServletRequest request, @RequestParam String context_id, @RequestParam String ckey)
129                         throws Exception {
130
131                 logger.debug(EELFLoggerDelegate.debugLogger, "getContext for ID " + context_id + ", key " + ckey);
132                 if (context_id == null || ckey == null)
133                         throw new Exception("Received null for context_id and/or ckey");
134
135                 SharedContext context = contextService.getSharedContext(context_id, ckey);
136                 String jsonResponse = "";
137                 if (context == null)
138                         jsonResponse = convertResponseToJSON(context);
139                 else
140                         jsonResponse = mapper.writeValueAsString(context);
141
142                 return jsonResponse;
143         }
144
145         /**
146          * Gets user information for the specified context (RESTful service method).
147          * 
148          * @param request
149          *            HTTP servlet request
150          * @param context_id
151          *            ID that identifies the context, usually the ONAP Portal
152          *            session key.
153          * @return List of shared-context objects as JSON; should have user's first
154          *         name, last name and email address; null if none found
155          * @throws Exception
156          *             on bad arguments
157          */
158         @ApiOperation(value = "Gets user information for the specified context.", response = SharedContext.class, responseContainer = "List")
159         @RequestMapping(value = { "/get_user" }, method = RequestMethod.GET, produces = "application/json")
160         public String getUserContext(HttpServletRequest request, @RequestParam String context_id) throws Exception {
161
162                 logger.debug(EELFLoggerDelegate.debugLogger, "getUserContext for ID " + context_id);
163                 if (context_id == null)
164                         throw new Exception("Received null for context_id");
165
166                 List<SharedContext> listSharedContext = new ArrayList<SharedContext>();
167                 SharedContext firstNameContext = contextService.getSharedContext(context_id,
168                                 EPCommonSystemProperties.USER_FIRST_NAME);
169                 SharedContext lastNameContext = contextService.getSharedContext(context_id,
170                                 EPCommonSystemProperties.USER_LAST_NAME);
171                 SharedContext emailContext = contextService.getSharedContext(context_id, EPCommonSystemProperties.USER_EMAIL);
172                 SharedContext orgUserIdContext = contextService.getSharedContext(context_id,
173                                 EPCommonSystemProperties.USER_ORG_USERID);
174                 if (firstNameContext != null)
175                         listSharedContext.add(firstNameContext);
176                 if (lastNameContext != null)
177                         listSharedContext.add(lastNameContext);
178                 if (emailContext != null)
179                         listSharedContext.add(emailContext);
180                 if (orgUserIdContext != null)
181                         listSharedContext.add(orgUserIdContext);
182                 String jsonResponse = convertResponseToJSON(listSharedContext);
183                 return jsonResponse;
184         }
185
186         /**
187          * Tests for presence of the specified key in the specified context (RESTful
188          * service method).
189          * 
190          * @param request
191          *            HTTP servlet request
192          * @param context_id
193          *            ID that identifies the context, usually the ONAP Portal
194          *            session key.
195          * @param ckey
196          *            Key for the key-value pair to test
197          * @return JSON with result indicating whether the context and key were
198          *         found.
199          * @throws Exception
200          *             on bad arguments
201          */
202         @ApiOperation(value = "Tests for presence of the specified key in the specified context.", response = SharedContextJsonResponse.class)
203         @RequestMapping(value = { "/check" }, method = RequestMethod.GET, produces = "application/json")
204         public String checkContext(HttpServletRequest request, @RequestParam String context_id, @RequestParam String ckey)
205                         throws Exception {
206
207                 logger.debug(EELFLoggerDelegate.debugLogger, "checkContext for " + context_id + ", key " + ckey);
208                 if (context_id == null || ckey == null)
209                         throw new Exception("Received null for contextId and/or key");
210
211                 String response = null;
212                 SharedContext context = contextService.getSharedContext(context_id, ckey);
213                 if (context != null)
214                         response = "exists";
215
216                 String jsonResponse = convertResponseToJSON(response);
217                 return jsonResponse;
218         }
219
220         /**
221          * Removes the specified key in the specified context (RESTful service
222          * method).
223          * 
224          * @param request
225          *            HTTP servlet request
226          * @param context_id
227          *            ID that identifies the context, usually the ONAP Portal
228          *            session key.
229          * @param ckey
230          *            Key for the key-value pair to remove
231          * @return JSON with result indicating whether the context and key were
232          *         found.
233          * @throws Exception
234          *             on bad arguments
235          */
236         @ApiOperation(value = "Removes the specified key in the specified context.", response = SharedContextJsonResponse.class)
237         @RequestMapping(value = { "/remove" }, method = RequestMethod.GET, produces = "application/json")
238         public String removeContext(HttpServletRequest request, @RequestParam String context_id, @RequestParam String ckey)
239                         throws Exception {
240
241                 logger.debug(EELFLoggerDelegate.debugLogger, "removeContext for " + context_id + ", key " + ckey);
242                 if (context_id == null || ckey == null)
243                         throw new Exception("Received null for contextId and/or key");
244
245                 SharedContext context = contextService.getSharedContext(context_id, ckey);
246                 String response = null;
247                 if (context != null) {
248                         contextService.deleteSharedContext(context);
249                         response = "removed";
250                 }
251
252                 String jsonResponse = convertResponseToJSON(response);
253                 return jsonResponse;
254         }
255
256         /**
257          * Clears all key-value pairs in the specified context (RESTful service
258          * method).
259          * 
260          * @param request
261          *            HTTP servlet request
262          * @param context_id
263          *            ID that identifies the context, usually the ONAP Portal
264          *            session key.
265          * @return JSON with result indicating the number of key-value pairs
266          *         removed.
267          * @throws Exception
268          *             on bad arguments
269          */
270         @ApiOperation(value = "Clears all key-value pairs in the specified context.", response = SharedContextJsonResponse.class)
271         @RequestMapping(value = { "/clear" }, method = RequestMethod.GET, produces = "application/json")
272         public String clearContext(HttpServletRequest request, @RequestParam String context_id) throws Exception {
273
274                 logger.debug(EELFLoggerDelegate.debugLogger, "clearContext for " + context_id);
275                 if (context_id == null)
276                         throw new Exception("clearContext: Received null for contextId");
277
278                 int count = contextService.deleteSharedContexts(context_id);
279                 String jsonResponse = convertResponseToJSON(Integer.toString(count));
280                 return jsonResponse;
281         }
282
283         /**
284          * Sets a context value for the specified context and key (RESTful service
285          * method). Creates the context if no context with the specified ID-key pair
286          * exists, overwrites the value if it exists already.
287          * 
288          * @param request
289          *            HTTP servlet request
290          * @param userJson
291          *            JSON block with these tag-value pairs:
292          *            <UL>
293          *            <LI>context_id: ID that identifies the context
294          *            <LI>ckey: Key for the key-value pair to store
295          *            <LI>cvalue: Value to store
296          *            </UL>
297          * @return JSON with result indicating whether the value was added (key not
298          *         previously known) or replaced (key previously known).
299          * @throws Exception
300          *             on bad arguments
301          */
302         @ApiOperation(value = "Sets a context value for the specified context and key. Creates the context if no context with the specified ID-key pair exists, overwrites the value if it exists already.", response = SharedContextJsonResponse.class)
303         @RequestMapping(value = { "/set" }, method = RequestMethod.POST, produces = "application/json")
304         public String setContext(HttpServletRequest request, @RequestBody String userJson) throws Exception {
305
306                 @SuppressWarnings("unchecked")
307                 Map<String, Object> userData = mapper.readValue(userJson, Map.class);
308                 // Use column names as JSON tags
309                 final String contextId = (String) userData.get("context_id");
310                 final String key = (String) userData.get("ckey");
311                 final String value = (String) userData.get("cvalue");
312                 if (contextId == null || key == null)
313                         throw new Exception("setContext: received null for contextId and/or key");
314
315                 logger.debug(EELFLoggerDelegate.debugLogger, "setContext: ID " + contextId + ", key " + key + "->" + value);
316                 String response = null;
317                 SharedContext existing = contextService.getSharedContext(contextId, key);
318                 if (existing == null) {
319                         contextService.addSharedContext(contextId, key, value);
320                 } else {
321                         existing.setCvalue(value);
322                         contextService.saveSharedContext(existing);
323                 }
324                 response = existing == null ? "added" : "replaced";
325                 String jsonResponse = convertResponseToJSON(response);
326                 return jsonResponse;
327         }
328
329         /**
330          * Creates a two-element JSON object tagged "response".
331          * 
332          * @param responseBody
333          * @return JSON object as String
334          * @throws JsonProcessingException
335          */
336         private String convertResponseToJSON(String responseBody) throws JsonProcessingException {
337                 Map<String, String> responseMap = new HashMap<String, String>();
338                 responseMap.put("response", responseBody);
339                 String response = mapper.writeValueAsString(responseMap);
340                 return response;
341         }
342
343         /**
344          * Converts a list of SharedContext objects to a JSON array.
345          * 
346          * @param contextList
347          * @return JSON array as String
348          * @throws JsonProcessingException
349          */
350         private String convertResponseToJSON(List<SharedContext> contextList) throws JsonProcessingException {
351                 String jsonArray = mapper.writeValueAsString(contextList);
352                 return jsonArray;
353         }
354
355         /**
356          * Creates a JSON object with the content of the shared context; null is ok.
357          * 
358          * @param context
359          * @return tag "response" with collection of context object's fields
360          * @throws JsonProcessingException
361          */
362         private String convertResponseToJSON(SharedContext context) throws JsonProcessingException {
363                 Map<String, Object> responseMap = new HashMap<String, Object>();
364                 responseMap.put("response", context);
365                 String responseBody = mapper.writeValueAsString(responseMap);
366                 return responseBody;
367         }
368
369         /**
370          * Handles any exception thrown by a method in this controller.
371          * 
372          * @param e
373          *            Exception
374          * @param response
375          *            HttpServletResponse
376          * @throws IOException
377          */
378         @ExceptionHandler(Exception.class)
379         protected void handleBadRequests(Exception e, HttpServletResponse response) throws IOException {
380                 logger.error(EELFLoggerDelegate.errorLogger, "handleBadRequest caught exception", e);
381                 response.sendError(HttpStatus.BAD_REQUEST.value(), e.getMessage());
382         }
383
384 }