Support delete non-normative data types
[sdc.git] / catalog-model / src / test / java / org / openecomp / sdc / be / model / operations / impl / ModelOperationTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.openecomp.sdc.be.model.operations.impl;
21
22 import static org.assertj.core.api.Assertions.assertThat;
23 import static org.junit.jupiter.api.Assertions.assertEquals;
24 import static org.junit.jupiter.api.Assertions.assertFalse;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.anyList;
30 import static org.mockito.ArgumentMatchers.anyMap;
31 import static org.mockito.ArgumentMatchers.anyString;
32 import static org.mockito.ArgumentMatchers.eq;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
38 import static org.openecomp.sdc.be.model.operations.impl.ModelOperation.ADDITIONAL_TYPE_DEFINITIONS_PATH;
39
40 import fj.data.Either;
41 import java.io.IOException;
42 import java.nio.charset.StandardCharsets;
43 import java.nio.file.Files;
44 import java.nio.file.Path;
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Optional;
51 import java.util.TreeMap;
52 import java.util.stream.Stream;
53 import org.apache.commons.lang3.tuple.ImmutablePair;
54 import org.junit.jupiter.api.BeforeAll;
55 import org.junit.jupiter.api.BeforeEach;
56 import org.junit.jupiter.api.Test;
57 import org.mockito.ArgumentCaptor;
58 import org.mockito.InjectMocks;
59 import org.mockito.Mock;
60 import org.mockito.MockitoAnnotations;
61 import org.openecomp.sdc.be.dao.api.ActionStatus;
62 import org.openecomp.sdc.be.dao.cassandra.ToscaModelImportCassandraDao;
63 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
64 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
65 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
66 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
67 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
68 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
69 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
70 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
71 import org.openecomp.sdc.be.data.model.ToscaImportByModel;
72 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
73 import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
74 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
75 import org.openecomp.sdc.be.model.Model;
76 import org.openecomp.sdc.be.model.ModelTestBase;
77 import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto;
78 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
79 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
80 import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
81 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
82 import org.openecomp.sdc.be.resources.data.ModelData;
83 import org.springframework.test.context.ContextConfiguration;
84
85 @ContextConfiguration("classpath:application-context-test.xml")
86 class ModelOperationTest extends ModelTestBase {
87
88     private static final String modelName = "ETSI-SDC-MODEL-TEST";
89     @InjectMocks
90     private ModelOperation modelOperation;
91     @Mock
92     private JanusGraphGenericDao janusGraphGenericDao;
93     @Mock
94     private JanusGraphDao janusGraphDao;
95     @Mock
96     private ToscaModelImportCassandraDao toscaModelImportCassandraDao;
97     @Mock
98     private DerivedFromOperation derivedFromOperation;
99
100     @BeforeAll
101     static void beforeAllInit() {
102         init();
103     }
104
105     @BeforeEach
106     void beforeEachInit() {
107         MockitoAnnotations.openMocks(this);
108     }
109
110     @Test
111     void createModelSuccessTest() {
112         final ModelData modelData = new ModelData(modelName, UniqueIdBuilder.buildModelUid(modelName), ModelTypeEnum.NORMATIVE);
113         when(janusGraphGenericDao.createNode(any(), any())).thenReturn(Either.left(modelData));
114         final Model createdModel = modelOperation.createModel(new Model(modelName, ModelTypeEnum.NORMATIVE), false);
115         assertThat(createdModel).isNotNull();
116         assertThat(createdModel.getName()).isEqualTo(modelName);
117     }
118
119     @Test
120     void createDerivedModelSuccessTest() {
121         final String derivedModelName = "derivedModel";
122         final ModelData modelData = new ModelData(derivedModelName, UniqueIdBuilder.buildModelUid(derivedModelName), ModelTypeEnum.NORMATIVE);
123         when(janusGraphGenericDao.createNode(any(), any())).thenReturn(Either.left(modelData));
124
125         final GraphVertex modelVertex = new GraphVertex();
126         modelVertex.addMetadataProperty(GraphPropertyEnum.NAME, "baseModel");
127         modelVertex.addMetadataProperty(GraphPropertyEnum.MODEL_TYPE, ModelTypeEnum.NORMATIVE.getValue());
128         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), anyMap())).thenReturn(Either.left(Collections.singletonList(modelVertex)));
129         when(janusGraphGenericDao.getChild(eq("uid"), anyString(), eq(GraphEdgeLabels.DERIVED_FROM), eq(NodeTypeEnum.Model),
130             eq(ModelData.class))).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
131         when(derivedFromOperation.addDerivedFromRelation("model.derivedModel", "model.baseModel", NodeTypeEnum.Model)).thenReturn(
132             Either.left(new GraphRelation()));
133
134         final Model createdModel = modelOperation.createModel(new Model(derivedModelName, modelName, ModelTypeEnum.NORMATIVE), false);
135         assertThat(createdModel).isNotNull();
136         assertThat(createdModel.getName()).isEqualTo(derivedModelName);
137     }
138
139     @Test
140     void createModelFailWithModelAlreadyExistTest() {
141         when(janusGraphGenericDao.createNode(any(), any())).thenReturn(Either.right(JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION));
142         final var model = new Model(modelName, ModelTypeEnum.NORMATIVE);
143         assertThrows(OperationException.class, () -> modelOperation.createModel(model, false));
144     }
145
146     @Test
147     void createModelFailTest() {
148         when(janusGraphGenericDao.createNode(any(), any())).thenReturn(Either.right(JanusGraphOperationStatus.GRAPH_IS_NOT_AVAILABLE));
149         final var model = new Model(modelName, ModelTypeEnum.NORMATIVE);
150         assertThrows(OperationException.class, () -> modelOperation.createModel(model, false));
151     }
152
153     @Test
154     void createModelImportsSuccessTest() {
155         var modelId = "modelId";
156         var contentEntry1 = "contentEntry1";
157         var pathEntry1 = "entry1";
158         var contentEntry2 = "contentEntry2";
159         var pathEntry2 = "entry2/path";
160         final Map<String, byte[]> zipContent = new TreeMap<>();
161         zipContent.put(pathEntry1, contentEntry1.getBytes(StandardCharsets.UTF_8));
162         zipContent.put(pathEntry2, contentEntry2.getBytes(StandardCharsets.UTF_8));
163
164         modelOperation.createModelImports(modelId, zipContent);
165
166         final var toscaImport1 = new ToscaImportByModel();
167         toscaImport1.setModelId(modelId);
168         toscaImport1.setContent(contentEntry1);
169         toscaImport1.setFullPath(pathEntry1);
170         final var toscaImport2 = new ToscaImportByModel();
171         toscaImport2.setModelId(modelId);
172         toscaImport2.setContent(contentEntry2);
173         toscaImport2.setFullPath(pathEntry2);
174         final List<ToscaImportByModel> toscaImportByModelList = List.of(toscaImport1, toscaImport2);
175
176         verify(toscaModelImportCassandraDao).replaceImports(modelId, toscaImportByModelList);
177     }
178
179     @Test
180     void createModelImportsTest_emptyZipContent() {
181         var modelId = "modelId";
182         modelOperation.createModelImports(modelId, Collections.emptyMap());
183         verify(toscaModelImportCassandraDao, never()).replaceImports(eq(modelId), anyList());
184         modelOperation.createModelImports(modelId, null);
185         verify(toscaModelImportCassandraDao, never()).replaceImports(eq(null), anyList());
186     }
187
188     @Test
189     void findModelVertexSuccessTest() {
190         final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
191         final GraphVertex expectedVertex = new GraphVertex();
192         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture())).thenReturn(Either.left(List.of(expectedVertex)));
193         var modelName = "modelName";
194         final Optional<GraphVertex> modelVertexByNameOpt = modelOperation.findModelVertexByName(modelName);
195         assertTrue(modelVertexByNameOpt.isPresent());
196         assertEquals(expectedVertex, modelVertexByNameOpt.get());
197         final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
198         assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
199         assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
200     }
201
202     @Test
203     void findModelVertexTest_modelNotFound() {
204         final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
205         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture()))
206             .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
207         var modelName = "modelName";
208
209         final Optional<GraphVertex> modelVertexByNameOpt = modelOperation.findModelVertexByName(modelName);
210
211         assertTrue(modelVertexByNameOpt.isEmpty());
212         final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
213         assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
214         assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
215     }
216
217     @Test
218     void findModelVertexTest_janusGraphError() {
219         final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
220         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture()))
221             .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
222         var modelName = "modelName";
223
224         final var actualException = assertThrows(OperationException.class, () -> modelOperation.findModelVertexByName(modelName));
225
226         assertEquals(ActionStatus.GENERAL_ERROR, actualException.getActionStatus());
227         final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
228         assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
229         assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
230     }
231
232     @Test
233     void findModelVertexTest_emptyOrNullModelName() {
234         assertTrue(modelOperation.findModelVertexByName("").isEmpty());
235         assertTrue(modelOperation.findModelVertexByName(null).isEmpty());
236     }
237
238     @Test
239     void findModelByNameSuccessTest() {
240         final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
241         var modelName = "modelName";
242         final GraphVertex expectedVertex = mock(GraphVertex.class);
243         when(expectedVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(modelName);
244         when(expectedVertex.getMetadataProperty(GraphPropertyEnum.MODEL_TYPE)).thenReturn(ModelTypeEnum.NORMATIVE.getValue());
245         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture())).thenReturn(Either.left(List.of(expectedVertex)));
246         when(janusGraphGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Model), UniqueIdBuilder.buildModelUid(modelName),
247             GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model, ModelData.class)).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
248         final Optional<Model> modelByNameOpt = modelOperation.findModelByName(modelName);
249
250         final Map<GraphPropertyEnum, Object> value = mapArgumentCaptor.getValue();
251         assertEquals(modelName, value.get(GraphPropertyEnum.NAME));
252         assertEquals(UniqueIdBuilder.buildModelUid(modelName), value.get(GraphPropertyEnum.UNIQUE_ID));
253
254         final Model expectedModel = new Model(modelName, ModelTypeEnum.NORMATIVE);
255         assertTrue(modelByNameOpt.isPresent());
256         assertEquals(expectedModel, modelByNameOpt.get());
257     }
258
259     @Test
260     void findModelByNameTest_modelNameNotFound() {
261         final ArgumentCaptor<Map<GraphPropertyEnum, Object>> mapArgumentCaptor = ArgumentCaptor.forClass(Map.class);
262         var modelName = "modelName";
263         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), mapArgumentCaptor.capture()))
264             .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
265         final Optional<Model> modelByNameOpt = modelOperation.findModelByName(modelName);
266         assertTrue(modelByNameOpt.isEmpty());
267     }
268
269     @Test
270     void findModelByNameTest_emptyOrNullModelName() {
271         assertTrue(modelOperation.findModelByName("").isEmpty());
272         assertTrue(modelOperation.findModelByName(null).isEmpty());
273     }
274
275     @Test
276     void findAllModelsSuccessTest() {
277         final GraphVertex expectedVertex = mock(GraphVertex.class);
278         when(expectedVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(modelName);
279         when(expectedVertex.getMetadataProperty(GraphPropertyEnum.MODEL_TYPE)).thenReturn(ModelTypeEnum.NORMATIVE.getValue());
280         when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap())).thenReturn(Either.left(List.of(expectedVertex)));
281         when(janusGraphGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Model), UniqueIdBuilder.buildModelUid(modelName),
282             GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model, ModelData.class)).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
283
284         final List<Model> actualModelList = modelOperation.findAllModels();
285         assertFalse(actualModelList.isEmpty());
286         assertEquals(1, actualModelList.size());
287         assertEquals(modelName, actualModelList.get(0).getName());
288     }
289
290     @Test
291     void findAllModelsTest_noModelsFound() {
292         when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap())).thenReturn(Either.left(Collections.emptyList()));
293         final List<Model> actualModelList = modelOperation.findAllModels();
294         assertTrue(actualModelList.isEmpty());
295     }
296
297     @Test
298     void findAllModelsTest_janusGraphNotFound() {
299         when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap()))
300             .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
301         final List<Model> actualModelList = modelOperation.findAllModels();
302         assertTrue(actualModelList.isEmpty());
303     }
304
305     @Test
306     void findAllModelsTest_janusGraphError() {
307         when(janusGraphDao.getByCriteria(VertexTypeEnum.MODEL, Collections.emptyMap()))
308             .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
309         final var actualException = assertThrows(OperationException.class, () -> modelOperation.findAllModels());
310         final var expectedException = ModelOperationExceptionSupplier.failedToRetrieveModels(JanusGraphOperationStatus.GENERAL_ERROR).get();
311         assertEquals(expectedException.getMessage(), actualException.getMessage());
312     }
313
314     @Test
315     void findAllModelImportsTest() {
316         //given
317         final var modelName = "modelName";
318         final var parentModelName = "parentModelName";
319         final GraphVertex expectedVertex = mock(GraphVertex.class);
320         when(expectedVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(modelName);
321         when(expectedVertex.getMetadataProperty(GraphPropertyEnum.MODEL_TYPE)).thenReturn(ModelTypeEnum.NORMATIVE_EXTENSION.getValue());
322         when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.MODEL), anyMap())).thenReturn(Either.left(List.of(expectedVertex)));
323
324         final var modelData = new ModelData(parentModelName, parentModelName, ModelTypeEnum.NORMATIVE);
325         final ImmutablePair<ModelData, GraphEdge> modelDataGraphEdgePair = new ImmutablePair<>(modelData, null);
326
327         when(janusGraphGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Model), UniqueIdBuilder.buildModelUid(modelName),
328             GraphEdgeLabels.DERIVED_FROM, NodeTypeEnum.Model, ModelData.class)).thenReturn(Either.left(modelDataGraphEdgePair));
329
330         final ArrayList<ToscaImportByModel> childModelImportList = new ArrayList<>();
331         childModelImportList.add(createModelImport(modelName, "anyPath1"));
332         childModelImportList.add(createModelImport(modelName, "anyPath2"));
333         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(new ArrayList<>(childModelImportList));
334         final ArrayList<ToscaImportByModel> parentModelImportList = new ArrayList<>();
335         parentModelImportList.add(createModelImport(parentModelName, "anyPath1"));
336         parentModelImportList.add(createModelImport(parentModelName, "anyPath2"));
337         when(toscaModelImportCassandraDao.findAllByModel(parentModelName)).thenReturn(parentModelImportList);
338
339         //when
340         final List<ToscaImportByModel> actualModelImportList = modelOperation.findAllModelImports(modelName, true);
341
342         //then
343         assertFalse(actualModelImportList.isEmpty());
344         assertEquals(childModelImportList.size() + parentModelImportList.size(), actualModelImportList.size());
345         Stream.concat(childModelImportList.stream(), parentModelImportList.stream())
346             .forEach(toscaImportByModel -> assertTrue(actualModelImportList.contains(toscaImportByModel)));
347     }
348
349     @Test
350     void addTypesToDefaultImportsTest_nonExistingAdditionalTypesImport() throws IOException {
351         var modelName = "model";
352         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
353
354         final var dataTypesPath = testResourcePath.resolve(Path.of("input-data_types.yaml"));
355         final var dataTypes = Files.readString(dataTypesPath);
356
357         final Path import1RelativePath = Path.of("original-import-1.yaml");
358         final Path import1Path = testResourcePath.resolve(import1RelativePath);
359         final Path import2RelativePath = Path.of("original-import-2.yaml");
360         final Path import2Path = testResourcePath.resolve(import2RelativePath);
361
362         var toscaImportByModel1 = new ToscaImportByModel();
363         toscaImportByModel1.setModelId(modelName);
364         toscaImportByModel1.setFullPath(import1RelativePath.toString());
365         toscaImportByModel1.setContent(Files.readString(import1Path));
366
367         var toscaImportByModel2 = new ToscaImportByModel();
368         toscaImportByModel2.setModelId(modelName);
369         toscaImportByModel2.setFullPath(import2RelativePath.toString());
370         toscaImportByModel2.setContent(Files.readString(import2Path));
371
372         final List<ToscaImportByModel> modelImports = new ArrayList<>();
373         modelImports.add(toscaImportByModel1);
374         modelImports.add(toscaImportByModel2);
375         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
376
377         modelOperation.addTypesToDefaultImports(ElementTypeEnum.DATA_TYPE, dataTypes, modelName);
378         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
379         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
380
381         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
382         assertEquals(3, actualImportList.size());
383         assertTrue(actualImportList.contains(toscaImportByModel1));
384         assertTrue(actualImportList.contains(toscaImportByModel2));
385
386         var expectedAdditionalTypesImport = new ToscaImportByModel();
387         expectedAdditionalTypesImport.setModelId(modelName);
388         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
389         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-1.yaml"))));
390         final ToscaImportByModel actualAdditionalTypesImport =
391             actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
392         assertNotNull(actualAdditionalTypesImport);
393         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
394
395         var expectedImport1 = new ToscaImportByModel();
396         expectedImport1.setModelId(modelName);
397         expectedImport1.setFullPath(import1RelativePath.toString());
398         expectedImport1.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-1.yaml"))));
399         final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null);
400         assertNotNull(actualImport1);
401         assertEquals(expectedImport1.getContent(), actualImport1.getContent());
402
403         var expectedImport2 = new ToscaImportByModel();
404         expectedImport2.setModelId(modelName);
405         expectedImport2.setFullPath(import2RelativePath.toString());
406         expectedImport2.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-2.yaml"))));
407         final ToscaImportByModel actualImport2 = actualImportList.stream().filter(expectedImport2::equals).findFirst().orElse(null);
408         assertNotNull(actualImport2);
409         assertEquals(expectedImport2.getContent(), actualImport2.getContent());
410     }
411
412     @Test
413     void addArtifactsToDefaultImportsTest_nonExistingAdditionalTypesImport() throws IOException {
414         var modelName = "model";
415         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
416
417         final var dataTypesPath = testResourcePath.resolve(Path.of("input-artifact_types.yaml"));
418         final var dataTypes = Files.readString(dataTypesPath);
419
420         final Path import1RelativePath = Path.of("original-import-3.yaml");
421         final Path import1Path = testResourcePath.resolve(import1RelativePath);
422
423         var toscaImportByModel1 = new ToscaImportByModel();
424         toscaImportByModel1.setModelId(modelName);
425         toscaImportByModel1.setFullPath(import1RelativePath.toString());
426         toscaImportByModel1.setContent(Files.readString(import1Path));
427
428         final List<ToscaImportByModel> modelImports = new ArrayList<>();
429         modelImports.add(toscaImportByModel1);
430         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
431
432         modelOperation.addTypesToDefaultImports(ElementTypeEnum.ARTIFACT_TYPE, dataTypes, modelName);
433         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
434         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
435
436         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
437         assertEquals(2, actualImportList.size());
438         assertTrue(actualImportList.contains(toscaImportByModel1));
439
440         var expectedAdditionalTypesImport = new ToscaImportByModel();
441         expectedAdditionalTypesImport.setModelId(modelName);
442         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
443         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-3.yaml"))));
444         final ToscaImportByModel actualAdditionalTypesImport =
445             actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
446         assertNotNull(actualAdditionalTypesImport);
447         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
448
449         var expectedImport1 = new ToscaImportByModel();
450         expectedImport1.setModelId(modelName);
451         expectedImport1.setFullPath(import1RelativePath.toString());
452         expectedImport1.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-3.yaml"))));
453         final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null);
454         assertNotNull(actualImport1);
455         assertEquals(expectedImport1.getContent(), actualImport1.getContent());
456
457     }
458
459     @Test
460     void addTypesToDefaultImportsTest_existingAdditionalTypesImport() throws IOException {
461         var modelName = "model";
462         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
463
464         final var dataTypesPath = testResourcePath.resolve(Path.of("input-data_types.yaml"));
465         final var dataTypes = Files.readString(dataTypesPath);
466
467         final Path import1RelativePath = Path.of("original-import-1.yaml");
468         final Path import1Path = testResourcePath.resolve(import1RelativePath);
469
470         var toscaImportByModel1 = new ToscaImportByModel();
471         toscaImportByModel1.setModelId(modelName);
472         toscaImportByModel1.setFullPath(import1RelativePath.toString());
473         toscaImportByModel1.setContent(Files.readString(import1Path));
474
475         var originalAdditionalTypesImport = new ToscaImportByModel();
476         originalAdditionalTypesImport.setModelId(modelName);
477         originalAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
478         final Path originalAdditionalTypesImportPath = testResourcePath.resolve(Path.of("original-additional_types-1.yaml"));
479         originalAdditionalTypesImport.setContent(Files.readString(originalAdditionalTypesImportPath));
480
481         final List<ToscaImportByModel> modelImports = new ArrayList<>();
482         modelImports.add(toscaImportByModel1);
483         modelImports.add(originalAdditionalTypesImport);
484         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
485
486         modelOperation.addTypesToDefaultImports(ElementTypeEnum.DATA_TYPE, dataTypes, modelName);
487         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
488         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
489
490         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
491         assertEquals(2, actualImportList.size());
492         assertTrue(actualImportList.contains(toscaImportByModel1));
493
494         var expectedAdditionalTypesImport = new ToscaImportByModel();
495         expectedAdditionalTypesImport.setModelId(modelName);
496         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
497         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-2.yaml"))));
498         final ToscaImportByModel actualAdditionalTypesImport =
499             actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
500         assertNotNull(actualAdditionalTypesImport);
501         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
502
503         var expectedImport1 = new ToscaImportByModel();
504         expectedImport1.setModelId(modelName);
505         expectedImport1.setFullPath(import1RelativePath.toString());
506         expectedImport1.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-1.yaml"))));
507         final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null);
508         assertNotNull(actualImport1);
509         assertEquals(expectedImport1.getContent(), actualImport1.getContent());
510
511         // Update the added additional type
512         final var updatedDataTypesPath = testResourcePath.resolve(Path.of("input-data_types-updated.yaml"));
513         final var updatedDataTypes = Files.readString(updatedDataTypesPath);
514         modelOperation.updateTypesInAdditionalTypesImport(ElementTypeEnum.DATA_TYPE, updatedDataTypes, modelName);
515
516         ArgumentCaptor<List<ToscaImportByModel>> updatedImportListArgumentCaptor = ArgumentCaptor.forClass(List.class);
517         verify(toscaModelImportCassandraDao, times(2)).saveAll(eq(modelName), updatedImportListArgumentCaptor.capture());
518
519         final List<ToscaImportByModel> updatedActualImportList = updatedImportListArgumentCaptor.getValue();
520         assertEquals(2, updatedActualImportList.size());
521
522         var expectedUpdatedAdditionalTypesImport = new ToscaImportByModel();
523         expectedUpdatedAdditionalTypesImport.setModelId(modelName);
524         expectedUpdatedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
525         expectedUpdatedAdditionalTypesImport.setContent(
526             Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-2-updated.yaml"))));
527         final ToscaImportByModel actualUpdatedAdditionalTypesImport =
528             actualImportList.stream().filter(expectedUpdatedAdditionalTypesImport::equals).findFirst().orElse(null);
529         assertNotNull(actualUpdatedAdditionalTypesImport);
530
531         assertTrue(actualUpdatedAdditionalTypesImport.getContent().contains("added_property_1"));
532         assertTrue(actualUpdatedAdditionalTypesImport.getContent().contains("added_property_2"));
533     }
534
535     @Test
536     void addArtifactsToDefaultImportsTest_existingAdditionalTypesImport() throws IOException {
537         var modelName = "model";
538         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
539
540         final var dataTypesPath = testResourcePath.resolve(Path.of("input-artifact_types.yaml"));
541         final var dataTypes = Files.readString(dataTypesPath);
542
543         final Path import1RelativePath = Path.of("original-import-3.yaml");
544         final Path import1Path = testResourcePath.resolve(import1RelativePath);
545
546         var toscaImportByModel1 = new ToscaImportByModel();
547         toscaImportByModel1.setModelId(modelName);
548         toscaImportByModel1.setFullPath(import1RelativePath.toString());
549         toscaImportByModel1.setContent(Files.readString(import1Path));
550
551         var originalAdditionalTypesImport = new ToscaImportByModel();
552         originalAdditionalTypesImport.setModelId(modelName);
553         originalAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
554         final Path originalAdditionalTypesImportPath = testResourcePath.resolve(Path.of("original-additional_types-2.yaml"));
555         originalAdditionalTypesImport.setContent(Files.readString(originalAdditionalTypesImportPath));
556
557         final List<ToscaImportByModel> modelImports = new ArrayList<>();
558         modelImports.add(toscaImportByModel1);
559         modelImports.add(originalAdditionalTypesImport);
560         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
561
562         modelOperation.addTypesToDefaultImports(ElementTypeEnum.ARTIFACT_TYPE, dataTypes, modelName);
563         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
564         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
565
566         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
567         assertEquals(2, actualImportList.size());
568         assertTrue(actualImportList.contains(toscaImportByModel1));
569
570         var expectedAdditionalTypesImport = new ToscaImportByModel();
571         expectedAdditionalTypesImport.setModelId(modelName);
572         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
573         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-3.yaml"))));
574         final ToscaImportByModel actualAdditionalTypesImport =
575             actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
576         assertNotNull(actualAdditionalTypesImport);
577         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
578
579         var expectedImport1 = new ToscaImportByModel();
580         expectedImport1.setModelId(modelName);
581         expectedImport1.setFullPath(import1RelativePath.toString());
582         expectedImport1.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-import-3.yaml"))));
583         final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null);
584         assertNotNull(actualImport1);
585         assertEquals(expectedImport1.getContent(), actualImport1.getContent());
586
587     }
588
589     @Test
590     void addPropertyToExistingAdditionalType() throws IOException {
591         var modelName = "model";
592         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
593
594         var originalAdditionalTypesImport = new ToscaImportByModel();
595         originalAdditionalTypesImport.setModelId(modelName);
596         originalAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
597         final Path originalAdditionalTypesImportPath = testResourcePath.resolve(Path.of("original-additional_types-1.yaml"));
598         originalAdditionalTypesImport.setContent(Files.readString(originalAdditionalTypesImportPath));
599
600         final List<ToscaImportByModel> modelImports = new ArrayList<>();
601         modelImports.add(originalAdditionalTypesImport);
602         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
603
604         PropertyDefinitionDto property = new PropertyDefinitionDto();
605         property.setName("addedMapProperty");
606         property.setType("map");
607         property.setSchemaType("string");
608         property.setDescription("This is a description");
609         Map<Object, Object> defaultValue = new HashMap<>();
610         defaultValue.put("k1", "v1");
611         defaultValue.put("k2", "v2");
612         property.setDefaultValue(defaultValue);
613         property.setRequired(true);
614
615         String dataTypeName = "tosca.datatypes.nfv.PreviouslyExistingType1";
616         modelOperation.updatePropertyInAdditionalType(ElementTypeEnum.DATA_TYPE, property, modelName, dataTypeName, true);
617         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
618         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
619
620         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
621         assertEquals(1, actualImportList.size());
622
623         var expectedAdditionalTypesImport = new ToscaImportByModel();
624         expectedAdditionalTypesImport.setModelId(modelName);
625         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
626         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-4.yaml"))));
627         final ToscaImportByModel actualAdditionalTypesImport =
628             actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
629         assertNotNull(actualAdditionalTypesImport);
630         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
631     }
632
633     @Test
634     void removeDataTypeFromAdditionalType() throws IOException {
635         var modelName = "model";
636         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
637
638         var originalAdditionalTypesImport = new ToscaImportByModel();
639         originalAdditionalTypesImport.setModelId(modelName);
640         originalAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
641         final Path originalAdditionalTypesImportPath = testResourcePath.resolve(Path.of("original-additional_types-1.yaml"));
642         originalAdditionalTypesImport.setContent(Files.readString(originalAdditionalTypesImportPath));
643
644         final List<ToscaImportByModel> modelImports = new ArrayList<>();
645         modelImports.add(originalAdditionalTypesImport);
646         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
647
648         String dataTypeName = "tosca.datatypes.nfv.PreviouslyExistingType1";
649         modelOperation.removeDataTypeFromAdditionalType(ElementTypeEnum.DATA_TYPE, modelName, dataTypeName);
650         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
651         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
652
653         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
654         assertEquals(1, actualImportList.size());
655
656         var expectedAdditionalTypesImport = new ToscaImportByModel();
657         expectedAdditionalTypesImport.setModelId(modelName);
658         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
659         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-5.yaml"))));
660         final ToscaImportByModel actualAdditionalTypesImport =
661                 actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
662         assertNotNull(actualAdditionalTypesImport);
663         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
664     }
665
666     @Test
667     void removeOnlyDataTypeFromAdditionalType() throws IOException {
668         var modelName = "model";
669         final Path testResourcePath = Path.of("src/test/resources/modelOperation");
670
671         var originalAdditionalTypesImport = new ToscaImportByModel();
672         originalAdditionalTypesImport.setModelId(modelName);
673         originalAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
674         final Path originalAdditionalTypesImportPath = testResourcePath.resolve(Path.of("original-additional_types-3.yaml"));
675         originalAdditionalTypesImport.setContent(Files.readString(originalAdditionalTypesImportPath));
676
677         final List<ToscaImportByModel> modelImports = new ArrayList<>();
678         modelImports.add(originalAdditionalTypesImport);
679         when(toscaModelImportCassandraDao.findAllByModel(modelName)).thenReturn(modelImports);
680
681         String dataTypeName = "tosca.datatypes.nfv.PreviouslyExistingType1";
682         modelOperation.removeDataTypeFromAdditionalType(ElementTypeEnum.DATA_TYPE, modelName, dataTypeName);
683         ArgumentCaptor<List<ToscaImportByModel>> importListArgumentCaptor = ArgumentCaptor.forClass(List.class);
684         verify(toscaModelImportCassandraDao).saveAll(eq(modelName), importListArgumentCaptor.capture());
685
686         final List<ToscaImportByModel> actualImportList = importListArgumentCaptor.getValue();
687         assertEquals(1, actualImportList.size());
688
689         var expectedAdditionalTypesImport = new ToscaImportByModel();
690         expectedAdditionalTypesImport.setModelId(modelName);
691         expectedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString());
692         expectedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-6.yaml"))));
693         final ToscaImportByModel actualAdditionalTypesImport =
694                 actualImportList.stream().filter(expectedAdditionalTypesImport::equals).findFirst().orElse(null);
695         assertNotNull(actualAdditionalTypesImport);
696         assertEquals(expectedAdditionalTypesImport.getContent(), actualAdditionalTypesImport.getContent());
697     }
698
699     private ToscaImportByModel createModelImport(final String parentModelName, final String importPath) {
700         var toscaImportByModel = new ToscaImportByModel();
701         toscaImportByModel.setModelId(parentModelName);
702         toscaImportByModel.setFullPath(importPath);
703         return toscaImportByModel;
704     }
705 }