aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichaelMorris <michael.morris@est.tech>2021-08-12 09:14:21 +0100
committerAnderson Ribeiro <anderson.ribeiro@est.tech>2021-08-13 18:53:24 +0000
commit276117aaa383b16a0b62e2666a612e669b8f27c8 (patch)
tree6e34078c50b768569bf97ebb8ae578c8ac9d5e0a
parentb8bfef3a009922db72c1a618211ce03c07683e58 (diff)
Support models extending models
Signed-off-by: MichaelMorris <michael.morris@est.tech> Issue-ID: SDC-3668 Change-Id: Iad4d2a28c1c982e55e8835d4f30a9a212aefb6be
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java2
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ModelServletTest.java15
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java18
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/Model.java5
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java53
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/ModelCreateRequest.java5
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java30
7 files changed, 122 insertions, 6 deletions
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java
index faede3d9c5..8a15f473c9 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java
@@ -264,7 +264,7 @@ class ArchiveEndpointTest extends JerseyTest {
@Bean
ModelOperation modelOperation() {
- return new ModelOperation(null, null, null);
+ return new ModelOperation(null, null, null, null);
}
private void initGraphForTest() {
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 e40124fff4..4e1c0e7945 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
@@ -199,6 +199,21 @@ class ModelServletTest extends JerseyTest {
.post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
+
+ @Test
+ void createModelWithDerivedFromSuccessTest() throws JsonProcessingException {
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
+ when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat);
+ when(modelBusinessLogic.createModel(any(Model.class))).thenReturn(model);
+ ModelCreateRequest derviedModelCreateRequest = new ModelCreateRequest();
+ derviedModelCreateRequest.setName("derivedModel");
+ derviedModelCreateRequest.setDerivedFrom(model.getName());
+ final FormDataMultiPart formDataMultiPart = buildCreateFormDataMultiPart(new byte[0], parseToJsonString(derviedModelCreateRequest));
+ 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() throws JsonProcessingException {
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java
index b2492cdb1a..2116dcc27e 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/janusgraph/JanusGraphGenericDao.java
@@ -693,7 +693,23 @@ public class JanusGraphGenericDao {
if (modelVertices.isLeft()) {
for (ImmutablePair<JanusGraphVertex, Edge> vertexPair : modelVertices.left().value()) {
- if (model.equals((String)vertexPair.getLeft().property("name").value())) {
+ if (modelVertexMatchesModel(vertexPair.getLeft(), model)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean modelVertexMatchesModel(final JanusGraphVertex modelVertex, final String model) {
+ if (model.equals((String)modelVertex.property("name").value())) {
+ return true;
+ }
+ final Either<List<ImmutablePair<JanusGraphVertex, Edge>>, JanusGraphOperationStatus> derivedModels =
+ getParentVerticies(modelVertex, GraphEdgeLabels.DERIVED_FROM);
+ if (derivedModels.isLeft()) {
+ for (final ImmutablePair<JanusGraphVertex, Edge> derivedModel : derivedModels.left().value()) {
+ if (modelVertexMatchesModel(derivedModel.left, model)) {
return true;
}
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Model.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Model.java
index 99d0f6599e..9c07c0565c 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Model.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Model.java
@@ -30,5 +30,10 @@ import lombok.NoArgsConstructor;
public class Model {
private String name;
+ private String derivedFrom;
+
+ public Model(final String name) {
+ this.name = name;
+ }
}
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 ddc0367a44..d4bd7996f2 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,6 +19,7 @@
package org.openecomp.sdc.be.model.operations.impl;
import fj.data.Either;
+
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.EnumMap;
@@ -29,17 +30,24 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
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.dao.neo4j.GraphEdgeLabels;
import org.openecomp.sdc.be.data.model.ToscaImportByModel;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
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;
@@ -55,14 +63,17 @@ public class ModelOperation {
private final JanusGraphGenericDao janusGraphGenericDao;
private final JanusGraphDao janusGraphDao;
private final ToscaModelImportCassandraDao toscaModelImportCassandraDao;
+ private final DerivedFromOperation derivedFromOperation;
@Autowired
public ModelOperation(final JanusGraphGenericDao janusGraphGenericDao,
final JanusGraphDao janusGraphDao,
- final ToscaModelImportCassandraDao toscaModelImportCassandraDao) {
+ final ToscaModelImportCassandraDao toscaModelImportCassandraDao,
+ final DerivedFromOperation derivedFromOperation) {
this.janusGraphGenericDao = janusGraphGenericDao;
this.janusGraphDao = janusGraphDao;
this.toscaModelImportCassandraDao = toscaModelImportCassandraDao;
+ this.derivedFromOperation = derivedFromOperation;
}
public Model createModel(final Model model, final boolean inTransaction) {
@@ -80,7 +91,8 @@ public class ModelOperation {
throw new OperationException(ActionStatus.GENERAL_ERROR,
String.format("Failed to create model %s on JanusGraph with %s error", model, janusGraphOperationStatus));
}
- result = new Model(createNode.left().value().getName());
+ addDerivedFromRelation(model);
+ result = new Model(createNode.left().value().getName(), model.getDerivedFrom());
return result;
} finally {
if (!inTransaction) {
@@ -92,6 +104,24 @@ public class ModelOperation {
}
}
}
+
+ private void addDerivedFromRelation(final Model model) {
+ final String derivedFrom = model.getDerivedFrom();
+ if (derivedFrom == null) {
+ return;
+ }
+ log.debug("Adding derived from relation between model {} to its parent {}",
+ model.getName(), derivedFrom);
+ final Optional<Model> derivedFromModelOptional = this.findModelByName(derivedFrom);
+ if (derivedFromModelOptional.isPresent()) {
+ final Either<GraphRelation, StorageOperationStatus> result = derivedFromOperation.addDerivedFromRelation(UniqueIdBuilder.buildModelUid(model.getName()),
+ UniqueIdBuilder.buildModelUid(derivedFromModelOptional.get().getName()), NodeTypeEnum.Model);
+ if(result.isRight()) {
+ throw new OperationException(ActionStatus.GENERAL_ERROR,
+ String.format("Failed to create relationship from model % to derived from model %s on JanusGraph with %s error", model, derivedFrom, result.right().value()));
+ }
+ }
+ }
public Optional<GraphVertex> findModelVertexByName(final String name) {
if (StringUtils.isEmpty(name)) {
@@ -171,7 +201,24 @@ public class ModelOperation {
}
private Model convertToModel(final GraphVertex modelGraphVertex) {
- return new Model((String) modelGraphVertex.getMetadataProperty(GraphPropertyEnum.NAME));
+ final String modelName = (String) modelGraphVertex.getMetadataProperty(GraphPropertyEnum.NAME);
+
+ final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> parentNode =
+ janusGraphGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Model), UniqueIdBuilder.buildModelUid(modelName),
+ GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model, ModelData.class);
+ log.debug("After retrieving DERIVED_FROM node of {}. status is {}", modelName, parentNode);
+ if (parentNode.isRight()) {
+ final JanusGraphOperationStatus janusGraphOperationStatus = parentNode.right().value();
+ if (janusGraphOperationStatus != JanusGraphOperationStatus.NOT_FOUND) {
+ final var operationException = ModelOperationExceptionSupplier.failedToRetrieveModels(janusGraphOperationStatus).get();
+ log.error(EcompLoggerErrorCode.DATA_ERROR, this.getClass().getName(), operationException.getMessage());
+ throw operationException;
+ }
+ return new Model((String) modelGraphVertex.getMetadataProperty(GraphPropertyEnum.NAME));
+ } else {
+ final ModelData parentModel = parentNode.left().value().getKey();
+ return new Model((String) modelGraphVertex.getMetadataProperty(GraphPropertyEnum.NAME), parentModel.getName());
+ }
}
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/ModelCreateRequest.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/ModelCreateRequest.java
index 0d294b42c4..685d95e4ab 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/ModelCreateRequest.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/ModelCreateRequest.java
@@ -20,17 +20,20 @@ package org.openecomp.sdc.be.ui.model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
/**
* This class is responsible for holding all required fields from the create Model post request.
* It also validates the Model 'name' field.
*/
-@Data
+@Data @AllArgsConstructor @NoArgsConstructor
public class ModelCreateRequest {
@NotNull(message = "Model name cannot be null")
@Size(min = 2, message = "Model name cannot be empty")
private String name;
+ private String derivedFrom;
}
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 c48a1524b8..e8d01dbb0f 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
@@ -25,6 +25,8 @@ 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.anyMap;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -47,17 +49,21 @@ 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.graph.datatype.GraphRelation;
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.dao.neo4j.GraphEdgeLabels;
import org.openecomp.sdc.be.data.model.ToscaImportByModel;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.ModelTestBase;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
import org.openecomp.sdc.be.resources.data.ModelData;
import org.springframework.test.context.ContextConfiguration;
@@ -72,6 +78,8 @@ class ModelOperationTest extends ModelTestBase {
private JanusGraphDao janusGraphDao;
@Mock
private ToscaModelImportCassandraDao toscaModelImportCassandraDao;
+ @Mock
+ private DerivedFromOperation derivedFromOperation;
private final String modelName = "ETSI-SDC-MODEL-TEST";
@@ -93,6 +101,23 @@ class ModelOperationTest extends ModelTestBase {
assertThat(createdModel).isNotNull();
assertThat(createdModel.getName()).isEqualTo(modelName);
}
+
+ @Test
+ void createDerivedModelSuccessTest() {
+ final String derivedModelName = "derivedModel";
+ final ModelData modelData = new ModelData(derivedModelName, UniqueIdBuilder.buildModelUid(derivedModelName));
+ when(janusGraphGenericDao.createNode(any(),any())).thenReturn(Either.left(modelData));
+
+ final GraphVertex modelVertex = new GraphVertex();
+ modelVertex.addMetadataProperty(GraphPropertyEnum.NAME, "baseModel");
+ when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), anyMap())).thenReturn(Either.left(Collections.singletonList(modelVertex)));
+ when(janusGraphGenericDao.getChild(eq("uid"), anyString(), eq(GraphEdgeLabels.DERIVED_FROM), eq(NodeTypeEnum.Model), eq(ModelData.class))).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ when(derivedFromOperation.addDerivedFromRelation("model.derivedModel", "model.baseModel", NodeTypeEnum.Model)).thenReturn(Either.left(new GraphRelation()));
+
+ final Model createdModel = modelOperation.createModel(new Model(derivedModelName, modelName), false);
+ assertThat(createdModel).isNotNull();
+ assertThat(createdModel.getName()).isEqualTo(derivedModelName);
+ }
@Test
void createModelFailWithModelAlreadyExistTest() {
@@ -200,6 +225,8 @@ class ModelOperationTest extends ModelTestBase {
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)));
+ when(janusGraphGenericDao.getChild("uid", UniqueIdBuilder.buildModelUid(modelName), GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model,
+ ModelData.class)).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
final Optional<Model> modelByNameOpt = modelOperation.findModelByName(modelName);
final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
@@ -232,6 +259,9 @@ class ModelOperationTest extends ModelTestBase {
final GraphVertex expectedVertex = mock(GraphVertex.class);
when(expectedVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(modelName);
when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap())).thenReturn(Either.left(List.of(expectedVertex)));
+ when(janusGraphGenericDao.getChild("uid", UniqueIdBuilder.buildModelUid(modelName), GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model,
+ ModelData.class)).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+
final List<Model> actualModelList = modelOperation.findAllModels();
assertFalse(actualModelList.isEmpty());
assertEquals(1, actualModelList.size());