diff options
author | andre.schmid <andre.schmid@est.tech> | 2022-10-12 18:14:23 +0100 |
---|---|---|
committer | Vasyl Razinkov <vasyl.razinkov@est.tech> | 2022-11-25 11:00:53 +0000 |
commit | 5e71c18416adc5c136ea9053a6bbac819da18c60 (patch) | |
tree | 51984434750fc8d7f80d25550196b7939b581553 /catalog-model | |
parent | 7ae4305a259d32520a5120a3e23710cbd2c9187c (diff) |
Implement create data type property
Allows to add a new data type property and visualize the properties
details.
Change-Id: Ib7bcd4b0bd8213dbe8ee8a3762a0636e22dc67eb
Issue-ID: SDC-4258
Signed-off-by: André Schmid <andre.schmid@est.tech>
Diffstat (limited to 'catalog-model')
7 files changed, 168 insertions, 49 deletions
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java deleted file mode 100644 index 6a647b1d44..0000000000 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/exception/OperationException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.exception; - -public class OperationException extends BusinessException { - - public OperationException(final String message) { - super(message); - } - - public OperationException(final Throwable cause) { - super(cause); - } - - public OperationException(final String message, final Throwable cause) { - super(message, cause); - } - -} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java index 75cacdd7a8..6b444b26ad 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/exception/supplier/DataTypeOperationExceptionSupplier.java @@ -24,14 +24,28 @@ package org.openecomp.sdc.be.exception.supplier; import java.util.function.Supplier; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.openecomp.sdc.be.exception.OperationException; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DataTypeOperationExceptionSupplier { public static Supplier<OperationException> unexpectedErrorWhileFetchingProperties(final String uniqueId) { - final String errorMessage = String.format("An unexpected error has occurred while retrieving the data type '%s' properties", uniqueId); - return () -> new OperationException(errorMessage); + return () -> new OperationException(ActionStatus.UNEXPECTED_ERROR, String.format("retrieving the data type '%s' properties", uniqueId)); + } + + public static Supplier<OperationException> dataTypeNotFound(final String dataTypeId) { + return () -> new OperationException(ActionStatus.DATA_TYPE_NOT_FOUND, dataTypeId); + } + + public static Supplier<OperationException> dataTypePropertyAlreadyExists(final String dataTypeId, final String propertyName) { + return () -> new OperationException(ActionStatus.DATA_TYPE_PROPERTY_ALREADY_EXISTS, dataTypeId, propertyName); + } + + public static Supplier<OperationException> unexpectedErrorWhileCreatingProperty(String dataTypeId, String propertyName) { + return () -> new OperationException(ActionStatus.UNEXPECTED_ERROR, + String.format("creating the property '%s' in the data type '%s'", propertyName, dataTypeId) + ); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java index bac73d9e1d..4144e1f5b6 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/dto/PropertyDefinitionDto.java @@ -30,7 +30,9 @@ public class PropertyDefinitionDto { private String uniqueId; private String type; + private String schemaType; private String name; + private String description; private Boolean required; private Object value; private Object defaultValue; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java index 8566f55339..67600a5dbe 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/PropertyDefinitionDtoMapper.java @@ -24,12 +24,17 @@ package org.openecomp.sdc.be.model.mapper; import com.google.gson.Gson; import java.util.ArrayList; import java.util.List; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class PropertyDefinitionDtoMapper { public static PropertyDefinition mapTo(final PropertyDefinitionDto propertyDefinitionDto) { @@ -38,11 +43,19 @@ public class PropertyDefinitionDtoMapper { propertyDefinition.setType(propertyDefinitionDto.getType()); propertyDefinition.setRequired(propertyDefinitionDto.getRequired()); propertyDefinition.setName(propertyDefinitionDto.getName()); + if (StringUtils.isNotBlank(propertyDefinitionDto.getSchemaType())) { + final PropertyDefinition schemaProperty = new PropertyDefinition(); + schemaProperty.setType(propertyDefinitionDto.getSchemaType()); + final SchemaDefinition schema = new SchemaDefinition(); + schema.setProperty(schemaProperty); + propertyDefinition.setSchema(schema); + } if (CollectionUtils.isNotEmpty(propertyDefinitionDto.getConstraints())) { final List<PropertyConstraint> propertyConstraints = new ArrayList<>(); propertyDefinition.setConstraints(propertyConstraints); propertyConstraints.addAll(propertyDefinitionDto.getConstraints()); } + propertyDefinition.setDescription(propertyDefinitionDto.getDescription()); propertyDefinition.setValue(new Gson().toJson(propertyDefinitionDto.getValue())); propertyDefinition.setDefaultValue(new Gson().toJson(propertyDefinitionDto.getDefaultValue())); return propertyDefinition; @@ -52,9 +65,11 @@ public class PropertyDefinitionDtoMapper { final var propertyDefinition = new PropertyDefinition(propertyDataDefinition); final var propertyDefinitionDto = new PropertyDefinitionDto(); propertyDefinitionDto.setUniqueId(propertyDefinition.getUniqueId()); + propertyDefinitionDto.setName(propertyDefinition.getName()); propertyDefinitionDto.setType(propertyDefinition.getType()); + propertyDefinitionDto.setDescription(propertyDefinition.getDescription()); propertyDefinitionDto.setRequired(propertyDefinition.getRequired()); - propertyDefinitionDto.setName(propertyDefinition.getName()); + propertyDefinitionDto.setSchemaType(propertyDefinition.getSchemaType()); if (CollectionUtils.isNotEmpty(propertyDefinition.getConstraints())) { final List<PropertyConstraint> propertyConstraints = new ArrayList<>(); propertyDefinitionDto.setConstraints(propertyConstraints); 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 4194ab70db..7cd042a27d 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 @@ -39,12 +39,16 @@ import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.exception.supplier.DataTypeOperationExceptionSupplier; import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException; +import org.openecomp.sdc.be.model.mapper.PropertyDefinitionDtoMapper; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.resources.data.DataTypeData; +import org.openecomp.sdc.be.resources.data.PropertyData; import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -204,4 +208,29 @@ public class DataTypeOperation extends AbstractOperation { return propertyDefinitions; } + public PropertyDefinitionDto createProperty(final String dataTypeId, final PropertyDefinitionDto propertyDefinitionDto) { + final String propertyName = propertyDefinitionDto.getName(); + LOGGER.debug("Adding property '{}' to data type '{}'.", propertyName, dataTypeId); + + getDataTypeByUid(dataTypeId).orElseThrow(DataTypeOperationExceptionSupplier.dataTypeNotFound(dataTypeId)); + + final Either<PropertyData, JanusGraphOperationStatus> resultEither = + propertyOperation.addPropertyToNodeType(propertyName, PropertyDefinitionDtoMapper.mapTo(propertyDefinitionDto), + NodeTypeEnum.DataType, dataTypeId, false); + if (resultEither.isRight()) { + final JanusGraphOperationStatus status = resultEither.right().value(); + LOGGER.debug("Could not create property '{}' on data type '{}'. JanusGraph status is '{}'", propertyName, dataTypeId, status); + if (status == JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION) { + throw DataTypeOperationExceptionSupplier.dataTypePropertyAlreadyExists(dataTypeId, propertyName).get(); + } + LOGGER.error("Could not create property '{}' on data type '{}'. JanusGraph status is '{}'", propertyName, dataTypeId, status); + throw DataTypeOperationExceptionSupplier.unexpectedErrorWhileCreatingProperty(dataTypeId, propertyName).get(); + } + LOGGER.debug("Property '{}' was added to data type '{}'.", propertyName, dataTypeId); + final PropertyData propertyData = resultEither.left().value(); + final PropertyDataDefinition propertyDataDefinition = propertyData.getPropertyDataDefinition(); + propertyDataDefinition.setName(propertyName); + return PropertyDefinitionDtoMapper.mapFrom(propertyDataDefinition); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java index 1068e31db6..cd87dd4fe7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java @@ -332,6 +332,13 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(String propertyName, PropertyDefinition propertyDefinition, NodeTypeEnum nodeType, String uniqueId) { + return addPropertyToNodeType(propertyName, propertyDefinition, nodeType, uniqueId, true); + } + + public Either<PropertyData, JanusGraphOperationStatus> addPropertyToNodeType(final String propertyName, + final PropertyDefinition propertyDefinition, + final NodeTypeEnum nodeType, final String uniqueId, + final boolean inTransaction) { List<PropertyConstraint> constraints = propertyDefinition.getConstraints(); propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(uniqueId, propertyName)); PropertyData propertyData = new PropertyData(propertyDefinition, convertConstraintsToString(constraints)); @@ -339,6 +346,9 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe Either<PropertyData, JanusGraphOperationStatus> createNodeResult = janusGraphGenericDao.createNode(propertyData, PropertyData.class); log.debug(AFTER_ADDING_PROPERTY_TO_GRAPH, propertyData); if (createNodeResult.isRight()) { + if (!inTransaction) { + janusGraphGenericDao.rollback(); + } JanusGraphOperationStatus operationStatus = createNodeResult.right().value(); log.error("Failed to add property {} to graph. status is {}", propertyName, operationStatus); return Either.right(operationStatus); @@ -350,10 +360,16 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe Either<GraphRelation, JanusGraphOperationStatus> createRelResult = janusGraphGenericDao.createRelation(uniqueIdData, propertyData, GraphEdgeLabels.PROPERTY, props); if (createRelResult.isRight()) { + if (!inTransaction) { + janusGraphGenericDao.rollback(); + } JanusGraphOperationStatus operationStatus = createNodeResult.right().value(); log.error(FAILED_TO_ASSOCIATE_RESOURCE_TO_PROPERTY_IN_GRAPH_STATUS_IS, uniqueId, propertyName, operationStatus); return Either.right(operationStatus); } + if (!inTransaction) { + janusGraphGenericDao.commit(); + } return Either.left(createNodeResult.left().value()); } diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java index 1f448fd875..26fb7658f1 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/DataTypeOperationTest.java @@ -19,7 +19,9 @@ package org.openecomp.sdc.be.model.operations.impl; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -42,14 +44,18 @@ import org.mockito.MockitoAnnotations; import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; -import org.openecomp.sdc.be.exception.OperationException; import org.openecomp.sdc.be.exception.supplier.DataTypeOperationExceptionSupplier; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.Model; import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException; +import org.openecomp.sdc.be.model.mapper.PropertyDefinitionDtoMapper; import org.openecomp.sdc.be.resources.data.DataTypeData; +import org.openecomp.sdc.be.resources.data.PropertyData; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration("classpath:application-context-test.xml") @@ -87,9 +93,10 @@ class DataTypeOperationTest { when(janusGraphGenericDao.getByCriteriaForModel(NodeTypeEnum.DataType, null, modelName, DataTypeData.class)) .thenReturn(Either.left(dataTypesWithModel)); final var dataTypesFound = dataTypeOperation.getAllDataTypeNodes(); - assertThat(dataTypesFound.size()).isEqualTo(4); - assertThat(dataTypesFound.containsAll(dataTypesWithoutModel)).isTrue(); - assertThat(dataTypesFound.containsAll(dataTypesWithModel)).isTrue(); + assertThat(dataTypesFound) + .hasSize(4) + .containsAll(dataTypesWithoutModel) + .containsAll(dataTypesWithModel); } @Test @@ -100,8 +107,9 @@ class DataTypeOperationTest { when(janusGraphGenericDao.getByCriteriaForModel(NodeTypeEnum.DataType, null, modelName, DataTypeData.class)) .thenReturn(Either.left(dataTypesWithModel)); final var dataTypesFound = dataTypeOperation.getAllDataTypeNodes(); - assertThat(dataTypesFound.size()).isEqualTo(2); - assertThat(dataTypesFound.containsAll(dataTypesWithModel)).isTrue(); + assertThat(dataTypesFound) + .hasSize(2) + .containsAll(dataTypesWithModel); assertThat(dataTypesFound.containsAll(dataTypesWithoutModel)).isFalse(); } @@ -110,7 +118,7 @@ class DataTypeOperationTest { when(janusGraphGenericDao.getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class)) .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND)); final var dataTypesFound = dataTypeOperation.getAllDataTypeNodes(); - assertThat(dataTypesFound.isEmpty()).isTrue(); + assertThat(dataTypesFound).isEmpty(); } @Test @@ -187,6 +195,79 @@ class DataTypeOperationTest { assertEquals(expectedException.getMessage(), actualException.getMessage()); } + @Test + void createPropertyTest_Success() { + final String dataTypeId = "uniqueId"; + final var property1 = new PropertyDefinitionDto(); + property1.setName("property1"); + final var propertyData = new PropertyData(); + final var propertyDataDefinition = new PropertyDataDefinition(); + propertyDataDefinition.setName("property1"); + propertyData.setPropertyDataDefinition(propertyDataDefinition); + when(janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeId, DataTypeData.class)) + .thenReturn(Either.left(new DataTypeData())); + when(propertyOperation.addPropertyToNodeType(eq(property1.getName()), any(PropertyDefinition.class), + eq(NodeTypeEnum.DataType), eq(dataTypeId), eq(false))) + .thenReturn(Either.left(propertyData)); + final PropertyDefinitionDto propertyDefinitionDto = dataTypeOperation.createProperty(dataTypeId, property1); + assertNotNull(propertyDefinitionDto); + assertEquals(property1.getName(), propertyDefinitionDto.getName()); + } + + @Test + void createPropertyTest_DataTypePropertyAlreadyExists() { + final String dataTypeId = "uniqueId"; + final var property1 = new PropertyDefinitionDto(); + property1.setName("property1"); + when(janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeId, DataTypeData.class)) + .thenReturn(Either.left(new DataTypeData())); + when(propertyOperation.addPropertyToNodeType(eq(property1.getName()), any(PropertyDefinition.class), + eq(NodeTypeEnum.DataType), eq(dataTypeId), eq(false))) + .thenReturn(Either.right(JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION)); + final OperationException actualException = assertThrows(OperationException.class, + () -> dataTypeOperation.createProperty(dataTypeId, property1)); + final OperationException expectedException = + DataTypeOperationExceptionSupplier.dataTypePropertyAlreadyExists(dataTypeId, property1.getName()).get(); + + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + + @Test + void createPropertyTest_DataTypeNotFound() { + final String dataTypeId = "uniqueId"; + final var property1 = new PropertyDefinitionDto(); + property1.setName("property1"); + when(janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeId, DataTypeData.class)) + .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND)); + final OperationException actualException = assertThrows(OperationException.class, + () -> dataTypeOperation.createProperty(dataTypeId, property1)); + final OperationException expectedException = + DataTypeOperationExceptionSupplier.dataTypeNotFound(dataTypeId).get(); + + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + + @Test + void createPropertyTest_UnexpectedError() { + final String dataTypeId = "uniqueId"; + final var property1 = new PropertyDefinitionDto(); + property1.setName("property1"); + when(janusGraphGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), dataTypeId, DataTypeData.class)) + .thenReturn(Either.left(new DataTypeData())); + when(propertyOperation.addPropertyToNodeType(eq(property1.getName()), any(PropertyDefinition.class), + eq(NodeTypeEnum.DataType), eq(dataTypeId), eq(false))) + .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR)); + final OperationException actualException = assertThrows(OperationException.class, + () -> dataTypeOperation.createProperty(dataTypeId, property1)); + final OperationException expectedException = + DataTypeOperationExceptionSupplier.unexpectedErrorWhileCreatingProperty(dataTypeId, property1.getName()).get(); + + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + private void initTestData() { model = new Model(modelName, ModelTypeEnum.NORMATIVE); final String TEST_DATA_TYPE_001 = "test.data.type001"; |