diff options
9 files changed, 183 insertions, 71 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java index 05c1fb7ad3..3a62600433 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/DataTypeServlet.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Optional; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; @@ -63,7 +64,6 @@ import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.stereotype.Controller; -import org.apache.commons.lang3.StringUtils; @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog/data-types") @@ -162,10 +162,10 @@ public class DataTypeServlet extends BeGenericServlet { String.format("Property model is not the same as the data type model. Must be '%s'", model)); } if (StringUtils.isEmpty(dataType.getModel())) { - dataType.setModel("SDC AID"); + dataType.setModel(Constants.DEFAULT_MODEL_NAME); } final PropertyDefinitionDto property = dataTypeOperation.createProperty(id, propertyDefinitionDto); - dataTypeOperation.addPropertyToAdditionalTypeDataType(dataType, property); + dataTypeOperation.updatePropertyInAdditionalTypeDataType(dataType, property, true); dataTypeBusinessLogic.updateApplicationDataTypeCache(id); return Response.status(Status.CREATED).entity(property).build(); } @@ -204,7 +204,7 @@ public class DataTypeServlet extends BeGenericServlet { dataType.setModel(Constants.DEFAULT_MODEL_NAME); } final PropertyDefinitionDto property = dataTypeOperation.updateProperty(id, propertyDefinitionDto); - dataTypeOperation.addPropertyToAdditionalTypeDataType(dataType, property); + dataTypeOperation.updatePropertyInAdditionalTypeDataType(dataType, property, true); dataTypeBusinessLogic.updateApplicationDataTypeCache(id); return Response.status(Status.CREATED).entity(property).build(); } @@ -224,4 +224,38 @@ public class DataTypeServlet extends BeGenericServlet { return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), gson.toJson(dataTypeOperation.getAllDataTypeModels(dataTypeName))); } + + @DELETE + @Path("{dataTypeId}/{propertyId}") + public Response deleteProperty(@Parameter(in = ParameterIn.PATH, required = true, description = "The data type id") + @PathParam("dataTypeId") final String dataTypeId, + @Parameter(in = ParameterIn.PATH, required = true, description = "The property id to delete") + @PathParam("propertyId") final String propertyId) { + final Optional<DataTypeDataDefinition> dataTypeOptional = dataTypeOperation.getDataTypeByUid(dataTypeId); + dataTypeOptional.orElseThrow(() -> { + throw new OperationException(ActionStatus.DATA_TYPE_NOT_FOUND, String.format("Failed to find data type '%s'", dataTypeId)); + }); + final DataTypeDataDefinition dataTypeDataDefinition = dataTypeOptional.get(); + if (StringUtils.isEmpty(dataTypeDataDefinition.getModel())) { + dataTypeDataDefinition.setModel(Constants.DEFAULT_MODEL_NAME); + } + final PropertyDefinitionDto propertyDefinitionDto; + try { + propertyDefinitionDto = dataTypeOperation.deleteProperty(dataTypeDataDefinition, propertyId); + dataTypeOperation.updatePropertyInAdditionalTypeDataType(dataTypeDataDefinition, propertyDefinitionDto, false); + } catch (OperationException e) { + final PropertyDefinitionDto dto = new PropertyDefinitionDto(); + dto.setName(extractNameFromPropertyId(propertyId)); + dataTypeOperation.updatePropertyInAdditionalTypeDataType(dataTypeDataDefinition, dto, false); + throw e; + } finally { + dataTypeBusinessLogic.updateApplicationDataTypeCache(dataTypeId); + } + return Response.status(Status.OK).entity(propertyDefinitionDto).build(); + } + + private String extractNameFromPropertyId(final String propertyId) { + final String[] split = propertyId.split("\\."); + return split[split.length - 1]; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java index 8974704199..f7ea9bb407 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java @@ -137,7 +137,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadCapabilityType(@Parameter(description = "FileInputStream") @FormDataParam("capabilityTypeZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod = (responseWrapper, ymlPayload, model, includeToModelImport) -> createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload, modelName, @@ -157,10 +157,10 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadRelationshipType(@Parameter(description = "FileInputStream") @FormDataParam("relationshipTypeZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { - return uploadElementTypeServletLogic( - this::createRelationshipTypes, file, request, creator, NodeTypeEnum.RelationshipType.getName(), modelName, includeToModelDefaultImports); + return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator, NodeTypeEnum.RelationshipType.getName(), + modelName, includeToModelDefaultImports); } @POST @@ -174,7 +174,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadInterfaceLifecycleType(@Parameter(description = "FileInputStream") @FormDataParam("interfaceLifecycleTypeZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) -> createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload, modelName, @@ -230,7 +230,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadDataTypes(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { return uploadElementTypeServletLogic(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName, includeToModelDefaultImports); @@ -247,7 +247,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadDataTypesYaml(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesYaml") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { return uploadElementTypeServletLogicYaml(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName, includeToModelDefaultImports); @@ -263,7 +263,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @ApiResponse(responseCode = "409", description = "group types already exist")}) @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadGroupTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "FileInputStream") @FormDataParam("groupTypesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { @@ -282,7 +282,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet { @ApiResponse(responseCode = "409", description = "policy types already exist")}) @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) public Response uploadPolicyTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData, - @Parameter(description = "model") @FormDataParam("model") String modelName, + @Parameter(description = "model name") @FormDataParam("model") String modelName, @Parameter(description = "FileInputStream") @FormDataParam("policyTypesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator, @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) { @@ -331,8 +331,6 @@ public class TypesUploadServlet extends AbstractValidationsServlet { final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file); if (responseWrapper.isEmpty()) { fillZipContents(yamlStringWrapper, file); - } - if (responseWrapper.isEmpty()) { createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement(), modelName, includeToModelDefaultImports); } return responseWrapper.getInnerElement(); @@ -353,11 +351,12 @@ public class TypesUploadServlet extends AbstractValidationsServlet { final String url = request.getMethod() + " " + request.getRequestURI(); log.debug(START_HANDLE_REQUEST_OF, url); final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file); + final String yamlAsString = getFileAsString(file); if (responseWrapper.isEmpty()) { - final String yamlAsString = getFileAsString(file); log.debug("received yaml: {}", yamlAsString); createElementsMethod.accept(responseWrapper, yamlAsString, modelName, includeToModelDefaultImports); } + return responseWrapper.getInnerElement(); } catch (final Exception e) { log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java index 391add9a94..f79f1501e7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperation.java @@ -303,8 +303,38 @@ public class DataTypeOperation extends AbstractOperation { return PropertyDefinitionDtoMapper.mapFrom(propertyData); } - public void addPropertyToAdditionalTypeDataType(DataTypeDataDefinition dataTypeDataDefinition, PropertyDefinitionDto property) { - modelOperation.addPropertyToAdditionalType(ElementTypeEnum.DATA_TYPE, property, dataTypeDataDefinition.getModel(), dataTypeDataDefinition.getName()); + public void updatePropertyInAdditionalTypeDataType(final DataTypeDataDefinition dataTypeDataDefinition, + final PropertyDefinitionDto property, + final boolean isAdd) { + modelOperation.updatePropertyInAdditionalType(ElementTypeEnum.DATA_TYPE, property, dataTypeDataDefinition.getModel(), + dataTypeDataDefinition.getName(), isAdd); + } + + public PropertyDefinitionDto deleteProperty(final DataTypeDataDefinition dataTypeDataDefinition, final String propertyId) { + final List<PropertyDefinition> propertiesData = findAllProperties(dataTypeDataDefinition.getUniqueId()); + final String dataTypeDataDefinitionName = dataTypeDataDefinition.getName(); + if (CollectionUtils.isEmpty(propertiesData)) { + throw new OperationException(ActionStatus.PROPERTY_NOT_FOUND, + String.format("Failed to find property '%s' for data type '%s'", propertyId, dataTypeDataDefinitionName)); + } + Optional<PropertyDefinition> optionalPropertyDefinition = propertiesData.stream() + .filter(propertyDataDefinition -> propertyDataDefinition.getUniqueId().equals(propertyId)).findAny(); + optionalPropertyDefinition.orElseThrow(() -> { + throw new OperationException(ActionStatus.PROPERTY_NOT_FOUND, + String.format("Failed to find property '%s' for data type '%s'", propertyId, dataTypeDataDefinitionName)); + }); + final Either<PropertyData, JanusGraphOperationStatus> statusEither = propertyOperation.deletePropertyFromGraph(propertyId); + if (statusEither.isRight()) { + throw new OperationException(ActionStatus.PROPERTY_NOT_FOUND, + String.format("Failed to delete property '%s' from data type '%s'", propertyId, dataTypeDataDefinitionName)); + } + final PropertyDefinition propertyDefinition = optionalPropertyDefinition.get(); + final PropertyData propertyData = statusEither.left().value(); + final PropertyDataDefinition propertyDataDefinition = propertyData.getPropertyDataDefinition(); + propertyDataDefinition.setName(propertyDefinition.getName()); + propertyDataDefinition.setPropertyConstraints(propertyData.getConstraints()); + propertiesData.remove(propertyDefinition); + return PropertyDefinitionDtoMapper.mapFrom(propertyDataDefinition); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java index 311b4719bd..19289411c3 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java @@ -18,6 +18,8 @@ */ package org.openecomp.sdc.be.model.operations.impl; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DATA_TYPES; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.PROPERTIES; import static org.openecomp.sdc.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS; import fj.data.Either; @@ -220,11 +222,11 @@ public class ModelOperation { public List<Model> findAllModels() { return findModelsByCriteria(Collections.emptyMap()); } - + public List<Model> findModels(final ModelTypeEnum modelType) { final Map<GraphPropertyEnum, Object> propertyCriteria = new EnumMap<>(GraphPropertyEnum.class); propertyCriteria.put(GraphPropertyEnum.MODEL_TYPE, modelType.getValue()); - + return findModelsByCriteria(propertyCriteria); } @@ -259,7 +261,7 @@ public class ModelOperation { if (optionalModelTypeEnum.isPresent()) { modelType = optionalModelTypeEnum.get(); } - + final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> parentNode = janusGraphGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Model), UniqueIdBuilder.buildModelUid(modelName), GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model, ModelData.class); @@ -298,8 +300,8 @@ public class ModelOperation { } Map<String, Object> typesYamlMap = new Yaml().loadAs(typesYaml, Map.class); - if (typesYamlMap.containsKey("data_types")){ - typesYamlMap = (Map<String, Object>) typesYamlMap.get("data_types"); + if (typesYamlMap.containsKey(DATA_TYPES.getElementName())) { + typesYamlMap = (Map<String, Object>) typesYamlMap.get(DATA_TYPES.getElementName()); } removeExistingTypesFromDefaultImports(elementTypeEnum, typesYamlMap, rebuiltModelImportList); @@ -378,7 +380,7 @@ public class ModelOperation { if (deleteParentNodeByModel.isRight()) { final var janusGraphOperationStatus = deleteParentNodeByModel.right().value(); log.error(EcompLoggerErrorCode.DATA_ERROR, ModelOperation.class.getName(), - "Failed to delete model {} on JanusGraph with status {}", new Object[] {model.getName(), janusGraphOperationStatus}); + "Failed to delete model {} on JanusGraph with status {}", model.getName(), janusGraphOperationStatus); throw new OperationException(ActionStatus.COULD_NOT_DELETE_MODEL, model.getName()); } } @@ -397,28 +399,28 @@ public class ModelOperation { final Map<String, Object> existingTypeContent = getExistingTypes(elementTypeEnum, additionalTypeDefinitionsImportOptional.get()); final Set<String> existingTypeNames = existingTypeContent.keySet(); - final Map<String, Object> typesToUpate = new HashMap<>(); - Map<String, Object> newTypesYaml = new Yaml().load(typesYaml); - if (newTypesYaml.containsKey("data_types")){ - newTypesYaml = (Map<String, Object>) newTypesYaml.get("data_types"); + if (newTypesYaml.containsKey(DATA_TYPES.getElementName())) { + newTypesYaml = (Map<String, Object>) newTypesYaml.get(DATA_TYPES.getElementName()); } + final Map<String, Object> typesToUpate = new HashMap<>(); newTypesYaml.entrySet().stream().filter(entry -> existingTypeNames.contains(entry.getKey())).forEach(newTypeToUpdate -> { - final Map<String, Object> propertiesInNewDef = (Map<String, Object>) ((Map<String, Object>) newTypeToUpdate.getValue()).get("properties"); + final Map<String, Object> propertiesInNewDef = + (Map<String, Object>) ((Map<String, Object>) newTypeToUpdate.getValue()).get(PROPERTIES.getElementName()); final Map<String, Object> existingProperties = - (Map<String, Object>) ((Map<String, Object>) existingTypeContent.get(newTypeToUpdate.getKey())).get("properties"); + (Map<String, Object>) ((Map<String, Object>) existingTypeContent.get(newTypeToUpdate.getKey())).get(PROPERTIES.getElementName()); final List<Entry<String, Object>> propertiesMissingFromNewDef = MapUtils.isEmpty(existingProperties) ? Collections.emptyList() - : existingProperties.entrySet().stream() - .filter(existingPropEntry -> !propertiesInNewDef.keySet().contains(existingPropEntry.getKey())) - .collect(Collectors.toList()); + : existingProperties.entrySet().stream() + .filter(existingPropEntry -> !propertiesInNewDef.keySet().contains(existingPropEntry.getKey())) + .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(propertiesMissingFromNewDef)) { typesToUpate.put(newTypeToUpdate.getKey(), newTypeToUpdate.getValue()); propertiesMissingFromNewDef - .forEach(existingPropToAdd -> propertiesInNewDef.put(existingPropToAdd.getKey(), existingPropToAdd.getValue())); + .forEach(existingPropToAdd -> propertiesInNewDef.put(existingPropToAdd.getKey(), existingPropToAdd.getValue())); } }); if (MapUtils.isNotEmpty(typesToUpate)) { @@ -426,48 +428,51 @@ public class ModelOperation { } } } - - private Optional<ToscaImportByModel> getAdditionalTypes(final String modelName) { + + private Optional<ToscaImportByModel> getAdditionalTypes(final String modelName) { final List<ToscaImportByModel> modelImportList = toscaModelImportCassandraDao.findAllByModel(modelName); return modelImportList.stream().filter(t -> ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(t.getFullPath()))).findAny(); } private Map<String, Object> getExistingTypes(final ElementTypeEnum elementTypeEnum, final ToscaImportByModel additionalTypeDefinitionsImport) { final Map<String, Object> existingContent = new Yaml().load(additionalTypeDefinitionsImport.getContent()); - return (Map<String, Object>) existingContent.get(elementTypeEnum.getToscaEntryName()); + return (Map<String, Object>) existingContent.get(elementTypeEnum.getToscaEntryName()); } - public void addPropertyToAdditionalType(final ElementTypeEnum elementTypeEnum, final PropertyDefinitionDto property, - final String modelName, final String name) { + public void updatePropertyInAdditionalType(final ElementTypeEnum elementTypeEnum, final PropertyDefinitionDto property, + final String modelName, final String name, boolean isAdd) { final List<ToscaImportByModel> modelImportList = toscaModelImportCassandraDao.findAllByModel(modelName); final Optional<ToscaImportByModel> additionalTypeDefinitionsImportOptional = modelImportList.stream() - .filter(t -> ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(t.getFullPath()))).findAny(); - final ToscaImportByModel additionalTypeDefinitionsImport; - final List<ToscaImportByModel> rebuiltModelImportList; + .filter(t -> ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(t.getFullPath()))).findAny(); if (additionalTypeDefinitionsImportOptional.isEmpty()) { return; } - additionalTypeDefinitionsImport = additionalTypeDefinitionsImportOptional.get(); - rebuiltModelImportList = modelImportList.stream() - .filter(toscaImportByModel -> !ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(toscaImportByModel.getFullPath()))) - .collect(Collectors.toList()); + final ToscaImportByModel additionalTypeDefinitionsImport = additionalTypeDefinitionsImportOptional.get(); + final List<ToscaImportByModel> rebuiltModelImportList = modelImportList.stream() + .filter(toscaImportByModel -> !ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(toscaImportByModel.getFullPath()))) + .collect(Collectors.toList()); final Map<String, Object> originalContent = new Yaml().load(additionalTypeDefinitionsImport.getContent()); - additionalTypeDefinitionsImport.setContent(buildPropertyAdditionalTypeDefinitionContent(elementTypeEnum, name, property, originalContent)); + additionalTypeDefinitionsImport.setContent( + buildPropertyAdditionalTypeDefinitionContent(elementTypeEnum, name, property, originalContent, isAdd)); rebuiltModelImportList.add(additionalTypeDefinitionsImport); toscaModelImportCassandraDao.saveAll(modelName, rebuiltModelImportList); } private String buildPropertyAdditionalTypeDefinitionContent(final ElementTypeEnum elementTypeEnum, final String name, - final PropertyDefinitionDto property, final Map<String, Object> originalContent) { + final PropertyDefinitionDto property, final Map<String, Object> originalContent, + boolean isAdd) { final Map<String, Object> originalTypeContent = (Map<String, Object>) originalContent.get(elementTypeEnum.getToscaEntryName()); Map<String, Object> typeContent = (Map<String, Object>) originalTypeContent.get(name); - Map<String, Object> typeProperties = (Map<String, Object>) typeContent.get("properties"); - if (typeProperties == null) { + Map<String, Object> typeProperties = (Map<String, Object>) typeContent.get(PROPERTIES.getElementName()); + if (MapUtils.isEmpty(typeProperties)) { typeProperties = new HashMap<>(); } - Map<String, Object> typeProp = constructProperty(property); - typeProperties.put(property.getName(), typeProp); - typeContent.put("properties", typeProperties); + if (isAdd) { + typeProperties.put(property.getName(), constructProperty(property)); + } else { + typeProperties.remove(property.getName()); + } + typeContent.put(PROPERTIES.getElementName(), typeProperties); return new YamlUtil().objectToYaml(originalContent); } diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java index 8fe89216fa..1bd4d9dbac 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java @@ -613,7 +613,7 @@ class ModelOperationTest extends ModelTestBase { property.setRequired(true); String dataTypeName = "tosca.datatypes.nfv.PreviouslyExistingType1"; - modelOperation.addPropertyToAdditionalType(ElementTypeEnum.DATA_TYPE, property, modelName, dataTypeName); + modelOperation.updatePropertyInAdditionalType(ElementTypeEnum.DATA_TYPE, property, modelName, dataTypeName, true); ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class); verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture()); diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html index e657520ee4..12b2d992a8 100644 --- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.html @@ -32,14 +32,15 @@ <div class="table-header head-row hand flex-item" *ngFor="let header of tableHeadersList" (click)="onUpdateSort(header.property)">{{header.title}} <span *ngIf="tableSortBy === header.property" class="table-header-sort-arrow" [ngClass]="{'down': tableColumnReverse, 'up': !tableColumnReverse}"></span> </div> + <div class="table-no-text-header head-row flex-item" *ngIf="!isViewOnly"><span class="delete-col-header"></span></div> </div> <div class="body"> <div *ngIf="filteredProperties.length === 0" class="no-row-text"> {{'PROPERTY_LIST_EMPTY_MESSAGE' | translate}} </div> - <div *ngFor="let property of filteredProperties" [attr.data-tests-id]="'property-row-' + property.name" class="flex-container data-row" (click)="onNameClick(property)"> - <div class="table-col-general flex-item text" [title]="property.name"> + <div *ngFor="let property of filteredProperties" [attr.data-tests-id]="'property-row-' + property.name" class="flex-container data-row"> + <div class="table-col-general flex-item text" [title]="property.name" (click)="onNameClick(property)"> <a [attr.data-tests-id]="'property-name-' + property.name" [ngClass]="{'disabled': false}">{{property.name}}</a> </div> <div class="table-col-general flex-item text" [title]="property.type"> @@ -54,6 +55,10 @@ <div class="table-col-general flex-item text" [title]="property.description || ''"> <span [attr.data-tests-id]="'property-description-' + property.name" [title]="property.description">{{property.description}}</span> </div> + <div class="table-btn-col flex-item" *ngIf="!isViewOnly"> + <button class="table-delete-btn" data-ng-if="!property.ownerId || property.ownerId==component.uniqueId" + (click)="delete(property); $event.stopPropagation();" data-ng-class="{'disabled': isViewOnly}"></button> + </div> </div> </div> diff --git a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts index 60edd13c2d..f9eaa1332d 100644 --- a/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts +++ b/catalog-ui/src/app/ng2/pages/type-workspace/type-workspace-properties/type-workspace-properties.component.ts @@ -32,6 +32,8 @@ import {TranslateService} from "../../../shared/translator/translate.service"; import {AddPropertyComponent, PropertyValidationEvent} from "./add-property/add-property.component"; import {IWorkspaceViewModelScope} from "../../../../view-models/workspace/workspace-view-model"; import {SdcUiServices} from "onap-ui-angular/dist"; +import {PropertyModel} from "../../../../models/properties"; +import {SdcUiCommon, SdcUiComponents} from "onap-ui-angular"; import {ToscaTypeHelper} from "../../../../utils/tosca-type-helper"; @Component({ @@ -249,9 +251,31 @@ export class TypeWorkspacePropertiesComponent implements OnInit { } return null; } + + delete(property: PropertyModel) { + let onOk: Function = (): void => { + this.dataTypeService.deleteProperty(this.dataType.uniqueId, property.uniqueId).subscribe((response) => { + const props = this.properties; + props.splice(props.findIndex(p => p.uniqueId === response), 1); + this.filter(); + }, (error) => { + console.error(error); + }); + }; + let title: string = this.translateService.translate("PROPERTY_VIEW_DELETE_MODAL_TITLE"); + let message: string = this.translateService.translate("PROPERTY_VIEW_DELETE_MODAL_TEXT", {'name': property.name}); + const okButton = { + testId: "OK", + text: "OK", + type: SdcUiCommon.ButtonType.info, + callback: onOk, + closeModal: true + } as SdcUiComponents.ModalButtonComponent; + this.modalServiceSdcUI.openInfoModal(title, message, 'delete-modal', [okButton]); + }; } interface TableHeader { title: string; property: string; -}
\ No newline at end of file +} diff --git a/catalog-ui/src/app/ng2/services/data-type.service.ts b/catalog-ui/src/app/ng2/services/data-type.service.ts index 38714c96da..636217fb68 100644 --- a/catalog-ui/src/app/ng2/services/data-type.service.ts +++ b/catalog-ui/src/app/ng2/services/data-type.service.ts @@ -20,9 +20,15 @@ import * as _ from "lodash"; import {Inject, Injectable} from '@angular/core'; -import {DataTypeModel, DataTypesMap, PropertyFEModel, DerivedFEProperty, PropertyBEModel} from "app/models"; -import { DataTypesService } from "app/services/data-types-service"; -import { PROPERTY_DATA } from "app/utils"; +import { + DataTypeModel, + DataTypesMap, + DerivedFEProperty, + PropertyBEModel, + PropertyFEModel +} from "app/models"; +import {DataTypesService} from "app/services/data-types-service"; +import {PROPERTY_DATA} from "app/utils"; import {DerivedFEAttribute} from "../../models/attributes-outputs/derived-fe-attribute"; import {ISdcConfig} from "../config/sdc-config.config.factory"; import {SdcConfigToken} from "../config/sdc-config.config"; @@ -62,7 +68,7 @@ export class DataTypeService { } public getDataTypeByTypeName(typeName: string): DataTypeModel { - if(!this.dataTypes){ + if (!this.dataTypes) { this.dataTypes = this.dataTypeService.getAllDataTypes(); } if (!this.dataTypes[typeName]) console.log("MISSING Datatype: " + typeName); @@ -97,6 +103,15 @@ export class DataTypeService { return this.httpClient.put<PropertyBEModel>(url, property); } + public deleteProperty(dataTypeId: string, propertyId: string): Observable<Object> { + const url = `${this.dataTypeUrl}/${dataTypeId}/${propertyId}`; + let headers = new HttpHeaders({'USER_ID': this.authService.getLoggedinUser().userId}); + let options = {headers: headers}; + return this.httpClient.delete(url, options).map((res: Response) => { + return propertyId; + }); + } + public createImportedType(model: string, importingFile: File): Observable<any> { const url = `${this.dataTypeUploadUrl}/datatypesyaml`; const formData = new FormData(); @@ -109,7 +124,7 @@ export class DataTypeService { return this.httpClient.post<any>(url, formData, options); } - public getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName){ + public getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName) { // const property = this.dataTypes[rootPropertyType].properties.filter(property => // property.name == propertyName); // return property[0] && property[0].constraints ? property[0].constraints[0].validValues : null; @@ -121,7 +136,7 @@ export class DataTypeService { if (!dataTypeObj) return; if (dataTypeObj.properties) { dataTypeObj.properties.forEach((derivedProperty) => { - if(dataTypeObj.name !== PROPERTY_DATA.OPENECOMP_ROOT || derivedProperty.name !== PROPERTY_DATA.SUPPLEMENTAL_DATA){//The requirement is to not display the property supplemental_data + if (dataTypeObj.name !== PROPERTY_DATA.OPENECOMP_ROOT || derivedProperty.name !== PROPERTY_DATA.SUPPLEMENTAL_DATA) {//The requirement is to not display the property supplemental_data propertiesArray.push(new DerivedFEProperty(derivedProperty, parentName)); } let derivedDataTypeObj: DataTypeModel = this.getDataTypeByTypeName(derivedProperty.type); @@ -139,7 +154,7 @@ export class DataTypeService { if (!dataTypeObj) return; if (dataTypeObj.attributes) { dataTypeObj.attributes.forEach((derivedAttribute) => { - if(dataTypeObj.name !== PROPERTY_DATA.OPENECOMP_ROOT || derivedAttribute.name !== PROPERTY_DATA.SUPPLEMENTAL_DATA){//The requirement is to not display the property supplemental_data + if (dataTypeObj.name !== PROPERTY_DATA.OPENECOMP_ROOT || derivedAttribute.name !== PROPERTY_DATA.SUPPLEMENTAL_DATA) {//The requirement is to not display the property supplemental_data attributesArray.push(new DerivedFEAttribute(derivedAttribute, parentName)); } let derivedDataTypeObj: DataTypeModel = this.getDataTypeByTypeName(derivedAttribute.type); @@ -156,8 +171,8 @@ export class DataTypeService { * Checks for custom behavior for a given data type by checking if a function exists within data-type.service with that name * Additional custom behavior can be added by adding a function with the given dataType name */ - public checkForCustomBehavior = (property:PropertyFEModel) => { - let shortTypeName:string = property.type.split('.').pop(); + public checkForCustomBehavior = (property: PropertyFEModel) => { + let shortTypeName: string = property.type.split('.').pop(); if (this[shortTypeName]) { this[shortTypeName](property); //execute function for given type, pass property as param } diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java b/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java index 7a0feb9361..039fc8ed8a 100644 --- a/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java +++ b/common-app-api/src/main/java/org/openecomp/sdc/common/api/Constants.java @@ -19,6 +19,10 @@ */ package org.openecomp.sdc.common.api; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class Constants { public static final String APPLICATION_NAME = "application-name"; @@ -62,8 +66,6 @@ public final class Constants { public static final String RESOURCE_SUPPORTED_VERSION = "0.0.1"; public static final String ARTIFACT_ID_FORMAT = "%s:%s:%s"; // resourceName:resourceVersion:artifactName public static final String ADDITIONAL_TYPE_DEFINITIONS = "additional_type_definitions.yaml"; - - public static final String SERVICE_ARTIFACT_ID_FORMAT = "%s:%s:%s:%s"; // serviceName:serviceVersion:nodeTemplateName:artifactName public static final String CONTENT_DISPOSITION = "content-disposition"; public static final String DOWNLOAD_ARTIFACT_LOGIC_ATTR = "downloadArtifactLogic"; @@ -156,8 +158,6 @@ public final class Constants { public static final String INITIAL_COUNT = "initial_count"; public static final String VF_MODULE_TYPE = "vf_module_type"; public static final String VOLUME_GROUP = "volume_group"; - public static final String ASD_DEPLOYMENT_ITEM= "tosca.artifacts.asd.deploymentItem"; + public static final String ASD_DEPLOYMENT_ITEM = "tosca.artifacts.asd.deploymentItem"; - private Constants() { - } } |