aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--catalog-be/pom.xml3
-rw-r--r--catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml22
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java63
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java65
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/exception/OperationExceptionMapper.java11
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java137
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ToscaModelImportCassandraDaoMock.java39
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java138
-rw-r--r--catalog-be/src/test/resources/modelImports/emptyModelImports.zipbin0 -> 186 bytes
-rw-r--r--catalog-be/src/test/resources/modelImports/modelWithSubFolderAndEmptyFolder.zipbin0 -> 1961 bytes
-rw-r--r--catalog-be/src/test/resources/paths/path-context.xml1
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java2
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitException.java27
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitExceptionProvider.java36
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/CassandraClient.java3
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaImportByModelAccessor.java33
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java106
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/SdcSchemaBuilder.java24
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java4
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/ToscaImportByModelTableDescription.java78
-rw-r--r--catalog-dao/src/test/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDaoTest.java152
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java50
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java93
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java160
-rw-r--r--common-be/src/main/java/org/openecomp/sdc/be/data/model/ToscaImportByModel.java40
-rw-r--r--common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/CapabilityDefinition.java57
-rw-r--r--common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/EntrySchema.java28
27 files changed, 1220 insertions, 152 deletions
diff --git a/catalog-be/pom.xml b/catalog-be/pom.xml
index 3f56c02afa..53af2c7b27 100644
--- a/catalog-be/pom.xml
+++ b/catalog-be/pom.xml
@@ -1221,8 +1221,7 @@
</outputDirectory>
<resources>
<resource>
- <directory>${project.parent.basedir}/catalog-be/target
- </directory>
+ <directory>${project.build.directory}</directory>
<includes>
<include>normatives.tar.gz</include>
</includes>
diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
index 2c6a0c852b..b277aeef2f 100644
--- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
+++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
@@ -2473,3 +2473,25 @@ errors:
message: "Error: Model name '%1' already exists.",
messageId: "SVC4144"
}
+
+ #---------SVC4145------------------------------
+ # %1 - "Model name"
+ INVALID_MODEL: {
+ code: 400,
+ message: "Invalid model '%1'.",
+ messageId: "SVC4145"
+ }
+
+ #---------SVC4146------------------------------
+ MODEL_IMPORTS_IS_EMPTY: {
+ code: 400,
+ message: "Given model imports zip is empty.",
+ messageId: "SVC4146"
+ }
+
+ #---------SVC4147------------------------------
+ COULD_NOT_READ_MODEL_IMPORTS: {
+ code: 400,
+ message: "Could not read imports zip.",
+ messageId: "SVC4147"
+ }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java
index 1ef4cef701..7f68a00a8b 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogic.java
@@ -18,17 +18,25 @@
*/
package org.openecomp.sdc.be.components.impl;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.commons.lang3.StringUtils;
import org.openecomp.sdc.be.model.Model;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
-
@Component("modelBusinessLogic")
public class ModelBusinessLogic {
- private static final Logger log = LoggerFactory.getLogger(ModelBusinessLogic.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ModelBusinessLogic.class);
private final ModelOperation modelOperation;
@Autowired
@@ -37,7 +45,56 @@ public class ModelBusinessLogic {
}
public Model createModel(final Model model) {
- log.debug("createModel: creating model {}", model);
+ LOGGER.debug("createModel: creating model {}", model);
return modelOperation.createModel(model, false);
}
+
+ public Optional<Model> findModel(final String modelName) {
+ if (StringUtils.isEmpty(modelName)) {
+ return Optional.empty();
+ }
+ return modelOperation.findModelByName(modelName);
+ }
+
+ public void createModelImports(final String modelName, final InputStream modelImportsZip) {
+ if (StringUtils.isEmpty(modelName)) {
+ throw ModelOperationExceptionSupplier.invalidModel(modelName).get();
+ }
+ if (modelImportsZip == null) {
+ throw ModelOperationExceptionSupplier.emptyModelImports().get();
+ }
+ if (findModel(modelName).isEmpty()) {
+ throw ModelOperationExceptionSupplier.invalidModel(modelName).get();
+ }
+
+ final var fileBytes = readBytes(modelImportsZip);
+ final Map<String, byte[]> zipFilesPathContentMap = unzipInMemory(fileBytes);
+ if (zipFilesPathContentMap.isEmpty()) {
+ throw ModelOperationExceptionSupplier.emptyModelImports().get();
+ }
+
+ modelOperation.createModelImports(modelName, zipFilesPathContentMap);
+ }
+
+ private Map<String, byte[]> unzipInMemory(final byte[] fileBytes) {
+ try {
+ return ZipUtils.readZip(fileBytes, false);
+ } catch (final ZipException e) {
+ throw ModelOperationExceptionSupplier.couldNotReadImports().get();
+ }
+ }
+
+ private byte[] readBytes(final InputStream modelImportsZip) {
+ try (final InputStream in = modelImportsZip; final ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ final var buffer = new byte[1024];
+ int len;
+ while ((len = in.read(buffer)) != -1) {
+ os.write(buffer, 0, len);
+ }
+ return os.toByteArray();
+ } catch (final IOException e) {
+ LOGGER.debug("Could not read the model imports zip", e);
+ throw ModelOperationExceptionSupplier.couldNotReadImports().get();
+ }
+ }
} \ No newline at end of file
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java
index f4fc883b4c..0c5e4aebd6 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ModelServlet.java
@@ -28,6 +28,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.tags.Tag;
+import java.io.InputStream;
import java.util.Arrays;
import javax.inject.Inject;
import javax.validation.Valid;
@@ -35,10 +36,13 @@ import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import org.glassfish.jersey.media.multipart.FormDataParam;
import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
import org.openecomp.sdc.be.components.impl.ResourceImportManager;
@@ -55,10 +59,10 @@ import org.openecomp.sdc.be.ui.model.ModelCreateRequest;
import org.openecomp.sdc.be.user.Role;
import org.openecomp.sdc.be.user.UserBusinessLogic;
import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.util.ValidationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestBody;
/**
* Root resource (exposed at "/" path)
@@ -85,34 +89,67 @@ public class ModelServlet extends AbstractValidationsServlet {
@POST
@Path("/model")
- @Consumes(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
- @Operation(description = "Create model", method = "POST", summary = "Returns created model", responses = {
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ @Operation(description = "Create a TOSCA model, along with its imports files", method = "POST", summary = "Create a TOSCA model", responses = {
@ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
@ApiResponse(responseCode = "201", description = "Model created"),
- @ApiResponse(responseCode = "403", description = "Restricted operation"),
@ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
- @ApiResponse(responseCode = "409", description = "Resource already exists")})
- @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "409", description = "Model already exists")})
public Response createModel(@Parameter(description = "model to be created", required = true)
- @Valid @RequestBody @NotNull final ModelCreateRequest modelCreateRequest,
- @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
- validateUser(userId);
+ @NotNull @Valid @FormDataParam("model") final ModelCreateRequest modelCreateRequest,
+ @Parameter(description = "the model TOSCA imports zipped", required = true)
+ @NotNull @FormDataParam("modelImportsZip") final InputStream modelImportsZip,
+ @HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
+ validateUser(ValidationUtils.sanitizeInputString(userId));
+ final var modelName = ValidationUtils.sanitizeInputString(modelCreateRequest.getName().trim());
try {
- final Model modelCreateResponse = modelBusinessLogic
+ final Model createdModel = modelBusinessLogic
.createModel(new JMapper<>(Model.class, ModelCreateRequest.class).getDestination(modelCreateRequest));
+ modelBusinessLogic.createModelImports(modelName, modelImportsZip);
return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED),
- RepresentationUtils.toRepresentation(modelCreateResponse));
+ RepresentationUtils.toRepresentation(createdModel));
+ } catch (final BusinessException e) {
+ throw e;
+ } catch (final Exception e) {
+ var errorMsg = String.format("Unexpected error while creating model '%s' imports", modelName);
+ BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
+ log.error(errorMsg, e);
+ return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+ }
+ }
+
+ @PUT
+ @Path("/model/imports")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @Produces(MediaType.APPLICATION_JSON)
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ @Operation(description = "Update a model TOSCA imports", method = "PUT", summary = "Update a model TOSCA imports", responses = {
+ @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+ @ApiResponse(responseCode = "204", description = "Model imports updated"),
+ @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+ @ApiResponse(responseCode = "403", description = "Restricted operation"),
+ @ApiResponse(responseCode = "404", description = "Model not found")})
+ public Response updateModelImports(@Parameter(description = "model to be created", required = true)
+ @NotNull @FormDataParam("modelName") String modelName,
+ @Parameter(description = "the model TOSCA imports zipped", required = true)
+ @NotNull @FormDataParam("modelImportsZip") final InputStream modelImportsZip,
+ @HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
+ validateUser(ValidationUtils.sanitizeInputString(userId));
+ modelName = ValidationUtils.sanitizeInputString(modelName);
+ try {
+ modelBusinessLogic.createModelImports(modelName, modelImportsZip);
} catch (final BusinessException e) {
throw e;
} catch (final Exception e) {
- var errorMsg = String
- .format("Unexpected error while creating model '%s'", modelCreateRequest.getName());
+ var errorMsg = String.format("Unexpected error while creating model '%s' imports", modelName);
BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
log.error(errorMsg, e);
return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
}
+ return Response.status(Status.NO_CONTENT).build();
}
private void validateUser(final String userId) {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/exception/OperationExceptionMapper.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/exception/OperationExceptionMapper.java
index 7c25f8aef8..062e03b0da 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/exception/OperationExceptionMapper.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/exception/OperationExceptionMapper.java
@@ -26,6 +26,7 @@ import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
import org.openecomp.sdc.be.servlets.builder.ServletResponseBuilder;
import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@@ -35,16 +36,22 @@ public class OperationExceptionMapper implements ExceptionMapper<OperationExcept
private final ServletResponseBuilder servletResponseBuilder;
private final ResponseFormatManager responseFormatManager;
- private static final Logger log = Logger.getLogger(OperationExceptionMapper.class);
+ private static final Logger LOGGER = Logger.getLogger(OperationExceptionMapper.class);
+ @Autowired
public OperationExceptionMapper(final ServletResponseBuilder servletResponseBuilder) {
this.servletResponseBuilder = servletResponseBuilder;
this.responseFormatManager = ResponseFormatManager.getInstance();
}
+ public OperationExceptionMapper(final ServletResponseBuilder servletResponseBuilder, final ResponseFormatManager responseFormatManager) {
+ this.servletResponseBuilder = servletResponseBuilder;
+ this.responseFormatManager = responseFormatManager;
+ }
+
@Override
public Response toResponse(final OperationException exception) {
- log.debug("Handling OperationException response", exception);
+ LOGGER.debug("Handling OperationException response", exception);
return servletResponseBuilder.buildErrorResponse(responseFormatManager.getResponseFormat(exception.getActionStatus(), exception.getParams()));
}
}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java
index 6c7bd5323f..b88bdfb01c 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ModelBusinessLogicTest.java
@@ -19,16 +19,25 @@
package org.openecomp.sdc.be.components.impl;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyMap;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
-import org.junit.jupiter.api.Order;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.TestInstance.Lifecycle;
-import org.junit.jupiter.api.TestMethodOrder;
+import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -36,10 +45,11 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.exception.BusinessException;
import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
-@TestInstance(Lifecycle.PER_CLASS)
-@TestMethodOrder(OrderAnnotation.class)
class ModelBusinessLogicTest {
@InjectMocks
@@ -47,8 +57,9 @@ class ModelBusinessLogicTest {
@Mock
private ModelOperation modelOperation;
private Model model;
+ private final Path modelImportsResourcePath = Path.of("src/test/resources/modelImports");
- @BeforeAll
+ @BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
initTestData();
@@ -59,7 +70,6 @@ class ModelBusinessLogicTest {
}
@Test
- @Order(1)
void createModelTest() {
when(modelOperation.createModel(model, false)).thenReturn(model);
final Model result = modelBusinessLogic.createModel(model);
@@ -68,13 +78,116 @@ class ModelBusinessLogicTest {
}
@Test
- @Order(2)
void createModelFailTest() {
when(modelOperation.createModel(model, false))
- .thenThrow(new OperationException(ActionStatus.MODEL_ALREADY_EXISTS, model.getName()));
+ .thenThrow(ModelOperationExceptionSupplier.modelAlreadyExists(model.getName()).get());
final BusinessException exception = assertThrows(BusinessException.class, () -> modelBusinessLogic.createModel(model));
assertThat(((OperationException) exception).getActionStatus().name()).isEqualTo(ActionStatus.MODEL_ALREADY_EXISTS.name());
assertThat(((OperationException) exception).getParams()).contains(model.getName());
}
+ @Test
+ void createModelImportsSuccessTest() throws IOException, ZipException {
+ final var modelId = "modelId";
+ final var resolve = modelImportsResourcePath.resolve("modelWithSubFolderAndEmptyFolder.zip");
+ final var zipBytes = Files.readAllBytes(resolve);
+ final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes);
+ final Map<String, byte[]> expectedZipMap = ZipUtils.readZip(zipBytes, false);
+
+ when(modelOperation.findModelByName(modelId)).thenReturn(Optional.of(new Model(modelId)));
+ doNothing().when(modelOperation).createModelImports(eq(modelId), anyMap());
+
+ modelBusinessLogic.createModelImports(modelId, byteArrayInputStream);
+
+ final ArgumentCaptor<Map<String, byte[]>> zipMapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
+ verify(modelOperation).createModelImports(eq(modelId), zipMapArgumentCaptor.capture());
+ expectedZipMap.keySet().forEach(key -> assertTrue(zipMapArgumentCaptor.getValue().containsKey(key), "Expecting import " + key));
+ }
+
+ @Test
+ void createModelImportsTest_invalidModel() {
+ //given an empty model
+ final var modelId = "";
+
+ final var emptyByteArrayInputStream = new ByteArrayInputStream(new byte[0]);
+ var actualOperationException = assertThrows(OperationException.class,
+ () -> modelBusinessLogic.createModelImports(modelId, emptyByteArrayInputStream));
+
+ var expectedOperationException = ModelOperationExceptionSupplier.invalidModel(modelId).get();
+ assertEquals(actualOperationException.getActionStatus(), expectedOperationException.getActionStatus());
+ assertEquals(actualOperationException.getParams().length, expectedOperationException.getParams().length);
+ assertEquals(actualOperationException.getParams()[0], expectedOperationException.getParams()[0]);
+
+ //given a null model
+ actualOperationException = assertThrows(OperationException.class,
+ () -> modelBusinessLogic.createModelImports(null, emptyByteArrayInputStream));
+
+ expectedOperationException = ModelOperationExceptionSupplier.invalidModel(null).get();
+ assertEquals(actualOperationException.getActionStatus(), expectedOperationException.getActionStatus());
+ assertEquals(actualOperationException.getParams().length, expectedOperationException.getParams().length);
+ assertEquals(actualOperationException.getParams()[0], expectedOperationException.getParams()[0]);
+ }
+
+ @Test
+ void createModelImportsTest_nullInputStream() {
+ final var modelId = "modelId";
+
+ final OperationException actualOperationException = assertThrows(OperationException.class,
+ () -> modelBusinessLogic.createModelImports(modelId, null));
+
+ final OperationException expectedOperationException = ModelOperationExceptionSupplier.emptyModelImports().get();
+ assertEquals(actualOperationException.getActionStatus(), expectedOperationException.getActionStatus());
+ assertEquals(actualOperationException.getParams().length, expectedOperationException.getParams().length);
+ }
+
+ @Test
+ void createModelImportsTest_emptyModelImports() throws IOException {
+ final var modelId = "modelId";
+
+ final var resolve = modelImportsResourcePath.resolve("emptyModelImports.zip");
+ final var zipBytes = Files.readAllBytes(resolve);
+ final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes);
+
+ when(modelOperation.findModelByName(modelId)).thenReturn(Optional.of(new Model(modelId)));
+
+ final OperationException actualOperationException = assertThrows(OperationException.class,
+ () -> modelBusinessLogic.createModelImports(modelId, byteArrayInputStream));
+
+ final OperationException expectedOperationException = ModelOperationExceptionSupplier.emptyModelImports().get();
+ assertEquals(actualOperationException.getActionStatus(), expectedOperationException.getActionStatus());
+ assertEquals(actualOperationException.getParams().length, expectedOperationException.getParams().length);
+ }
+
+ @Test
+ void createModelImportsTest_modelNotFound() {
+ final var modelId = "modelId";
+ final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[0]);
+
+ when(modelOperation.findModelByName(modelId)).thenReturn(Optional.empty());
+
+ final OperationException actualOperationException = assertThrows(OperationException.class,
+ () -> modelBusinessLogic.createModelImports(modelId, byteArrayInputStream));
+
+ final OperationException expectedOperationException = ModelOperationExceptionSupplier.invalidModel(modelId).get();
+ assertEquals(actualOperationException.getActionStatus(), expectedOperationException.getActionStatus());
+ assertEquals(actualOperationException.getParams().length, expectedOperationException.getParams().length);
+ }
+
+ @Test
+ void findModelSuccessTest() {
+ final var modelId = "modelId";
+ when(modelOperation.findModelByName(modelId)).thenReturn(Optional.of(new Model(modelId)));
+ final Optional<Model> actualModel = modelBusinessLogic.findModel(modelId);
+ assertTrue(actualModel.isPresent());
+ assertEquals(new Model(modelId), actualModel.get());
+ }
+
+ @Test
+ void findModelTest_emptyOrNullModelName() {
+ when(modelOperation.findModelByName(anyString())).thenReturn(Optional.of(new Model()));
+ var actualModel = modelBusinessLogic.findModel("");
+ assertTrue(actualModel.isEmpty());
+ actualModel = modelBusinessLogic.findModel(null);
+ assertTrue(actualModel.isEmpty());
+ }
} \ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ToscaModelImportCassandraDaoMock.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ToscaModelImportCassandraDaoMock.java
new file mode 100644
index 0000000000..9f293b1a1c
--- /dev/null
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/path/beans/ToscaModelImportCassandraDaoMock.java
@@ -0,0 +1,39 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.components.path.beans;
+
+import javax.annotation.PostConstruct;
+import org.openecomp.sdc.be.dao.cassandra.CassandraClient;
+import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
+import org.springframework.stereotype.Component;
+
+@Component("tosca-model-import-cassandra-dao")
+public class ToscaModelImportCassandraDaoMock extends ToscaModelImportCassandraDao {
+
+ public ToscaModelImportCassandraDaoMock(final CassandraClient cassandraClient) {
+ super(cassandraClient);
+ }
+
+ @PostConstruct
+ @Override
+ public void init() {
+
+ }
+}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java
index 34201d3c1f..5992be4e9d 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java
@@ -18,19 +18,28 @@
*/
package org.openecomp.sdc.be.servlets;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.InputStream;
+import java.nio.file.Path;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import javax.validation.ConstraintViolationException;
-import javax.ws.rs.core.Response;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.http.HttpStatus;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
@@ -46,6 +55,7 @@ import org.mockito.MockitoAnnotations;
import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
import org.openecomp.sdc.be.components.impl.ResourceImportManager;
+import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
import org.openecomp.sdc.be.components.validation.UserValidations;
import org.openecomp.sdc.be.config.ConfigurationManager;
import org.openecomp.sdc.be.config.SpringConfig;
@@ -55,6 +65,9 @@ import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.impl.ServletUtils;
import org.openecomp.sdc.be.impl.WebAppContextWrapper;
import org.openecomp.sdc.be.model.Model;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.servlets.builder.ServletResponseBuilder;
+import org.openecomp.sdc.be.servlets.exception.OperationExceptionMapper;
import org.openecomp.sdc.be.ui.model.ModelCreateRequest;
import org.openecomp.sdc.be.user.UserBusinessLogic;
import org.openecomp.sdc.common.api.ConfigurationSource;
@@ -100,13 +113,16 @@ class ModelServletTest extends JerseyTest {
@Mock
private UserValidations userValidations;
+ @Mock
+ private ResponseFormatManager responseFormatManager;
+
private Model model;
- private Response response;
private ModelCreateRequest modelCreateRequest;
+ private final Path rootPath = Path.of("/v1/catalog/model");
+ private final Path importsPath = rootPath.resolve("imports");
@BeforeAll
public void initClass() {
- MockitoAnnotations.openMocks(this);
when(request.getSession()).thenReturn(session);
when(session.getServletContext()).thenReturn(servletContext);
when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
@@ -145,6 +161,7 @@ class ModelServletTest extends JerseyTest {
@Override
protected ResourceConfig configure() {
+ MockitoAnnotations.openMocks(this);
forceSet(TestProperties.CONTAINER_PORT, "0");
final ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
return new ResourceConfig(ModelServlet.class)
@@ -158,51 +175,132 @@ class ModelServletTest extends JerseyTest {
bind(servletUtils).to(ServletUtils.class);
bind(resourceImportManager).to(ResourceImportManager.class);
bind(modelBusinessLogic).to(ModelBusinessLogic.class);
+ bind(userValidations).to(UserValidations.class);
}
})
+ .register(new OperationExceptionMapper(new ServletResponseBuilder(), responseFormatManager))
+ .register(MultiPartFeature.class)
.property("contextConfig", context);
}
+ @Override
+ protected void configureClient(final ClientConfig config) {
+ config.register(MultiPartFeature.class);
+ }
+
@Test
- void createModelSuccessTest() {
+ void createModelSuccessTest() throws JsonProcessingException {
when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat);
when(modelBusinessLogic.createModel(any(Model.class))).thenReturn(model);
- response = modelServlet.createModel(modelCreateRequest, USER_ID);
- assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200);
+ final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(modelCreateRequest));
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
- void createModelFailTest() {
+ void createModelFailTest() throws JsonProcessingException {
when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
when(modelBusinessLogic.createModel(any(Model.class))).thenReturn(model);
- response = modelServlet.createModel(modelCreateRequest, USER_ID);
- assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(modelCreateRequest));
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
}
@Test
- void createModelFailWithModelNameEmptyTest() {
+ void createModelFailWithModelNameEmptyTest() throws JsonProcessingException {
when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
modelCreateRequest.setName(StringUtils.EMPTY);
- final Exception exception = assertThrows(ConstraintViolationException.class, () -> modelServlet.createModel(modelCreateRequest, USER_ID));
- assertThat(exception.getMessage()).isEqualTo("Model name cannot be empty");
+ final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(modelCreateRequest));
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
@Test
- void createModelFailWithModelNameNullTest() {
+ void createModelFailWithModelNameNullTest() throws JsonProcessingException {
when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
modelCreateRequest.setName(null);
- final Exception exception = assertThrows(ConstraintViolationException.class, () -> modelServlet.createModel(modelCreateRequest, USER_ID));
- assertThat(exception.getMessage()).isEqualTo("Model name cannot be null");
+ final var modelFile = new byte[0];
+ final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(modelFile, parseToJsonString(modelCreateRequest));
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
@Test
- void createModelThrowsBusinessExceptionTest() {
+ void createModelThrowsBusinessExceptionTest() throws JsonProcessingException {
+ final var modelFile = new byte[0];
+ final String modelCreateAsJson = parseToJsonString(modelCreateRequest);
+ final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(modelFile, modelCreateAsJson);
when(modelBusinessLogic.createModel(model)).thenThrow(new BusinessException() {});
- assertThrows(BusinessException.class, () -> modelServlet.createModel(modelCreateRequest, USER_ID));
+
+ final var response = target(rootPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+ }
+
+ @Test
+ void updateModelImportsSuccessTest() {
+ final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart("model1", new byte[0]);
+
+ final var response = target(importsPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .put(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
+ }
+
+ @Test
+ void updateModelImports_businessException() {
+ final var modelId = "model1";
+ final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart(modelId, new byte[0]);
+ final OperationException operationException = new OperationException(ActionStatus.INVALID_MODEL, modelId);
+ doThrow(operationException).when(modelBusinessLogic).createModelImports(eq(modelId), any(InputStream.class));
+ when(responseFormatManager.getResponseFormat(ActionStatus.INVALID_MODEL, modelId))
+ .thenReturn(new ResponseFormat(Status.BAD_REQUEST.getStatusCode()));
+ final var response = target(importsPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .put(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+ }
+
+ @Test
+ void updateModelImports_unknownException() {
+ final var modelName = "model1";
+ final FormDataMultiPart formDataMultiPart = buildUpdateFormDataMultiPart(modelName, new byte[0]);
+ doThrow(new RuntimeException()).when(modelBusinessLogic).createModelImports(eq(modelName), any(InputStream.class));
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
+ final var response = target(importsPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, USER_ID)
+ .put(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
+ assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+ }
+
+ private FormDataMultiPart buildUpdateFormDataMultiPart(final String modelName, final byte[] importFilesZip) {
+ return new FormDataMultiPart()
+ .field("modelName", modelName)
+ .field("modelImportsZip", importFilesZip, MediaType.MULTIPART_FORM_DATA_TYPE);
+ }
+
+ private FormDataMultiPart buildCreateFormDataMultiPart(final byte[] modelFile, final String modelCreateAsJson) {
+ return new FormDataMultiPart()
+ .field("model", modelCreateAsJson, MediaType.APPLICATION_JSON_TYPE)
+ .field("modelImportsZip", modelFile, MediaType.MULTIPART_FORM_DATA_TYPE);
+ }
+
+ private String parseToJsonString(final Object object) throws JsonProcessingException {
+ return new ObjectMapper().writeValueAsString(object);
}
} \ No newline at end of file
diff --git a/catalog-be/src/test/resources/modelImports/emptyModelImports.zip b/catalog-be/src/test/resources/modelImports/emptyModelImports.zip
new file mode 100644
index 0000000000..323472535d
--- /dev/null
+++ b/catalog-be/src/test/resources/modelImports/emptyModelImports.zip
Binary files differ
diff --git a/catalog-be/src/test/resources/modelImports/modelWithSubFolderAndEmptyFolder.zip b/catalog-be/src/test/resources/modelImports/modelWithSubFolderAndEmptyFolder.zip
new file mode 100644
index 0000000000..281e3fc3c1
--- /dev/null
+++ b/catalog-be/src/test/resources/modelImports/modelWithSubFolderAndEmptyFolder.zip
Binary files differ
diff --git a/catalog-be/src/test/resources/paths/path-context.xml b/catalog-be/src/test/resources/paths/path-context.xml
index 3b472dd16f..7994b0c44d 100644
--- a/catalog-be/src/test/resources/paths/path-context.xml
+++ b/catalog-be/src/test/resources/paths/path-context.xml
@@ -80,6 +80,7 @@ Modifications copyright (c) 2018 Nokia
<bean id="userOperation" class="org.openecomp.sdc.be.facade.operations.UserOperation"/>
<bean id="dmaapProducerHealth" class="org.openecomp.sdc.be.catalog.impl.DmaapProducerHealth"/>
<bean id="feature_toggle_dao" class="org.openecomp.sdc.be.components.path.beans.FeatureToggleDaoMock"/>
+ <bean id="tosca-model-import-cassandra-dao" class="org.openecomp.sdc.be.components.path.beans.ToscaModelImportCassandraDaoMock"/>
<bean name="httpClient" class="org.apache.http.impl.client.HttpClients" factory-method="createDefault" />
<bean class="org.openecomp.sdc.be.components.attribute.AttributeDeclarationOrchestrator"/>
<bean class="org.openecomp.sdc.be.components.attribute.ComponentInstanceOutputAttributeDeclarator"/>
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
index 1ebaeab54f..ed448c18d4 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
@@ -52,7 +52,7 @@ public enum ActionStatus {
// Category related
COMPONENT_MISSING_CATEGORY, COMPONENT_INVALID_CATEGORY, COMPONENT_ELEMENT_INVALID_NAME_FORMAT, COMPONENT_ELEMENT_INVALID_NAME_LENGTH, COMPONENT_CATEGORY_ALREADY_EXISTS, COMPONENT_CATEGORY_NOT_FOUND, COMPONENT_SUB_CATEGORY_NOT_FOUND_FOR_CATEGORY, COMPONENT_SUB_CATEGORY_EXISTS_FOR_CATEGORY, COMPONENT_GROUPING_EXISTS_FOR_SUB_CATEGORY,
// Model related
- MODEL_ALREADY_EXISTS,
+ MODEL_ALREADY_EXISTS, INVALID_MODEL, MODEL_IMPORTS_IS_EMPTY, COULD_NOT_READ_MODEL_IMPORTS,
// Service API URL
INVALID_SERVICE_API_URL,
// Property related
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitException.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitException.java
new file mode 100644
index 0000000000..b1ee5f0ae1
--- /dev/null
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.dao.api.exception;
+
+public class CassandraDaoInitException extends RuntimeException {
+
+ public CassandraDaoInitException(final String message) {
+ super(message);
+ }
+}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitExceptionProvider.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitExceptionProvider.java
new file mode 100644
index 0000000000..4fec8fbdd9
--- /dev/null
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/exception/CassandraDaoInitExceptionProvider.java
@@ -0,0 +1,36 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.dao.api.exception;
+
+import java.util.function.Supplier;
+import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
+
+public class CassandraDaoInitExceptionProvider {
+
+ private CassandraDaoInitExceptionProvider() {
+
+ }
+
+ public static Supplier<CassandraDaoInitException> keySpaceConnectError(final String keyspace, final CassandraOperationStatus cassandraOperationStatus) {
+ var errorMsg = String.format("Could not connect to keyspace '%s'. Operation status was '%s'", keyspace, cassandraOperationStatus);
+ return () -> new CassandraDaoInitException(errorMsg);
+ }
+
+}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/CassandraClient.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/CassandraClient.java
index 624f9b44f2..25a6b49bba 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/CassandraClient.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/CassandraClient.java
@@ -34,6 +34,7 @@ import java.util.List;
import javax.annotation.PreDestroy;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
import org.openecomp.sdc.common.log.wrappers.Logger;
import org.springframework.stereotype.Component;
@@ -155,7 +156,7 @@ public class CassandraClient {
Mapper<T> mapper = manager.mapper(clazz);
mapper.save(entity);
} catch (Exception e) {
- logger.debug("Failed to save entity [{}], error :", entity, e);
+ logger.error(EcompLoggerErrorCode.DATA_ERROR, CassandraClient.class.getName(), "Failed to save entity [{}], error :", entity, e);
return CassandraOperationStatus.GENERAL_ERROR;
}
return CassandraOperationStatus.OK;
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaImportByModelAccessor.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaImportByModelAccessor.java
new file mode 100644
index 0000000000..eb54bd7fca
--- /dev/null
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaImportByModelAccessor.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.dao.cassandra;
+
+import com.datastax.driver.mapping.Result;
+import com.datastax.driver.mapping.annotations.Accessor;
+import com.datastax.driver.mapping.annotations.Param;
+import com.datastax.driver.mapping.annotations.Query;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+
+@Accessor
+public interface ToscaImportByModelAccessor {
+
+ @Query("SELECT * FROM sdcartifact.tosca_import_by_model WHERE model_id = :modelId")
+ Result<ToscaImportByModel> findAllByModel(@Param("modelId") String modelId);
+}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java
new file mode 100644
index 0000000000..a8b1ec635d
--- /dev/null
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDao.java
@@ -0,0 +1,106 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.dao.cassandra;
+
+import static java.util.function.Predicate.not;
+
+import com.datastax.driver.core.Session;
+import com.datastax.driver.mapping.Mapper;
+import com.datastax.driver.mapping.MappingManager;
+import fj.data.Either;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.dao.api.exception.CassandraDaoInitException;
+import org.openecomp.sdc.be.dao.api.exception.CassandraDaoInitExceptionProvider;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingTypesConstants;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("tosca-model-import-cassandra-dao")
+public class ToscaModelImportCassandraDao extends CassandraDao {
+
+ private static final Logger LOGGER = Logger.getLogger(ToscaModelImportCassandraDao.class.getName());
+
+ private ToscaImportByModelAccessor toscaImportByModelAccessor;
+ private Mapper<ToscaImportByModel> toscaImportByModelMapper;
+
+ @Autowired
+ public ToscaModelImportCassandraDao(final CassandraClient cassandraClient) {
+ super(cassandraClient);
+ }
+
+ /**
+ * For test purposes.
+ *
+ * @param toscaImportByModelAccessor the sdcartifact.tosca_import_by_model accessor
+ */
+ ToscaModelImportCassandraDao(final ToscaImportByModelAccessor toscaImportByModelAccessor,
+ final Mapper<ToscaImportByModel> toscaImportByModelMapper) {
+ super(null);
+ this.toscaImportByModelAccessor = toscaImportByModelAccessor;
+ this.toscaImportByModelMapper = toscaImportByModelMapper;
+ }
+
+ @PostConstruct
+ public void init() {
+ final var keyspace = AuditingTypesConstants.ARTIFACT_KEYSPACE;
+ if (!client.isConnected()) {
+ LOGGER.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaModelImportCassandraDao.class.getName(), "Cassandra client isn't connected");
+ return;
+ }
+ final Either<ImmutablePair<Session, MappingManager>, CassandraOperationStatus> connectionResult = client.connect(keyspace);
+ if (connectionResult.isRight()) {
+ final CassandraDaoInitException exception =
+ CassandraDaoInitExceptionProvider.keySpaceConnectError(keyspace, connectionResult.right().value()).get();
+ LOGGER.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaModelImportCassandraDao.class.getName(), exception.getMessage());
+ throw exception;
+ }
+ session = connectionResult.left().value().getLeft();
+ manager = connectionResult.left().value().getRight();
+ toscaImportByModelMapper = manager.mapper(ToscaImportByModel.class);
+ toscaImportByModelAccessor = manager.createAccessor(ToscaImportByModelAccessor.class);
+ LOGGER.info("{} successfully initialized", ToscaModelImportCassandraDao.class.getName());
+ }
+
+ public void importAll(final String modelId, final List<ToscaImportByModel> toscaImportByModelList) {
+ final List<ToscaImportByModel> importOfModelList = toscaImportByModelList.stream()
+ .filter(toscaImportByModel -> modelId.equals(toscaImportByModel.getModelId()))
+ .collect(Collectors.toList());
+ final List<ToscaImportByModel> actualImportOfModelList = toscaImportByModelAccessor.findAllByModel(modelId).all();
+ final List<ToscaImportByModel> removedImportList = actualImportOfModelList.stream()
+ .filter(not(importOfModelList::contains))
+ .collect(Collectors.toList());
+
+ importOfModelList.forEach(toscaImportByModelMapper::save);
+ removedImportList.forEach(toscaImportByModel ->
+ toscaImportByModelMapper.delete(toscaImportByModel.getModelId(), toscaImportByModel.getFullPath())
+ );
+ }
+
+ public List<ToscaImportByModel> findAllByModel(final String modelId) {
+ return toscaImportByModelAccessor.findAllByModel(modelId).all();
+ }
+
+}
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/SdcSchemaBuilder.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/SdcSchemaBuilder.java
index 0c6bb453ae..c0c12aa0b2 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/SdcSchemaBuilder.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/SdcSchemaBuilder.java
@@ -31,10 +31,12 @@ import com.datastax.driver.core.schemabuilder.Alter;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.core.schemabuilder.SchemaStatement;
+import com.datastax.oss.driver.shaded.guava.common.base.Function;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -112,17 +114,17 @@ public class SdcSchemaBuilder {
* the method creats all the tables and indexes thet do not already exist
*
* @param iTableDescriptions: a list of table description we want to create
- * @param keyspaceMetadate: the current tables that exist in the cassandra under this keyspace
+ * @param keyspaceMetadata: the current tables that exist in the cassandra under this keyspace
* @param session: the session object used for the execution of the query.
* @param existingTablesMetadata the current tables columns that exist in the cassandra under this keyspace
*/
- private static void createTables(List<ITableDescription> iTableDescriptions, Map<String, List<String>> keyspaceMetadate, Session session,
+ private static void createTables(List<ITableDescription> iTableDescriptions, Map<String, List<String>> keyspaceMetadata, Session session,
Map<String, List<String>> existingTablesMetadata) {
for (ITableDescription tableDescription : iTableDescriptions) {
String tableName = tableDescription.getTableName().toLowerCase();
Map<String, ImmutablePair<DataType, Boolean>> columnDescription = tableDescription.getColumnDescription();
log.info("creating tables:{}.", tableName);
- if (keyspaceMetadate == null || !keyspaceMetadate.keySet().contains(tableName)) {
+ if (keyspaceMetadata == null || !keyspaceMetadata.containsKey(tableName)) {
Create create = SchemaBuilder.createTable(tableDescription.getKeyspace(), tableDescription.getTableName());
for (ImmutablePair<String, DataType> key : tableDescription.primaryKeys()) {
create.addPartitionKey(key.getLeft(), key.getRight());
@@ -132,9 +134,15 @@ public class SdcSchemaBuilder {
create.addClusteringColumn(key.getLeft(), key.getRight());
}
}
- for (Map.Entry<String, ImmutablePair<DataType, Boolean>> entry : columnDescription.entrySet()) {
- create.addColumn(entry.getKey(), entry.getValue().getLeft());
- }
+ final Function<Entry<String, ?>, Boolean> notPrimaryKeyFilter = (Entry<String, ?> entry) -> {
+ if (entry == null) {
+ return true;
+ }
+ return tableDescription.primaryKeys().stream().noneMatch(primaryKeyPair -> primaryKeyPair.getLeft().equals(entry.getKey()));
+ };
+ columnDescription.entrySet().stream()
+ .filter(notPrimaryKeyFilter::apply)
+ .forEach(entry -> create.addColumn(entry.getKey(), entry.getValue().getLeft()));
log.trace("exacuting :{}", create);
session.execute(create);
log.info("table:{} created successfully.", tableName);
@@ -142,8 +150,8 @@ public class SdcSchemaBuilder {
log.info("table:{} already exists, skipping.", tableName);
alterTable(session, existingTablesMetadata, tableDescription, tableName, columnDescription);
}
- log.info("keyspacemetadata:{}", keyspaceMetadate);
- List<String> indexNames = (keyspaceMetadate != null && keyspaceMetadate.get(tableName) != null ? keyspaceMetadate.get(tableName)
+ log.info("keyspacemetadata:{}", keyspaceMetadata);
+ List<String> indexNames = (keyspaceMetadata != null && keyspaceMetadata.get(tableName) != null ? keyspaceMetadata.get(tableName)
: new ArrayList<>());
log.info("table:{} creating indexes.", tableName);
for (Map.Entry<String, ImmutablePair<DataType, Boolean>> description : columnDescription.entrySet()) {
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java
index 4c3c8fab2d..710a9a2921 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/Table.java
@@ -37,6 +37,7 @@ import org.openecomp.sdc.be.dao.cassandra.schema.tables.MigrationTasksTableDescr
import org.openecomp.sdc.be.dao.cassandra.schema.tables.OperationalEnvironmentsTableDescription;
import org.openecomp.sdc.be.dao.cassandra.schema.tables.ResAdminEventTableDescription;
import org.openecomp.sdc.be.dao.cassandra.schema.tables.SdcSchemaFilesTableDescription;
+import org.openecomp.sdc.be.dao.cassandra.schema.tables.ToscaImportByModelTableDescription;
import org.openecomp.sdc.be.dao.cassandra.schema.tables.UserAccessEventTableDescription;
import org.openecomp.sdc.be.dao.cassandra.schema.tables.UserAdminEventTableDescription;
@@ -61,7 +62,8 @@ public enum Table {
SDC_REPO(new MigrationTasksTableDescription()),
SDC_OPERATIONAL_ENVIRONMENT(new OperationalEnvironmentsTableDescription()),
AUDIT_ECOMP_OPERATIONAL_ENVIRONMENT(new EcompOperationalEnvironmentEventTableDesc()),
- FEATURE_TOGGLE_STATE(new FeatureToggleEventTableDesc());
+ FEATURE_TOGGLE_STATE(new FeatureToggleEventTableDesc()),
+ TOSCA_IMPORT_BY_MODEL(new ToscaImportByModelTableDescription());
// @formatter:on
ITableDescription tableDescription;
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/ToscaImportByModelTableDescription.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/ToscaImportByModelTableDescription.java
new file mode 100644
index 0000000000..5b67136285
--- /dev/null
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/cassandra/schema/tables/ToscaImportByModelTableDescription.java
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.dao.cassandra.schema.tables;
+
+import com.datastax.driver.core.DataType;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.dao.cassandra.schema.ITableDescription;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingTypesConstants;
+
+public class ToscaImportByModelTableDescription implements ITableDescription {
+
+ private static final String MODEL_ID = "model_id";
+ private static final String FULL_PATH = "full_path";
+
+ @Override
+ public List<ImmutablePair<String, DataType>> primaryKeys() {
+ return List.of(
+ new ImmutablePair<>(MODEL_ID, DataType.varchar()),
+ new ImmutablePair<>(FULL_PATH, DataType.varchar())
+ );
+ }
+
+ @Override
+ public List<ImmutablePair<String, DataType>> clusteringKeys() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Map<String, ImmutablePair<DataType, Boolean>> getColumnDescription() {
+ return Stream.of(SdcSchemaFilesFieldsDescription.values())
+ .collect(Collectors.toMap(SdcSchemaFilesFieldsDescription::getName, field -> new ImmutablePair<>(field.type, field.indexed)));
+ }
+
+ @Override
+ public String getKeyspace() {
+ return AuditingTypesConstants.ARTIFACT_KEYSPACE;
+ }
+
+ @Override
+ public String getTableName() {
+ return "tosca_import_by_model";
+ }
+
+ @Getter
+ @AllArgsConstructor
+ enum SdcSchemaFilesFieldsDescription {
+ MODEL_ID("model_id", DataType.varchar(), true),
+ CONTENT("content", DataType.varchar(), false);
+
+ private final String name;
+ private final DataType type;
+ private final boolean indexed;
+ }
+}
diff --git a/catalog-dao/src/test/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDaoTest.java b/catalog-dao/src/test/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDaoTest.java
new file mode 100644
index 0000000000..cddf3a2708
--- /dev/null
+++ b/catalog-dao/src/test/java/org/openecomp/sdc/be/dao/cassandra/ToscaModelImportCassandraDaoTest.java
@@ -0,0 +1,152 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.dao.cassandra;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.datastax.driver.core.Session;
+import com.datastax.driver.mapping.Mapper;
+import com.datastax.driver.mapping.MappingManager;
+import com.datastax.driver.mapping.Result;
+import fj.data.Either;
+import java.util.List;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.dao.api.exception.CassandraDaoInitException;
+import org.openecomp.sdc.be.dao.api.exception.CassandraDaoInitExceptionProvider;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingTypesConstants;
+
+class ToscaModelImportCassandraDaoTest {
+
+ @Mock
+ private CassandraClient cassandraClient;
+
+ @InjectMocks
+ private ToscaModelImportCassandraDao toscaModelImportCassandraDao;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ MockitoAnnotations.openMocks(this);
+ }
+
+ @Test
+ void findAllByModelTest() {
+ final var toscaImportByModelAccessorMock = mock(ToscaImportByModelAccessor.class);
+ toscaModelImportCassandraDao = new ToscaModelImportCassandraDao(toscaImportByModelAccessorMock, null);
+ final var modelId = "modelId";
+ final ToscaImportByModel toscaImportByModel1 = new ToscaImportByModel();
+ final ToscaImportByModel toscaImportByModel2 = new ToscaImportByModel();
+ final List<ToscaImportByModel> expectedImportModelList = List.of(toscaImportByModel1, toscaImportByModel2);
+
+ final Result<ToscaImportByModel> result = mock(Result.class);
+ when(result.all()).thenReturn(expectedImportModelList);
+ when(toscaImportByModelAccessorMock.findAllByModel(modelId)).thenReturn(result);
+
+ final List<ToscaImportByModel> actualImportModelList = toscaModelImportCassandraDao.findAllByModel(modelId);
+ assertEquals(expectedImportModelList.size(), actualImportModelList.size());
+ assertTrue(actualImportModelList.contains(toscaImportByModel1));
+ assertTrue(actualImportModelList.contains(toscaImportByModel2));
+ }
+
+ @Test
+ void importAllTest() {
+ final var toscaImportByModelAccessorMock = mock(ToscaImportByModelAccessor.class);
+ final Mapper<ToscaImportByModel> toscaImportByModelMapperMock = mock(Mapper.class);
+ toscaModelImportCassandraDao = new ToscaModelImportCassandraDao(toscaImportByModelAccessorMock, toscaImportByModelMapperMock);
+
+ final var modelId = "modelId";
+ final var toscaImportByModel1 = createToscaModelByImport(modelId, "path/model/1");
+ final var toscaImportByModel2 = createToscaModelByImport(modelId, "path/model/2");
+ final var toscaImportByModel3 = createToscaModelByImport(modelId, "path/model/3");
+ final var toscaImportByModelWrongModel = createToscaModelByImport("otherModel", "path/wrong-model/1");
+ final var importModelList = List.of(toscaImportByModel1, toscaImportByModel2, toscaImportByModel3);
+
+ final var toscaImportByModelDatabase1 = createToscaModelByImport(modelId, "toscaImportByModelDatabase1");
+ final Result<ToscaImportByModel> findAllByModelResult = mock(Result.class);
+ when(findAllByModelResult.all()).thenReturn(List.of(toscaImportByModel1, toscaImportByModelDatabase1));
+ when(toscaImportByModelAccessorMock.findAllByModel(modelId)).thenReturn(findAllByModelResult);
+
+ toscaModelImportCassandraDao.importAll(modelId, importModelList);
+
+ verify(toscaImportByModelMapperMock).save(toscaImportByModel1);
+ verify(toscaImportByModelMapperMock).save(toscaImportByModel2);
+ verify(toscaImportByModelMapperMock).save(toscaImportByModel3);
+ verify(toscaImportByModelMapperMock, never()).save(toscaImportByModelWrongModel);
+ verify(toscaImportByModelMapperMock).delete(toscaImportByModelDatabase1.getModelId(), toscaImportByModelDatabase1.getFullPath());
+ verify(toscaImportByModelMapperMock, never()).delete(toscaImportByModel1.getModelId(), toscaImportByModel1.getFullPath());
+ verify(toscaImportByModelMapperMock, never()).delete(toscaImportByModel2.getModelId(), toscaImportByModel2.getFullPath());
+ verify(toscaImportByModelMapperMock, never()).delete(toscaImportByModel3.getModelId(), toscaImportByModel3.getFullPath());
+ verify(toscaImportByModelMapperMock, never()).delete(toscaImportByModelWrongModel.getModelId(), toscaImportByModelWrongModel.getFullPath());
+ }
+
+ @Test
+ void initSuccessTest() {
+ toscaModelImportCassandraDao = new ToscaModelImportCassandraDao(cassandraClient);
+ when(cassandraClient.isConnected()).thenReturn(true);
+ final Session sessionMock = mock(Session.class);
+ final MappingManager mappingManagerMock = mock(MappingManager.class);
+ when(cassandraClient.connect(AuditingTypesConstants.ARTIFACT_KEYSPACE)).thenReturn(Either.left(new ImmutablePair<>(sessionMock, mappingManagerMock)));
+ toscaModelImportCassandraDao.init();
+ verify(cassandraClient).connect(AuditingTypesConstants.ARTIFACT_KEYSPACE);
+ verify(mappingManagerMock).mapper(ToscaImportByModel.class);
+ verify(mappingManagerMock).createAccessor(ToscaImportByModelAccessor.class);
+ }
+
+ @Test
+ void initTest_clientNotConnected() {
+ toscaModelImportCassandraDao = new ToscaModelImportCassandraDao(cassandraClient);
+ when(cassandraClient.isConnected()).thenReturn(false);
+ toscaModelImportCassandraDao.init();
+ verify(cassandraClient, never()).connect(anyString());
+ }
+
+ @Test
+ void initTest_keyspaceConnectionFailure() {
+ toscaModelImportCassandraDao = new ToscaModelImportCassandraDao(cassandraClient);
+ when(cassandraClient.isConnected()).thenReturn(true);
+ when(cassandraClient.connect(AuditingTypesConstants.ARTIFACT_KEYSPACE))
+ .thenReturn(Either.right(CassandraOperationStatus.KEYSPACE_NOT_CONNECTED));
+
+ final CassandraDaoInitException actualException = assertThrows(CassandraDaoInitException.class, () -> toscaModelImportCassandraDao.init());
+
+ final CassandraDaoInitException expectedException = CassandraDaoInitExceptionProvider
+ .keySpaceConnectError(AuditingTypesConstants.ARTIFACT_KEYSPACE, CassandraOperationStatus.KEYSPACE_NOT_CONNECTED).get();
+ assertEquals(expectedException.getMessage(), actualException.getMessage());
+ }
+
+ private ToscaImportByModel createToscaModelByImport(final String modelId, final String path) {
+ final var toscaImportByModel3 = new ToscaImportByModel();
+ toscaImportByModel3.setModelId(modelId);
+ toscaImportByModel3.setFullPath(path);
+ return toscaImportByModel3;
+ }
+} \ No newline at end of file
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java
new file mode 100644
index 0000000000..c2ad071d13
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ModelOperationExceptionSupplier.java
@@ -0,0 +1,50 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.model.jsonjanusgraph.operations.exception;
+
+import java.util.function.Supplier;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+
+/**
+ * Supplies operation exception needed by the the Model logic
+ */
+public class ModelOperationExceptionSupplier {
+
+ private ModelOperationExceptionSupplier() {
+
+ }
+
+ public static Supplier<OperationException> invalidModel(final String modelName) {
+ return () -> new OperationException(ActionStatus.INVALID_MODEL, modelName);
+ }
+
+ public static Supplier<OperationException> emptyModelImports() {
+ return () -> new OperationException(ActionStatus.MODEL_IMPORTS_IS_EMPTY);
+ }
+
+ public static Supplier<OperationException> couldNotReadImports() {
+ return () -> new OperationException(ActionStatus.COULD_NOT_READ_MODEL_IMPORTS);
+ }
+
+ public static Supplier<OperationException> modelAlreadyExists(final String modelName) {
+ return () -> new OperationException(ActionStatus.MODEL_ALREADY_EXISTS, modelName);
+ }
+
+}
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 c604df6dde..ccc18e57dd 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
@@ -19,12 +19,27 @@
package org.openecomp.sdc.be.model.operations.impl;
import fj.data.Either;
+import java.nio.charset.StandardCharsets;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
+import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
import org.openecomp.sdc.be.resources.data.ModelData;
import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
import org.openecomp.sdc.common.log.wrappers.Logger;
@@ -32,28 +47,34 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("model-operation")
-public class ModelOperation extends AbstractOperation {
+public class ModelOperation {
private static final Logger log = Logger.getLogger(ModelOperation.class);
- private final JanusGraphGenericDao genericDao;
+ private final JanusGraphGenericDao janusGraphGenericDao;
+ private final JanusGraphDao janusGraphDao;
+ private final ToscaModelImportCassandraDao toscaModelImportCassandraDao;
@Autowired
- public ModelOperation(final JanusGraphGenericDao janusGraphGenericDao) {
- this.genericDao = janusGraphGenericDao;
+ public ModelOperation(final JanusGraphGenericDao janusGraphGenericDao,
+ final JanusGraphDao janusGraphDao,
+ final ToscaModelImportCassandraDao toscaModelImportCassandraDao) {
+ this.janusGraphGenericDao = janusGraphGenericDao;
+ this.janusGraphDao = janusGraphDao;
+ this.toscaModelImportCassandraDao = toscaModelImportCassandraDao;
}
public Model createModel(final Model model, final boolean inTransaction) {
Model result = null;
- final ModelData modelData = new ModelData(model.getName(), UniqueIdBuilder.buildModelUid(model.getName()));
+ final var modelData = new ModelData(model.getName(), UniqueIdBuilder.buildModelUid(model.getName()));
try {
- final Either<ModelData, JanusGraphOperationStatus> createNode = genericDao.createNode(modelData, ModelData.class);
+ final Either<ModelData, JanusGraphOperationStatus> createNode = janusGraphGenericDao.createNode(modelData, ModelData.class);
if (createNode.isRight()) {
- final JanusGraphOperationStatus janusGraphOperationStatus = createNode.right().value();
+ final var janusGraphOperationStatus = createNode.right().value();
log.error(EcompLoggerErrorCode.DATA_ERROR, ModelOperation.class.getName(), "Problem while creating model, reason {}",
janusGraphOperationStatus);
if (janusGraphOperationStatus == JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION) {
- throw new OperationException(ActionStatus.MODEL_ALREADY_EXISTS, model.getName());
+ throw ModelOperationExceptionSupplier.modelAlreadyExists(model.getName()).get();
}
throw new OperationException(ActionStatus.GENERAL_ERROR,
String.format("Failed to create model %s on JanusGraph with %s error", model, janusGraphOperationStatus));
@@ -63,14 +84,66 @@ public class ModelOperation extends AbstractOperation {
} finally {
if (!inTransaction) {
if (Objects.nonNull(result)) {
- genericDao.commit();
+ janusGraphGenericDao.commit();
} else {
- genericDao.rollback();
+ janusGraphGenericDao.rollback();
}
}
}
}
+ public Optional<GraphVertex> findModelVertexByName(final String name) {
+ if (StringUtils.isEmpty(name)) {
+ return Optional.empty();
+ }
+ final Map<GraphPropertyEnum, Object> props = new EnumMap<>(GraphPropertyEnum.class);
+ props.put(GraphPropertyEnum.NAME, name);
+ props.put(GraphPropertyEnum.UNIQUE_ID, UniqueIdBuilder.buildModelUid(name));
+ final Either<List<GraphVertex>, JanusGraphOperationStatus> result = janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, props);
+ if (result.isRight()) {
+ final JanusGraphOperationStatus janusGraphOperationStatus = result.right().value();
+ if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
+ return Optional.empty();
+ }
+ log.error(EcompLoggerErrorCode.DATA_ERROR, this.getClass().getName(),
+ String.format("Problem while getting model %s. reason %s", name, janusGraphOperationStatus));
+ throw new OperationException(ActionStatus.GENERAL_ERROR,
+ String.format("Failed to get model %s on JanusGraph with %s error", name, janusGraphOperationStatus));
+ }
+ return Optional.ofNullable(result.left().value().get(0));
+ }
+
+ public Optional<Model> findModelByName(final String name) {
+ if (StringUtils.isEmpty(name)) {
+ return Optional.empty();
+ }
+ final Optional<GraphVertex> modelVertexOpt = findModelVertexByName(name);
+ if (modelVertexOpt.isEmpty()) {
+ return Optional.empty();
+ }
+
+ final GraphVertex graphVertex = modelVertexOpt.get();
+ final var model = new Model((String) graphVertex.getMetadataProperty(GraphPropertyEnum.NAME));
+ return Optional.of(model);
+ }
+
+ public void createModelImports(final String modelId, final Map<String, byte[]> zipContent) {
+ if (MapUtils.isEmpty(zipContent)) {
+ return;
+ }
+ final List<ToscaImportByModel> toscaImportByModelList = zipContent.entrySet().stream()
+ .map(entry -> {
+ final String path = entry.getKey();
+ final byte[] bytes = entry.getValue();
+ final String content = new String(bytes, StandardCharsets.UTF_8);
+ final var toscaImportByModel = new ToscaImportByModel();
+ toscaImportByModel.setModelId(modelId);
+ toscaImportByModel.setFullPath(path);
+ toscaImportByModel.setContent(content);
+ return toscaImportByModel;
+ }).collect(Collectors.toList());
+ toscaModelImportCassandraDao.importAll(modelId, toscaImportByModelList);
+ }
}
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 c1c0132b2c..620c7f76a6 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
@@ -19,20 +19,40 @@
package org.openecomp.sdc.be.model.operations.impl;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import fj.data.Either;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
+import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.ModelTestBase;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
@@ -40,19 +60,26 @@ import org.openecomp.sdc.be.resources.data.ModelData;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration("classpath:application-context-test.xml")
-@TestInstance(Lifecycle.PER_CLASS)
class ModelOperationTest extends ModelTestBase {
@InjectMocks
private ModelOperation modelOperation;
@Mock
private JanusGraphGenericDao janusGraphGenericDao;
+ @Mock
+ private JanusGraphDao janusGraphDao;
+ @Mock
+ private ToscaModelImportCassandraDao toscaModelImportCassandraDao;
private final String modelName = "ETSI-SDC-MODEL-TEST";
@BeforeAll
- void setup() {
+ static void beforeAllInit() {
init();
+ }
+
+ @BeforeEach
+ void beforeEachInit() {
MockitoAnnotations.openMocks(this);
}
@@ -68,13 +95,134 @@ class ModelOperationTest extends ModelTestBase {
@Test
void createModelFailWithModelAlreadyExistTest() {
when(janusGraphGenericDao.createNode(any(),any())).thenReturn(Either.right(JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION));
- assertThrows(OperationException.class, () -> modelOperation.createModel(new Model(modelName), false));
+ final var model = new Model(modelName);
+ assertThrows(OperationException.class, () -> modelOperation.createModel(model, false));
}
@Test
void createModelFailTest() {
when(janusGraphGenericDao.createNode(any(),any())).thenReturn(Either.right(JanusGraphOperationStatus.GRAPH_IS_NOT_AVAILABLE));
- assertThrows(OperationException.class, () -> modelOperation.createModel(new Model(modelName), false));
+ final var model = new Model(modelName);
+ assertThrows(OperationException.class, () -> modelOperation.createModel(model, false));
+ }
+
+ @Test
+ void createModelImportsSuccessTest() {
+ var modelId = "modelId";
+ var contentEntry1 = "contentEntry1";
+ var pathEntry1 = "entry1";
+ var contentEntry2 = "contentEntry2";
+ var pathEntry2 = "entry2/path";
+ final Map<String, byte[]> zipContent = new TreeMap<>();
+ zipContent.put(pathEntry1, contentEntry1.getBytes(StandardCharsets.UTF_8));
+ zipContent.put(pathEntry2, contentEntry2.getBytes(StandardCharsets.UTF_8));
+
+ modelOperation.createModelImports(modelId, zipContent);
+
+ final var toscaImport1 = new ToscaImportByModel();
+ toscaImport1.setModelId(modelId);
+ toscaImport1.setContent(contentEntry1);
+ toscaImport1.setFullPath(pathEntry1);
+ final var toscaImport2 = new ToscaImportByModel();
+ toscaImport2.setModelId(modelId);
+ toscaImport2.setContent(contentEntry2);
+ toscaImport2.setFullPath(pathEntry2);
+ final List<ToscaImportByModel> toscaImportByModelList = List.of(toscaImport1, toscaImport2);
+
+ verify(toscaModelImportCassandraDao).importAll(modelId, toscaImportByModelList);
+ }
+
+ @Test
+ void createModelImportsTest_emptyZipContent() {
+ var modelId = "modelId";
+ modelOperation.createModelImports(modelId, Collections.emptyMap());
+ verify(toscaModelImportCassandraDao, never()).importAll(eq(modelId), anyList());
+ modelOperation.createModelImports(modelId, null);
+ verify(toscaModelImportCassandraDao, never()).importAll(eq(null), anyList());
+ }
+
+ @Test
+ void findModelVertexSuccessTest() {
+ final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
+ final GraphVertex expectedVertex = new GraphVertex();
+ when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture())).thenReturn(Either.left(List.of(expectedVertex)));
+ var modelName = "modelName";
+ final Optional<GraphVertex> modelVertexByNameOpt = modelOperation.findModelVertexByName(modelName);
+ assertTrue(modelVertexByNameOpt.isPresent());
+ assertEquals(expectedVertex, modelVertexByNameOpt.get());
+ final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
+ assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
+ assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
+ }
+
+ @Test
+ void findModelVertexTest_modelNotFound() {
+ final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
+ when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture()))
+ .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ var modelName = "modelName";
+
+ final Optional<GraphVertex> modelVertexByNameOpt = modelOperation.findModelVertexByName(modelName);
+
+ assertTrue(modelVertexByNameOpt.isEmpty());
+ final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
+ assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
+ assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
+ }
+
+ @Test
+ void findModelVertexTest_janusGraphError() {
+ final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
+ when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture()))
+ .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
+ var modelName = "modelName";
+
+ final var actualException = assertThrows(OperationException.class, () -> modelOperation.findModelVertexByName(modelName));
+
+ assertEquals(ActionStatus.GENERAL_ERROR, actualException.getActionStatus());
+ final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
+ assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
+ assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
+ }
+
+ @Test
+ void findModelVertexTest_emptyOrNullModelName() {
+ assertTrue(modelOperation.findModelVertexByName("").isEmpty());
+ assertTrue(modelOperation.findModelVertexByName(null).isEmpty());
+ }
+
+ @Test
+ void findModelByNameSuccessTest() {
+ final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
+ var modelName = "modelName";
+ final GraphVertex expectedVertex = mock(GraphVertex.class);
+ when(expectedVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(modelName);
+ when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture())).thenReturn(Either.left(List.of(expectedVertex)));
+ final Optional<Model> modelByNameOpt = modelOperation.findModelByName(modelName);
+
+ final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
+ assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
+ assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
+
+ final Model expectedModel = new Model(modelName);
+ assertTrue(modelByNameOpt.isPresent());
+ assertEquals(expectedModel, modelByNameOpt.get());
+ }
+
+ @Test
+ void findModelByNameTest_modelNameNotFound() {
+ final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
+ var modelName = "modelName";
+ when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture()))
+ .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ final Optional<Model> modelByNameOpt = modelOperation.findModelByName(modelName);
+ assertTrue(modelByNameOpt.isEmpty());
+ }
+
+ @Test
+ void findModelByNameTest_emptyOrNullModelName() {
+ assertTrue(modelOperation.findModelByName("").isEmpty());
+ assertTrue(modelOperation.findModelByName(null).isEmpty());
}
}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/data/model/ToscaImportByModel.java b/common-be/src/main/java/org/openecomp/sdc/be/data/model/ToscaImportByModel.java
new file mode 100644
index 0000000000..5e8818b0b6
--- /dev/null
+++ b/common-be/src/main/java/org/openecomp/sdc/be/data/model/ToscaImportByModel.java
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.data.model;
+
+import com.datastax.driver.mapping.annotations.Column;
+import com.datastax.driver.mapping.annotations.PartitionKey;
+import com.datastax.driver.mapping.annotations.Table;
+import lombok.Data;
+
+@Data
+@Table(keyspace = "sdcartifact", name = "tosca_import_by_model")
+public class ToscaImportByModel {
+
+ @PartitionKey
+ @Column(name = "model_id")
+ private String modelId;
+ @PartitionKey(1)
+ @Column(name = "full_path")
+ private String fullPath;
+ @Column(name = "content")
+ private String content;
+
+}
diff --git a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/CapabilityDefinition.java b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/CapabilityDefinition.java
index 144822d07d..ad38d6f1a1 100644
--- a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/CapabilityDefinition.java
+++ b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/CapabilityDefinition.java
@@ -21,8 +21,12 @@ package org.onap.sdc.tosca.datatypes.model;
import java.util.List;
import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
import org.onap.sdc.tosca.services.DataModelCloneUtil;
+@Getter
+@Setter
public class CapabilityDefinition implements Cloneable {
private String type;
@@ -32,63 +36,14 @@ public class CapabilityDefinition implements Cloneable {
private List<String> valid_source_types;
private Object[] occurrences;
- /**
- * Constructor.
- */
public CapabilityDefinition() {
- occurrences = new Object[2];
- occurrences[0] = 1;
- occurrences[1] = "UNBOUNDED";
+ occurrences = new Object[] {1, "UNBOUNDED"};
}
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
+ public CapabilityDefinition(final String type) {
this.type = type;
}
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public Map<String, PropertyDefinition> getProperties() {
- return properties;
- }
-
- public void setProperties(Map<String, PropertyDefinition> properties) {
- this.properties = properties;
- }
-
- public Map<String, AttributeDefinition> getAttributes() {
- return attributes;
- }
-
- public void setAttributes(Map<String, AttributeDefinition> attributes) {
- this.attributes = attributes;
- }
-
- public List<String> getValid_source_types() {
- return valid_source_types;
- }
-
- public void setValid_source_types(List<String> valid_source_types) {
- this.valid_source_types = valid_source_types;
- }
-
- public Object[] getOccurrences() {
- return occurrences;
- }
-
- public void setOccurrences(Object[] occurrences) {
- this.occurrences = occurrences;
- }
-
@Override
public CapabilityDefinition clone() {
CapabilityDefinition capabilityDefinition = new CapabilityDefinition();
diff --git a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/EntrySchema.java b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/EntrySchema.java
index 932e3c7836..7e08dd85bc 100644
--- a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/EntrySchema.java
+++ b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/EntrySchema.java
@@ -20,38 +20,24 @@
package org.onap.sdc.tosca.datatypes.model;
import java.util.List;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
import org.onap.sdc.tosca.services.DataModelCloneUtil;
+@NoArgsConstructor
+@Getter
+@Setter
public class EntrySchema implements Cloneable {
private String description;
private String type;
private List<Constraint> constraints;
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
+ public EntrySchema(final String type) {
this.type = type;
}
- public List<Constraint> getConstraints() {
- return constraints;
- }
-
- public void setConstraints(List<Constraint> constraints) {
- this.constraints = constraints;
- }
-
@Override
public EntrySchema clone() {
EntrySchema entrySchema = new EntrySchema();