2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.servlets;
23 import java.lang.reflect.Type;
24 import java.util.HashMap;
25 import java.util.Iterator;
27 import java.util.Map.Entry;
30 import javax.inject.Singleton;
31 import javax.servlet.ServletContext;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.HeaderParam;
37 import javax.ws.rs.POST;
38 import javax.ws.rs.PUT;
39 import javax.ws.rs.Path;
40 import javax.ws.rs.PathParam;
41 import javax.ws.rs.Produces;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.Response;
46 import org.json.simple.JSONObject;
47 import org.json.simple.parser.JSONParser;
48 import org.json.simple.parser.ParseException;
49 import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
50 import org.openecomp.sdc.be.config.BeEcompErrorManager;
51 import org.openecomp.sdc.be.dao.api.ActionStatus;
52 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
53 import org.openecomp.sdc.be.model.PropertyConstraint;
54 import org.openecomp.sdc.be.model.PropertyDefinition;
55 import org.openecomp.sdc.be.model.User;
56 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
57 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintSerialiser;
58 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
59 import org.openecomp.sdc.be.resources.data.EntryData;
60 import org.openecomp.sdc.common.api.Constants;
61 import org.openecomp.sdc.common.config.EcompErrorName;
62 import org.openecomp.sdc.exception.ResponseFormat;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65 import org.springframework.web.context.WebApplicationContext;
67 import com.google.gson.Gson;
68 import com.google.gson.GsonBuilder;
69 import com.google.gson.reflect.TypeToken;
70 import com.jcabi.aspects.Loggable;
71 import io.swagger.annotations.Api;
72 import io.swagger.annotations.ApiOperation;
73 import io.swagger.annotations.ApiParam;
74 import io.swagger.annotations.ApiResponse;
75 import io.swagger.annotations.ApiResponses;
77 import fj.data.Either;
79 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
81 @Api(value = "Resource Property Servlet", description = "Resource Property Servlet")
83 public class PropertyServlet extends BeGenericServlet {
85 private static Logger log = LoggerFactory.getLogger(PropertyServlet.class.getName());
88 @Path("resources/{resourceId}/properties")
89 @Consumes(MediaType.APPLICATION_JSON)
90 @Produces(MediaType.APPLICATION_JSON)
91 @ApiOperation(value = "Create Resource Property", httpMethod = "POST", notes = "Returns created resource property", response = Response.class)
92 @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource property created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
93 @ApiResponse(code = 409, message = "Resource property already exist") })
94 public Response createProperty(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId, @ApiParam(value = "Resource property to be created", required = true) String data,
95 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
97 ServletContext context = request.getSession().getServletContext();
99 String url = request.getMethod() + " " + request.getRequestURI();
100 log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
103 // convert json to PropertyDefinition
104 Either<Map<String, PropertyDefinition>, ActionStatus> either = getPropertyModel(resourceId, data);
105 if (either.isRight()) {
106 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(either.right().value());
107 return buildErrorResponse(responseFormat);
109 Map<String, PropertyDefinition> properties = either.left().value();
110 if (properties == null || properties.size() != 1) {
111 log.info("Property conetnt is invalid - {}", data);
112 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
113 return buildErrorResponse(responseFormat);
115 Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
116 String propertyName = entry.getKey();
117 PropertyDefinition newPropertyDefinition = entry.getValue();
119 // create the new property
120 PropertyBusinessLogic businessLogic = getPropertyBL(context);
121 Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = businessLogic.createProperty(resourceId, propertyName, newPropertyDefinition, userId);
122 if (status.isRight()) {
123 log.info("Failed to create Property. Reason - ", status.right().value());
124 return buildErrorResponse(status.right().value());
126 EntryData<String, PropertyDefinition> property = status.left().value();
127 String name = property.getKey();
128 PropertyDefinition propertyDefinition = property.getValue();
130 log.debug("Property {} created successfully with id {}", name, propertyDefinition.getUniqueId());
131 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.CREATED);
132 return buildOkResponse(responseFormat, propertyToJson(property));
134 } catch (Exception e) {
135 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeRestApiGeneralError, "Create Property");
136 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property");
137 log.debug("create property failed with exception", e);
138 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
139 return buildErrorResponse(responseFormat);
145 @Path("resources/{resourceId}/properties/{propertyId}")
146 @Consumes(MediaType.APPLICATION_JSON)
147 @Produces(MediaType.APPLICATION_JSON)
148 @ApiOperation(value = "Create Resource Property", httpMethod = "GET", notes = "Returns property of resource", response = Response.class)
149 @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
150 @ApiResponse(code = 404, message = "Resource property not found") })
151 public Response getProperty(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId, @ApiParam(value = "proerty id to get", required = true) @PathParam("propertyId") final String propertyId,
152 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
154 ServletContext context = request.getSession().getServletContext();
156 String url = request.getMethod() + " " + request.getRequestURI();
157 log.debug("Start handle request of {}, modifier id is {}", url, userId);
162 PropertyBusinessLogic businessLogic = getPropertyBL(context);
163 Either<Entry<String, PropertyDefinition>, ResponseFormat> status = businessLogic.getProperty(resourceId, propertyId, userId);
165 if (status.isRight()) {
166 log.info("Failed to get Property. Reason - ", status.right().value());
167 return buildErrorResponse(status.right().value());
169 Entry<String, PropertyDefinition> property = status.left().value();
170 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
171 return buildOkResponse(responseFormat, propertyToJson(property));
172 } catch (Exception e) {
173 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeRestApiGeneralError, "Get Property");
174 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Property");
175 log.debug("get property failed with exception", e);
176 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
177 return buildErrorResponse(responseFormat);
183 @Path("resources/{resourceId}/properties/{propertyId}")
184 @Consumes(MediaType.APPLICATION_JSON)
185 @Produces(MediaType.APPLICATION_JSON)
186 @ApiOperation(value = "Create Resource Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class)
187 @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
188 @ApiResponse(code = 404, message = "Resource property not found") })
189 public Response deleteProperty(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
190 @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
192 ServletContext context = request.getSession().getServletContext();
194 String url = request.getMethod() + " " + request.getRequestURI();
195 log.debug("Start handle request of {} modifier id is {}", url, userId);
199 // delete the property
200 PropertyBusinessLogic businessLogic = getPropertyBL(context);
201 Either<Entry<String, PropertyDefinition>, ResponseFormat> status = businessLogic.deleteProperty(resourceId, propertyId, userId);
202 if (status.isRight()) {
203 log.debug("Failed to delete Property. Reason - ", status.right().value());
204 return buildErrorResponse(status.right().value());
206 Entry<String, PropertyDefinition> property = status.left().value();
207 String name = property.getKey();
208 PropertyDefinition propertyDefinition = property.getValue();
210 log.debug("Property {} deleted successfully with id {}", name, propertyDefinition.getUniqueId());
211 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT);
212 return buildOkResponse(responseFormat, propertyToJson(property));
214 } catch (Exception e) {
215 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property");
216 log.debug("delete property failed with exception", e);
217 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
218 return buildErrorResponse(responseFormat);
224 @Path("resources/{resourceId}/properties/{propertyId}")
225 @Consumes(MediaType.APPLICATION_JSON)
226 @Produces(MediaType.APPLICATION_JSON)
227 @ApiOperation(value = "Update Resource Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class)
228 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource property updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") })
229 public Response updateProperty(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId,
230 @ApiParam(value = "proerty id to update", required = true) @PathParam("propertyId") final String propertyId, @ApiParam(value = "Resource property to update", required = true) String data, @Context final HttpServletRequest request,
231 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
233 ServletContext context = request.getSession().getServletContext();
235 String url = request.getMethod() + " " + request.getRequestURI();
236 log.debug("Start handle request of {}", url);
239 User modifier = new User();
240 modifier.setUserId(userId);
241 log.debug("modifier id is {}", userId);
244 // convert json to PropertyDefinition
245 Either<Map<String, PropertyDefinition>, ActionStatus> either = getPropertyModel(resourceId, data);
246 if (either.isRight()) {
247 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(either.right().value());
248 return buildErrorResponse(responseFormat);
250 Map<String, PropertyDefinition> properties = either.left().value();
251 if (properties == null || properties.size() != 1) {
252 log.info("Property conetnt is invalid - {}", data);
253 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
254 return buildErrorResponse(responseFormat);
256 Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
257 PropertyDefinition newPropertyDefinition = entry.getValue();
260 PropertyBusinessLogic businessLogic = getPropertyBL(context);
261 Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = businessLogic.updateProperty(resourceId, propertyId, newPropertyDefinition, userId);
262 if (status.isRight()) {
263 log.info("Failed to update Property. Reason - ", status.right().value());
264 return buildErrorResponse(status.right().value());
266 EntryData<String, PropertyDefinition> property = status.left().value();
267 PropertyDefinition propertyDefinition = property.getValue();
269 log.debug("Property id {} updated successfully ", propertyDefinition.getUniqueId());
270 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
271 return buildOkResponse(responseFormat, propertyToJson(property));
273 } catch (Exception e) {
274 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeRestApiGeneralError, "Update Property");
275 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property");
276 log.debug("update property failed with exception", e);
277 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
278 return buildErrorResponse(responseFormat);
283 private Either<Map<String, PropertyDefinition>, ActionStatus> getPropertyModel(String resourceId, String data) {
284 JSONParser parser = new JSONParser();
287 Map<String, PropertyDefinition> properties = new HashMap<String, PropertyDefinition>();
288 root = (JSONObject) parser.parse(data);
290 Set entrySet = root.entrySet();
291 Iterator iterator = entrySet.iterator();
292 while (iterator.hasNext()) {
293 Entry next = (Entry) iterator.next();
294 String propertyName = (String) next.getKey();
295 JSONObject value = (JSONObject) next.getValue();
296 String jsonString = value.toJSONString();
297 Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, PropertyDefinition.class);
298 if (convertJsonToObject.isRight()) {
299 return Either.right(convertJsonToObject.right().value());
301 PropertyDefinition propertyDefinition = convertJsonToObject.left().value();
302 // PropertyDefinition propertyDefinition =
303 // gson.fromJson(jsonString , PropertyDefinition.class);
304 String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId, (String) propertyName);
305 propertyDefinition.setUniqueId(uniqueId);
306 properties.put(propertyName, propertyDefinition);
309 // Set keySet = root.keySet();
310 // for (Object propertyName : keySet){
311 // JSONObject val = (JSONObject) root.get(propertyName);
312 // String jsonString = val.toJSONString();
313 // Either<PropertyDefinition,ActionStatus> convertJsonToObject =
314 // convertJsonToObject(jsonString, PropertyDefinition.class);
315 // if (convertJsonToObject.isRight()){
316 // return Either.right(convertJsonToObject.right().value());
318 // PropertyDefinition propertyDefinition =
319 // convertJsonToObject.left().value();
320 // //PropertyDefinition propertyDefinition =
321 // gson.fromJson(jsonString , PropertyDefinition.class);
323 // UniqueIdBuilder.buildPropertyUniqueId("resourceId",
324 // (String)propertyName);
325 // propertyDefinition.setUniqueId(uniqueId);
326 // properties.put((String)propertyName,propertyDefinition);
328 return Either.left(properties);
329 } catch (ParseException e) {
330 log.info("Property conetnt is invalid - {}", data);
331 return Either.right(ActionStatus.INVALID_CONTENT);
335 private String propertyToJson(Map.Entry<String, PropertyDefinition> property) {
336 JSONObject root = new JSONObject();
337 String propertyName = property.getKey();
338 PropertyDefinition propertyDefinition = property.getValue();
339 // String jsonPropertyDefinition = gson.toJson(propertyDefinition);
340 // root.put(propertyName, jsonPropertyDefinition);
341 JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition);
342 root.put(propertyName, propertyDefinitionO);
343 propertyDefinition.getType();
344 return root.toString();
347 private JSONObject getPropertyDefinitionJSONObject(PropertyDefinition propertyDefinition) {
349 Either<String, ActionStatus> either = convertObjectToJson(propertyDefinition);
350 if (either.isRight()) {
351 return new JSONObject();
353 String value = either.left().value();
355 JSONObject root = (JSONObject) new JSONParser().parse(value);
357 } catch (ParseException e) {
358 log.info("failed to convert input to json");
359 log.debug("failed to convert to json", e);
360 return new JSONObject();
365 private <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
367 Type constraintType = new TypeToken<PropertyConstraint>() {
369 Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create();
371 log.trace("convert json to object. json=\n {}", data);
372 t = gson.fromJson(data, clazz);
374 log.info("object is null after converting from json");
375 return Either.right(ActionStatus.INVALID_CONTENT);
377 } catch (Exception e) {
379 log.info("failed to convert from json");
380 log.debug("failed to convert from json", e);
381 return Either.right(ActionStatus.INVALID_CONTENT);
383 return Either.left(t);
386 private <T> Either<String, ActionStatus> convertObjectToJson(PropertyDefinition propertyDefinition) {
387 Type constraintType = new TypeToken<PropertyConstraint>() {
389 Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintSerialiser()).create();
391 log.trace("convert object to json. propertyDefinition= {}", propertyDefinition.toString());
392 String json = gson.toJson(propertyDefinition);
394 log.info("object is null after converting to json");
395 return Either.right(ActionStatus.INVALID_CONTENT);
397 return Either.left(json);
398 } catch (Exception e) {
400 log.info("failed to convert to json");
401 log.debug("failed to convert fto json", e);
402 return Either.right(ActionStatus.INVALID_CONTENT);
407 private PropertyBusinessLogic getPropertyBL(ServletContext context) {
408 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
409 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
410 PropertyBusinessLogic propertytBl = webApplicationContext.getBean(PropertyBusinessLogic.class);
414 // private class UiProperty{
418 // String description;
419 // public String getType() {
422 // public void setType(String type) {
425 // public String getSource() {
428 // public void setSource(String source) {
429 // this.source = source;
431 // public String getName() {
434 // public void setName(String name) {
437 // public String getDescription() {
438 // return description;
440 // public void setDescription(String description) {
441 // this.description = description;