2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.be.servlets;
19 import com.jcabi.aspects.Loggable;
20 import fj.data.Either;
21 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
22 import io.swagger.v3.oas.annotations.Operation;
23 import io.swagger.v3.oas.annotations.Parameter;
24 import io.swagger.v3.oas.annotations.info.Info;
25 import io.swagger.v3.oas.annotations.media.ArraySchema;
26 import io.swagger.v3.oas.annotations.media.Content;
27 import io.swagger.v3.oas.annotations.media.Schema;
28 import io.swagger.v3.oas.annotations.responses.ApiResponse;
29 import io.swagger.v3.oas.annotations.responses.ApiResponses;
30 import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
31 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
32 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
33 import org.openecomp.sdc.be.config.BeEcompErrorManager;
34 import org.openecomp.sdc.be.dao.api.ActionStatus;
35 import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil;
36 import org.openecomp.sdc.be.impl.ComponentsUtils;
37 import org.openecomp.sdc.be.model.PropertyDefinition;
38 import org.openecomp.sdc.be.model.User;
39 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
40 import org.openecomp.sdc.be.resources.data.EntryData;
41 import org.openecomp.sdc.be.user.UserBusinessLogic;
42 import org.openecomp.sdc.common.api.Constants;
43 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
44 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
45 import org.openecomp.sdc.common.log.enums.StatusCode;
46 import org.openecomp.sdc.exception.ResponseFormat;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 import javax.inject.Inject;
51 import javax.inject.Singleton;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.ws.rs.Consumes;
54 import javax.ws.rs.DELETE;
55 import javax.ws.rs.GET;
56 import javax.ws.rs.HeaderParam;
57 import javax.ws.rs.POST;
58 import javax.ws.rs.PUT;
59 import javax.ws.rs.Path;
60 import javax.ws.rs.PathParam;
61 import javax.ws.rs.Produces;
62 import javax.ws.rs.core.Context;
63 import javax.ws.rs.core.MediaType;
64 import javax.ws.rs.core.Response;
65 import java.util.List;
68 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
70 @OpenAPIDefinition(info = @Info(title = "Component Property Servlet", description = "Component Property Servlet"))
72 public class ComponentPropertyServlet extends BeGenericServlet {
74 private final PropertyBusinessLogic propertyBusinessLogic;
75 private final ApplicationDataTypeCache applicationDataTypeCache;
78 public ComponentPropertyServlet(UserBusinessLogic userBusinessLogic,
79 ComponentsUtils componentsUtils,
80 ApplicationDataTypeCache applicationDataTypeCache,
81 PropertyBusinessLogic propertyBusinessLogic) {
82 super(userBusinessLogic, componentsUtils);
83 this.applicationDataTypeCache = applicationDataTypeCache;
84 this.propertyBusinessLogic = propertyBusinessLogic;
87 private static final Logger log = LoggerFactory.getLogger(ComponentPropertyServlet.class);
88 private static final String CREATE_PROPERTY = "Create Property";
89 private static final String DEBUG_MESSAGE = "Start handle request of {} modifier id is {}";
90 private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ComponentPropertyServlet.class.getName());
94 @Path("services/{serviceId}/properties")
95 @Consumes(MediaType.APPLICATION_JSON)
96 @Produces(MediaType.APPLICATION_JSON)
97 @Operation(description = "Create Service Property", method = "POST", summary = "Returns created service property",
98 responses = @ApiResponse(
99 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
100 @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Service property created"),
101 @ApiResponse(responseCode = "403", description = "Restricted operation"),
102 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
103 @ApiResponse(responseCode = "409", description = "Service property already exist")})
104 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
105 public Response createPropertyInService(
106 @Parameter(description = "service id to update with new property",
107 required = true) @PathParam("serviceId") final String serviceId,
108 @Parameter(description = "Service property to be created", required = true) String data,
109 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
111 return createProperty(serviceId, data, request, userId);
115 @Path("resources/{resourceId}/properties")
116 @Consumes(MediaType.APPLICATION_JSON)
117 @Produces(MediaType.APPLICATION_JSON)
118 @Operation(description = "Create Resource Property", method = "POST", summary = "Returns created service property",
119 responses = @ApiResponse(
120 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
121 @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource property created"),
122 @ApiResponse(responseCode = "403", description = "Restricted operation"),
123 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
124 @ApiResponse(responseCode = "409", description = "Resource property already exist")})
125 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
126 public Response createPropertyInResource(
127 @Parameter(description = "Resource id to update with new property",
128 required = true) @PathParam("resourceId") final String resourceId,
129 @Parameter(description = "Resource property to be created", required = true) String data,
130 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
132 return createProperty(resourceId, data, request, userId);
137 @Path("services/{serviceId}/properties/{propertyId}")
138 @Consumes(MediaType.APPLICATION_JSON)
139 @Produces(MediaType.APPLICATION_JSON)
140 @Operation(description = "Get Service Property", method = "GET", summary = "Returns property of service",
141 responses = @ApiResponse(
142 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
143 @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "property"),
144 @ApiResponse(responseCode = "403", description = "Restricted operation"),
145 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
146 @ApiResponse(responseCode = "404", description = "Service property not found")})
147 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
148 public Response getPropertyInService(
149 @Parameter(description = "service id of property", required = true) @PathParam("serviceId") final String serviceId,
150 @Parameter(description = "property id to get", required = true) @PathParam("propertyId") final String propertyId,
151 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
153 return getProperty(serviceId, propertyId, request, userId);
157 @Path("resources/{resourceId}/properties/{propertyId}")
158 @Consumes(MediaType.APPLICATION_JSON)
159 @Produces(MediaType.APPLICATION_JSON)
160 @Operation(description = "Get Resource Property", method = "GET", summary = "Returns property of resource",
161 responses = @ApiResponse(
162 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
163 @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "property"),
164 @ApiResponse(responseCode = "403", description = "Restricted operation"),
165 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
166 @ApiResponse(responseCode = "404", description = "Resource property not found")})
167 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
168 public Response getPropertyInResource(
169 @Parameter(description = "resource id of property",
170 required = true) @PathParam("resourceId") final String resourceId,
171 @Parameter(description = "property id to get", required = true) @PathParam("propertyId") final String propertyId,
172 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
174 return getProperty(resourceId, propertyId, request, userId);
178 @Path("services/{serviceId}/properties")
179 @Consumes(MediaType.APPLICATION_JSON)
180 @Produces(MediaType.APPLICATION_JSON)
181 @Operation(description = "Get Service Property", method = "GET", summary = "Returns property list of service",
182 responses = @ApiResponse(
183 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
184 @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "property"),
185 @ApiResponse(responseCode = "403", description = "Restricted operation"),
186 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
187 @ApiResponse(responseCode = "404", description = "Service property not found")})
188 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
189 public Response getPropertyListInService(
190 @Parameter(description = "service id of property",
191 required = true) @PathParam("serviceId") final String serviceId,
192 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
194 return getPropertyList(serviceId, request, userId);
198 @Path("resources/{resourceId}/properties")
199 @Consumes(MediaType.APPLICATION_JSON)
200 @Produces(MediaType.APPLICATION_JSON)
201 @Operation(description = "Get Resource Property", method = "GET", summary = "Returns property list of resource",
202 responses = @ApiResponse(
203 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
204 @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "property"),
205 @ApiResponse(responseCode = "403", description = "Restricted operation"),
206 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
207 @ApiResponse(responseCode = "404", description = "Resource property not found")})
208 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
209 public Response getPropertyListInResource(
210 @Parameter(description = "resource id of property",
211 required = true) @PathParam("resourceId") final String resourceId,
212 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
214 return getPropertyList(resourceId, request, userId);
218 @Path("services/{serviceId}/properties/{propertyId}")
219 @Consumes(MediaType.APPLICATION_JSON)
220 @Produces(MediaType.APPLICATION_JSON)
221 @Operation(description = "Delete Service Property", method = "DELETE", summary = "Returns deleted property",
222 responses = @ApiResponse(
223 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
224 @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "deleted property"),
225 @ApiResponse(responseCode = "403", description = "Restricted operation"),
226 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
227 @ApiResponse(responseCode = "404", description = "Service property not found")})
228 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
229 public Response deletePropertyInService(
230 @Parameter(description = "service id of property",
231 required = true) @PathParam("serviceId") final String serviceId,
232 @Parameter(description = "Property id to delete",
233 required = true) @PathParam("propertyId") final String propertyId,
234 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
236 return deleteProperty(serviceId, propertyId, request, userId);
240 @Path("resources/{resourceId}/properties/{propertyId}")
241 @Consumes(MediaType.APPLICATION_JSON)
242 @Produces(MediaType.APPLICATION_JSON)
243 @Operation(description = "Delete Resource Property", method = "DELETE", summary = "Returns deleted property",
244 responses = @ApiResponse(
245 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
246 @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "deleted property"),
247 @ApiResponse(responseCode = "403", description = "Restricted operation"),
248 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
249 @ApiResponse(responseCode = "404", description = "Resource property not found")})
250 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
251 public Response deletePropertyInResource(
252 @Parameter(description = "resource id of property",
253 required = true) @PathParam("resourceId") final String resourceId,
254 @Parameter(description = "Property id to delete",
255 required = true) @PathParam("propertyId") final String propertyId,
256 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
258 return deleteProperty(resourceId, propertyId, request, userId);
262 @Path("services/{serviceId}/properties")
263 @Consumes(MediaType.APPLICATION_JSON)
264 @Produces(MediaType.APPLICATION_JSON)
265 @Operation(description = "Update Service Property", method = "PUT", summary = "Returns updated property",
266 responses = @ApiResponse(
267 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
268 @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Service property updated"),
269 @ApiResponse(responseCode = "403", description = "Restricted operation"),
270 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
271 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
272 public Response updatePropertyInService(
273 @Parameter(description = "service id to update with new property",
274 required = true) @PathParam("serviceId") final String serviceId,
275 @Parameter(description = "Service property to update", required = true) String data,
276 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
278 return updateProperty(serviceId, data, request, userId);
282 @Path("resources/{resourceId}/properties")
283 @Consumes(MediaType.APPLICATION_JSON)
284 @Produces(MediaType.APPLICATION_JSON)
285 @Operation(description = "Update Resource Property", method = "PUT", summary = "Returns updated property",
286 responses = @ApiResponse(
287 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
288 @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource property updated"),
289 @ApiResponse(responseCode = "403", description = "Restricted operation"),
290 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
291 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
292 public Response updatePropertyInResource(
293 @Parameter(description = "resource id to update with new property",
294 required = true) @PathParam("resourceId") final String resourceId,
295 @Parameter(description = "Resource property to update", required = true) String data,
296 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
298 return updateProperty(resourceId, data, request, userId);
301 private Response createProperty(String componentId, String data, HttpServletRequest request,String userId) {
302 String url = request.getMethod() + " " + request.getRequestURI();
303 log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
304 loggerSupportability.log(LoggerSupportabilityActions.CREATE_PROPERTIES, StatusCode.STARTED,"CREATE_PROPERTIES by user {} ", userId);
307 Either<Map<String, PropertyDefinition>, ActionStatus> propertyDefinition =
308 getPropertyModel(componentId, data);
309 if (propertyDefinition.isRight()) {
310 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(propertyDefinition.right().value());
311 return buildErrorResponse(responseFormat);
314 Map<String, PropertyDefinition> properties = propertyDefinition.left().value();
315 if (properties == null || properties.size() != 1) {
316 log.info("Property content is invalid - {}", data);
317 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
318 return buildErrorResponse(responseFormat);
321 Map.Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
322 PropertyDefinition newPropertyDefinition = entry.getValue();
323 newPropertyDefinition.setParentUniqueId(componentId);
324 String propertyName = newPropertyDefinition.getName();
326 Either<EntryData<String, PropertyDefinition>, ResponseFormat> addPropertyEither =
327 propertyBusinessLogic.addPropertyToComponent(componentId, propertyName, newPropertyDefinition, userId);
329 if(addPropertyEither.isRight()) {
330 return buildErrorResponse(addPropertyEither.right().value());
333 loggerSupportability.log(LoggerSupportabilityActions.CREATE_PROPERTIES, StatusCode.COMPLETE,"CREATE_PROPERTIES by user {} ", userId);
334 return buildOkResponse(newPropertyDefinition);
336 } catch (Exception e) {
337 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_PROPERTY);
338 log.debug("create property failed with exception", e);
339 ResponseFormat responseFormat =
340 getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
341 return buildErrorResponse(responseFormat);
346 private Response updateProperty(String componentId, String data, HttpServletRequest request, String userId) {
347 String url = request.getMethod() + " " + request.getRequestURI();
348 log.debug("Start handle request of {}", url);
349 loggerSupportability.log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.STARTED,"UPDATE_PROPERTIES by user {} ", userId);
352 User modifier = new User();
353 modifier.setUserId(userId);
354 log.debug("modifier id is {}", userId);
357 // convert json to PropertyDefinition
359 Either<Map<String, PropertyDefinition>, ActionStatus> propertiesListEither =
360 getPropertiesListForUpdate(data);
361 if (propertiesListEither.isRight()) {
362 ResponseFormat responseFormat =
363 getComponentsUtils().getResponseFormat(propertiesListEither.right().value());
364 return buildErrorResponse(responseFormat);
366 Map<String, PropertyDefinition> properties = propertiesListEither.left().value();
367 if (properties == null) {
368 log.info("Property content is invalid - {}", data);
369 ResponseFormat responseFormat =
370 getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
371 return buildErrorResponse(responseFormat);
374 //Validate value and Constraint of property
375 Either<Boolean, ResponseFormat> constraintValidatorResponse =
376 PropertyValueConstraintValidationUtil.getInstance().
377 validatePropertyConstraints(properties.values(), applicationDataTypeCache);
378 if (constraintValidatorResponse.isRight()) {
379 log.error("Failed validation value and constraint of property: {}",
380 constraintValidatorResponse.right().value());
381 return buildErrorResponse(constraintValidatorResponse.right().value());
386 for(PropertyDefinition propertyDefinition : properties.values()) {
387 Either<EntryData<String, PropertyDefinition>, ResponseFormat> status =
388 propertyBusinessLogic.updateComponentProperty(
389 componentId, propertyDefinition.getUniqueId(), propertyDefinition, userId);
390 if (status.isRight()) {
391 log.info("Failed to update Property. Reason - ", status.right().value());
392 return buildErrorResponse(status.right().value());
394 EntryData<String, PropertyDefinition> property = status.left().value();
395 PropertyDefinition updatedPropertyDefinition = property.getValue();
397 log.debug("Property id {} updated successfully ", updatedPropertyDefinition.getUniqueId());
400 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
401 loggerSupportability.log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.COMPLETE,"UPDATE_PROPERTIES by user {} ", userId);
402 return buildOkResponse(responseFormat, properties);
404 } catch (Exception e) {
405 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property");
406 log.debug("update property failed with exception", e);
407 ResponseFormat responseFormat =
408 getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
409 return buildErrorResponse(responseFormat);
414 private Response getProperty(String componentId, String propertyId, HttpServletRequest request, String userId) {
415 String url = request.getMethod() + " " + request.getRequestURI();
416 log.debug(DEBUG_MESSAGE, url, userId);
419 Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> retrievedPropertyEither =
420 propertyBusinessLogic.getComponentProperty(componentId, propertyId, userId);
422 if(retrievedPropertyEither.isRight()) {
423 return buildErrorResponse(retrievedPropertyEither.right().value());
426 return buildOkResponse(retrievedPropertyEither.left().value());
428 } catch (Exception e) {
429 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_PROPERTY);
430 log.debug("get property failed with exception", e);
431 ResponseFormat responseFormat =
432 getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
433 return buildErrorResponse(responseFormat);
436 private Response getPropertyList(String componentId, HttpServletRequest request, String userId) {
438 String url = request.getMethod() + " " + request.getRequestURI();
439 log.debug(DEBUG_MESSAGE, url, userId);
442 Either<List<PropertyDefinition>, ResponseFormat> propertiesListEither =
443 propertyBusinessLogic.getPropertiesList(componentId, userId);
445 if(propertiesListEither.isRight()) {
446 return buildErrorResponse(propertiesListEither.right().value());
449 return buildOkResponse(propertiesListEither.left().value());
451 } catch (Exception e) {
452 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_PROPERTY);
453 log.debug("get property failed with exception", e);
454 ResponseFormat responseFormat =
455 getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
456 return buildErrorResponse(responseFormat);
459 private Response deleteProperty(String componentId, String propertyId, HttpServletRequest request, String userId) {
460 String url = request.getMethod() + " " + request.getRequestURI();
461 log.debug(DEBUG_MESSAGE, url, userId);
465 // delete the property
466 Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> status =
467 propertyBusinessLogic.deletePropertyFromComponent(componentId, propertyId, userId);
468 if (status.isRight()) {
469 log.debug("Failed to delete Property. Reason - ", status.right().value());
470 return buildErrorResponse(status.right().value());
472 Map.Entry<String, PropertyDefinition> property = status.left().value();
473 String name = property.getKey();
474 PropertyDefinition propertyDefinition = property.getValue();
476 log.debug("Property {} deleted successfully with id {}", name, propertyDefinition.getUniqueId());
477 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT);
478 return buildOkResponse(responseFormat, propertyToJson(property));
480 } catch (Exception e) {
481 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property");
482 log.debug("delete property failed with exception", e);
483 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
484 return buildErrorResponse(responseFormat);