aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvasraz <vasyl.razinkov@est.tech>2021-03-21 20:48:30 +0000
committerChristophe Closset <christophe.closset@intl.att.com>2021-03-24 06:59:24 +0000
commita6ae7294ecd336d7e88f915710b08e2658eaee00 (patch)
tree5353e6fd9ae41888f0f1cb5eb542ad90c261342e
parent1ccd74fb7723bc41424ca93902d68d351ce55462 (diff)
Enable selection of base type of service
Signed-off-by: MichaelMorris <michael.morris@est.tech> Issue-ID: SDC-3506 Change-Id: Iaba39955fac9056cb0d0f1eccd223c05dfb9c5b4 Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java9
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java17
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java2
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java34
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java23
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java23
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/ElementOperationMock.java7
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogicTest.java20
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java37
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java3
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java11
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/BaseType.java58
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java21
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IElementOperation.java4
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ElementOperation.java63
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java3
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ElementOperationTest.java103
-rw-r--r--catalog-ui/src/app/models/base-types.ts28
-rw-r--r--catalog-ui/src/app/models/components/component.ts5
-rw-r--r--catalog-ui/src/app/modules/service-module.ts2
-rw-r--r--catalog-ui/src/app/ng2/app.module.ts2
-rw-r--r--catalog-ui/src/app/ng2/services/element.service.ts42
-rw-r--r--catalog-ui/src/app/ng2/services/responses/component-generic-response.ts8
-rw-r--r--catalog-ui/src/app/services-ng2.ts1
-rw-r--r--catalog-ui/src/app/utils/component-factory.ts2
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts53
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html35
-rw-r--r--catalog-ui/src/assets/languages/en_US.json1
28 files changed, 596 insertions, 21 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java
index 499a6127a1..3b92e62e72 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogic.java
@@ -67,6 +67,7 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
import org.openecomp.sdc.be.model.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
import org.openecomp.sdc.be.model.CatalogUpdateTimestamp;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.ComponentParametersView;
@@ -1286,4 +1287,12 @@ public class ElementBusinessLogic extends BaseBusinessLogic {
janusGraphDao.commit();
}
}
+
+ public Either<List<BaseType>, ActionStatus> getBaseTypes(final String categoryName, final String userId) {
+ final ActionStatus status = validateUserExistsActionStatus(userId);
+ if (ActionStatus.OK != status) {
+ return Either.right(status);
+ }
+ return Either.left(elementOperation.getBaseTypes(categoryName));
+ }
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java
index a00f44ce39..313d345da1 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
@@ -62,13 +63,19 @@ public class GenericTypeBusinessLogic {
log.debug("Failed to fetch certified generic node type for component {}", component.getName());
return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
}
- Either<Resource, StorageOperationStatus> findLatestGeneric = toscaOperationFacade
+ Either<Resource, StorageOperationStatus> genericType;
+ if (StringUtils.isEmpty(component.getDerivedFromGenericVersion())){
+ genericType = toscaOperationFacade
.getLatestCertifiedNodeTypeByToscaResourceName(genericTypeToscaName);
- if (findLatestGeneric.isRight()) {
- log.debug("Failed to fetch certified node type by tosca resource name {}", genericTypeToscaName);
- return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERIC_TYPE_NOT_FOUND, component.assetType(), genericTypeToscaName));
+ if (genericType.isRight()) {
+ log.debug("Failed to fetch certified node type by tosca resource name {}", genericTypeToscaName);
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERIC_TYPE_NOT_FOUND, component.assetType(), genericTypeToscaName));
+ }
+ } else {
+ genericType = toscaOperationFacade.getByToscaResourceNameAndVersion(genericTypeToscaName, component.getDerivedFromGenericVersion());
}
- Resource genericTypeResource = findLatestGeneric.left().value();
+
+ Resource genericTypeResource = genericType.left().value();
return Either.left(genericTypeResource);
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java
index 5bbf84906f..8439ffbefd 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java
@@ -445,6 +445,8 @@ public class UiComponentDataConverter {
UiServiceMetadata metadata = new UiServiceMetadata(service.getCategories(),
(ServiceMetadataDataDefinition) service.getComponentMetadataDefinition().getMetadataDataDefinition());
dataTransfer.setMetadata(metadata);
+ dataTransfer.setDerivedFromGenericType(service.getDerivedFromGenericType());
+ dataTransfer.setDerivedFromGenericVersion(service.getDerivedFromGenericVersion());
break;
case NODE_FILTER:
if (service.getNodeFilterComponents() == null) {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
index 395c610e34..4efca8a2b8 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ElementServlet.java
@@ -65,6 +65,7 @@ import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.info.ArtifactTypesInfo;
import org.openecomp.sdc.be.model.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
import org.openecomp.sdc.be.model.CatalogUpdateTimestamp;
import org.openecomp.sdc.be.model.Category;
import org.openecomp.sdc.be.model.Component;
@@ -189,6 +190,39 @@ public class ElementServlet extends BeGenericServlet {
throw e;
}
}
+
+ @GET
+ @Path("/category/{componentType}/{categoryName}/baseTypes")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Operation(description = "Get base types for category", method = "GET", summary = "Get base types for category",
+ responses = {@ApiResponse(responseCode = "200", description = "Returns base types Ok"),
+ @ApiResponse(responseCode = "404", description = "No base types were found"),
+ @ApiResponse(responseCode = "500", description = "Internal Server Error")})
+ @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+ public Response getCategoryBaseTypes(@PathParam(value = "categoryName") final String categoryName,
+ @PathParam(value = "componentType") final String componentType, @Context final HttpServletRequest request,
+ @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+ try {
+ final ElementBusinessLogic elementBL = getElementBL(request.getSession().getServletContext());
+ final Either<List<BaseType>, ActionStatus> either = elementBL.getBaseTypes(categoryName, userId);
+
+ if (either.isRight() || either.left().value() == null) {
+ log.debug("No base types were found");
+ return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT));
+ } else {
+ final Map<String, Object> baseTypesMap = new HashMap<>();
+ baseTypesMap.put("baseTypes", either.left().value());
+
+ return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), baseTypesMap);
+ }
+ } catch (Exception e) {
+ BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get base types of category");
+ log.debug("getCategoryBaseTypes failed with exception", e);
+ throw e;
+ }
+ }
@DELETE
@Path("/category/{componentType}/{categoryUniqueId}")
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
index 3597c5c23c..b083fbfe2a 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
@@ -418,7 +418,7 @@ public class CsarUtils {
//US798487 - Abstraction of complex types
if (!ModelConverter.isAtomicComponent(component)) {
log.debug("Component {} is complex - generating abstract type for it..", component.getName());
- writeComponentInterface(component, zip, fileName, false);
+ dependencies.addAll(writeComponentInterface(component, zip, fileName, false));
}
//UID <cassandraId,filename,component>
Either<ZipOutputStream, ResponseFormat> zipOutputStreamOrResponseFormat = getZipOutputStreamResponseFormatEither(zip, dependencies);
@@ -747,18 +747,31 @@ public class CsarUtils {
return componentRI;
}
- private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(Component component, ZipOutputStream zip, String fileName,
+ private List<Triple<String, String, Component>> writeComponentInterface(Component component,
+ ZipOutputStream zip,
+ String fileName,
+ boolean isAssociatedComponent
+ ){
+ final Either<ToscaRepresentation, ToscaError> interfaceRepresentation = toscaExportUtils.exportComponentInterface(component, false);
+ writeComponentInterface(interfaceRepresentation, zip, fileName, false);
+ return interfaceRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
+ }
+
+
+ private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(
+ Either<ToscaRepresentation,ToscaError> interfaceRepresentation, ZipOutputStream zip, String fileName,
boolean isAssociatedComponent) {
// TODO: This should not be done but we need this to keep the refactoring small enough to be easily reviewable
- return writeComponentInterface(component, fileName, isAssociatedComponent, ZipWriter.live(zip))
+ return writeComponentInterface(interfaceRepresentation, fileName, isAssociatedComponent, ZipWriter.live(zip))
.map(void0 -> Either.<ZipOutputStream, ResponseFormat>left(zip)).recover(th -> {
log.error("#writeComponentInterface - zip writing failed with error: ", th);
return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
}).get();
}
- private Try<Void> writeComponentInterface(Component component, String fileName, boolean isAssociatedComponent, ZipWriter zw) {
- Either<byte[], ToscaError> yml = toscaExportUtils.exportComponentInterface(component, isAssociatedComponent).left()
+ private Try<Void> writeComponentInterface(
+ Either<ToscaRepresentation,ToscaError> interfaceRepresentation, String fileName, boolean isAssociatedComponent, ZipWriter zw) {
+ Either<byte[], ToscaError> yml = interfaceRepresentation.left()
.map(ToscaRepresentation::getMainYaml);
return fromEither(yml, ToscaErrorException::new).flatMap(zw.write(DEFINITIONS_PATH + ToscaExportHandler.getInterfaceFilename(fileName)));
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
index 988f709bfc..efb3f49d03 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
@@ -199,17 +199,27 @@ public class ToscaExportHandler {
}
public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
- final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImportConfig();
- if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
+ final List<Map<String, Map<String, String>>> imports = getDefaultToscaImportConfig();
+ if (CollectionUtils.isEmpty(imports)) {
log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
return Either.right(ToscaError.GENERAL_ERROR);
}
+ List<Triple<String, String, Component>> dependencies = new ArrayList<>();
+ if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType().startsWith("org.openecomp.resource.abstract.nodes.")) {
+ final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade.getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion());
+ if (baseType.isLeft() && baseType.left().value() != null) {
+ addDependencies(imports, dependencies , baseType.left().value());
+ } else {
+ log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
+ }
+ }
+
String toscaVersion = null;
if (component instanceof Resource) {
toscaVersion = ((Resource) component).getToscaVersion();
}
ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
- toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig));
+ toscaTemplate.setImports(new ArrayList<>(imports));
final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
isAssociatedComponent);
@@ -217,6 +227,7 @@ public class ToscaExportHandler {
return Either.right(toscaTemplateRes.right().value());
}
toscaTemplate = toscaTemplateRes.left().value();
+ toscaTemplate.setDependencies(dependencies);
ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
return Either.left(toscaRepresentation);
}
@@ -493,7 +504,7 @@ public class ToscaExportHandler {
if (!ModelConverter.isAtomicComponent(component)) {
final List<Map<String, Map<String, String>>> additionalImports =
toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports());
- List<Triple<String, String, Component>> dependecies = new ArrayList<>();
+ List<Triple<String, String, Component>> dependencies = new ArrayList<>();
Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
if (isNotEmpty(toscaArtifacts)) {
ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
@@ -510,9 +521,9 @@ public class ToscaExportHandler {
}
List<ComponentInstance> componentInstances = component.getComponentInstances();
if (componentInstances != null && !componentInstances.isEmpty()) {
- componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci));
+ componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
}
- toscaTemplate.setDependencies(dependecies);
+ toscaTemplate.setDependencies(dependencies);
toscaTemplate.setImports(additionalImports);
} else {
log.debug("currently imports supported for VF and service only");
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/ElementOperationMock.java b/catalog-be/src/test/java/org/openecomp/sdc/ElementOperationMock.java
index f9605c1aed..5d05e65886 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/ElementOperationMock.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/ElementOperationMock.java
@@ -26,6 +26,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.model.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
import org.openecomp.sdc.be.model.Category;
import org.openecomp.sdc.be.model.PropertyScope;
import org.openecomp.sdc.be.model.Tag;
@@ -280,4 +281,10 @@ public class ElementOperationMock implements IElementOperation {
return null;
}
+ @Override
+ public List<BaseType> getBaseTypes(String categoryName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogicTest.java
index c87bb2481d..36eee96848 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ElementBusinessLogicTest.java
@@ -39,6 +39,7 @@ import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.BaseType;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.Product;
import org.openecomp.sdc.be.model.Resource;
@@ -304,4 +305,23 @@ public class ElementBusinessLogicTest extends BaseBusinessLogicMock {
Assert.assertTrue(response.isRight());
Assert.assertEquals((Integer) 9, response.right().value().getStatus());
}
+
+ @Test
+ public void testGetBaseTypes_givenValidUserAndComponentType_thenReturnsSuccessful() {
+
+ List<BaseType> baseTypes = new ArrayList<>();
+ baseTypes.add(new BaseType("org.openecomp.type"));
+ String categoryName = "CAT01";
+
+ when(userValidations.validateUserExistsActionStatus(eq(user.getUserId()))).thenReturn(ActionStatus.OK);
+ when(elementDao.getBaseTypes(categoryName)).thenReturn(baseTypes);
+ Assert.assertTrue(elementBusinessLogic.getBaseTypes(categoryName, user.getUserId())
+ .isLeft());
+ }
+
+ @Test
+ public void testGetBaseTypes_givenUserValidationFails_thenReturnsException() {
+ when(userValidations.validateUserExistsActionStatus(eq(user.getUserId()))).thenReturn(ActionStatus.RESTRICTED_OPERATION);
+ Assert.assertTrue(elementBusinessLogic.getBaseTypes("CAT01", user.getUserId()).isRight());
+ }
} \ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java
index cd8c0c57ab..4d2c3621d9 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ElementServletTest.java
@@ -68,6 +68,7 @@ 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.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
import org.openecomp.sdc.be.model.PropertyScope;
import org.openecomp.sdc.be.model.Resource;
import org.openecomp.sdc.be.model.Tag;
@@ -1104,4 +1105,40 @@ class ElementServletTest extends JerseyTest {
})
.property("contextConfig", context);
}
+
+ @Test
+ void getBaseTypesTest() {
+ String path = "/v1/category/services/CAT1/baseTypes";
+ Either<List<BaseType>, ActionStatus> baseTypesEither = Either.left(new ArrayList<>());
+ when(elementBusinessLogic.getBaseTypes("CAT1", designerUser.getUserId()))
+ .thenReturn(baseTypesEither);
+
+ Response response = target()
+ .path(path)
+ .request()
+ .accept(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, designerUser.getUserId())
+ .get();
+
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
+ }
+
+ @Test
+ void getBaseTypesNoBaseTypesFoundTest() {
+ String path = "/v1/category/services/CAT1/baseTypes";
+ Either<List<BaseType>, ActionStatus> baseTypesEither = Either.right(ActionStatus.NO_CONTENT);
+
+ when(elementBusinessLogic.getBaseTypes("CAT1", designerUser.getUserId()))
+ .thenReturn(baseTypesEither);
+
+ Response response = target()
+ .path(path)
+ .request()
+ .accept(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, designerUser.getUserId())
+ .get();
+
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_NO_CONTENT);
+ }
+
} \ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
index 4aa967be47..ce7a10eb28 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
@@ -582,10 +582,9 @@ public class CsarUtilsTest extends BeConfDependentTest {
try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
- Either<ZipOutputStream, ResponseFormat> output = Deencapsulation.invoke(testSubject, "writeComponentInterface", new Resource(), zip, fileName, false);
+ List<Triple<String, String, Component>> output = Deencapsulation.invoke(testSubject, "writeComponentInterface", new Resource(), zip, fileName, false);
assertNotNull(output);
- assertTrue(output.isLeft());
}
}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
index bca8827736..1b38a245c4 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
@@ -521,6 +521,17 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
when(toscaOperationFacade.getToscaFullElement(any(String.class)))
.thenReturn(Either.left(component));
+
+ Resource baseType = getNewResource();
+ Map<String, ArtifactDefinition> baseTypeToscaArtifacts = new HashMap<>();
+ ArtifactDefinition baseTypeArtifact = new ArtifactDefinition();
+ baseTypeArtifact.setArtifactName("typeA");
+ baseTypeToscaArtifacts.put("assettoscatemplate", baseTypeArtifact);
+ baseType.setToscaArtifacts(baseTypeToscaArtifacts);
+
+ component.setDerivedFromGenericType("org.typeA");
+ component.setDerivedFromGenericVersion("1.0");
+ when(toscaOperationFacade.getByToscaResourceNameAndVersion("org.typeA", "1.0")).thenReturn(Either.left(baseType));
// default test
result = Deencapsulation.invoke(testSubject, "fillImports", component, toscaTemplate);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/BaseType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/BaseType.java
new file mode 100644
index 0000000000..5c88101b2f
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/BaseType.java
@@ -0,0 +1,58 @@
+/*
+ * ============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;
+
+import com.vdurmont.semver4j.Semver;
+import com.vdurmont.semver4j.Semver.SemverType;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
+
+
+public class BaseType {
+ @Getter
+ @Setter
+ private String toscaResourceName;
+
+ private List<Semver> versions = new ArrayList<>();
+
+ public BaseType(final String toscaResourceName) {
+ this.toscaResourceName = toscaResourceName;
+ }
+
+ public BaseType(final String toscaResourceName, final List<String> versions) {
+ this.toscaResourceName = toscaResourceName;
+ versions.forEach(version -> this.versions.add(new Semver(version, SemverType.LOOSE)));
+ }
+
+ public void addVersion(final String version) {
+ versions.add(new Semver(version, SemverType.LOOSE));
+ }
+
+ public List<String> getVersions(){
+ Collections.sort(versions);
+ final List<String> versionsAsStrings = new ArrayList<>();
+ this.versions.forEach(version -> versionsAsStrings.add(version.getValue()));
+ return versionsAsStrings;
+ }
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
index 3858912660..06e23f04ea 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
@@ -445,6 +445,27 @@ public class ToscaOperationFacade {
});
}
+ public <T extends Component> Either<T, StorageOperationStatus> getByToscaResourceNameAndVersion(final String toscaResourceName, final String version) {
+ Either<T, StorageOperationStatus> result;
+
+ Map<GraphPropertyEnum, Object> hasProperties = new EnumMap<>(GraphPropertyEnum.class);
+ Map<GraphPropertyEnum, Object> hasNotProperties = new EnumMap<>(GraphPropertyEnum.class);
+
+ hasProperties.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName);
+ hasProperties.put(GraphPropertyEnum.VERSION, version);
+ hasNotProperties.put(GraphPropertyEnum.IS_DELETED, true);
+
+ Either<List<GraphVertex>, JanusGraphOperationStatus> getResourceRes = janusGraphDao
+ .getByCriteria(VertexTypeEnum.NODE_TYPE, hasProperties, hasNotProperties, JsonParseFlagEnum.ParseAll);
+ if (getResourceRes.isRight()) {
+ JanusGraphOperationStatus status = getResourceRes.right().value();
+ log.debug("failed to find resource with toscaResourceName {}, version {}. Status is {} ", toscaResourceName, version, status);
+ result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
+ return result;
+ }
+ return getToscaElementByOperation(getResourceRes.left().value().get(0));
+ }
+
private Map<String, Entry<JanusGraphPredicate, Object>> getVendorVersionPredicate(final String vendorRelease) {
Map<String, Entry<JanusGraphPredicate, Object>> predicateCriteria = new HashMap<>();
if (!"1.0".equals(vendorRelease)) {
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IElementOperation.java
index b3f1306a04..aac14625c5 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IElementOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IElementOperation.java
@@ -20,6 +20,7 @@
package org.openecomp.sdc.be.model.operations.api;
import fj.data.Either;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.openecomp.sdc.be.config.Configuration;
@@ -27,6 +28,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.model.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
import org.openecomp.sdc.be.model.PropertyScope;
import org.openecomp.sdc.be.model.Tag;
import org.openecomp.sdc.be.model.category.CategoryDefinition;
@@ -83,6 +85,8 @@ public interface IElementOperation {
boolean inTransaction);
Either<List<CategoryDefinition>, ActionStatus> getAllCategories(NodeTypeEnum nodeType, boolean inTransaction);
+
+ List<BaseType> getBaseTypes(String categoryName);
Either<CategoryDefinition, ActionStatus> getCategory(NodeTypeEnum nodeType, String categoryId);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ElementOperation.java
index 60ffa1b0f7..054788a519 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ElementOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ElementOperation.java
@@ -21,8 +21,10 @@ package org.openecomp.sdc.be.model.operations.impl;
import fj.data.Either;
import java.util.ArrayList;
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -40,14 +42,22 @@ import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
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.HealingJanusGraphDao;
+import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
import org.openecomp.sdc.be.datatypes.category.CategoryDataDefinition;
import org.openecomp.sdc.be.datatypes.category.GroupingDataDefinition;
import org.openecomp.sdc.be.datatypes.category.SubCategoryDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
import org.openecomp.sdc.be.model.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
import org.openecomp.sdc.be.model.PropertyScope;
import org.openecomp.sdc.be.model.Tag;
import org.openecomp.sdc.be.model.category.CategoryDefinition;
@@ -71,10 +81,12 @@ public class ElementOperation implements IElementOperation {
private static final String UNKNOWN_CATEGORY_TYPE = "Unknown category type {}";
private static final Logger log = Logger.getLogger(ElementOperation.class.getName());
private JanusGraphGenericDao janusGraphGenericDao;
+ private HealingJanusGraphDao janusGraphDao;
- public ElementOperation(@Qualifier("janusgraph-generic-dao") JanusGraphGenericDao janusGraphGenericDao) {
+ public ElementOperation(@Qualifier("janusgraph-generic-dao") JanusGraphGenericDao janusGraphGenericDao, @Qualifier("janusgraph-dao") HealingJanusGraphDao janusGraphDao) {
super();
this.janusGraphGenericDao = janusGraphGenericDao;
+ this.janusGraphDao = janusGraphDao;
}
private static NodeTypeEnum getChildNodeType(NodeTypeEnum parentTypeEnum) {
@@ -367,6 +379,55 @@ public class ElementOperation implements IElementOperation {
}
}
+ @Override
+ public List<BaseType> getBaseTypes(final String categoryName){
+ final ArrayList<BaseType> baseTypes = new ArrayList<>();
+ final Map<String, String> categoriesSpecificBaseTypes = ConfigurationManager.getConfigurationManager().getConfiguration().getServiceNodeTypes();
+ final String categorySpecificBaseType = categoriesSpecificBaseTypes == null ? null : categoriesSpecificBaseTypes.get(categoryName);
+ final String generalBaseType = ConfigurationManager.getConfigurationManager().getConfiguration().getGenericAssetNodeTypes().get("Service");
+ final String baseToscaResourceName = categorySpecificBaseType == null? generalBaseType : categorySpecificBaseType;
+
+ final Map<GraphPropertyEnum, Object> props = new EnumMap<>(GraphPropertyEnum.class);
+ props.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, baseToscaResourceName);
+ props.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
+ final Either<List<GraphVertex>, JanusGraphOperationStatus> baseTypeVertex = janusGraphDao
+ .getByCriteria(VertexTypeEnum.NODE_TYPE, props, JsonParseFlagEnum.ParseAll);
+
+ if (baseTypeVertex.isLeft()) {
+ BaseType baseType = new BaseType(baseToscaResourceName);
+ baseTypes.add(baseType);
+
+ final Map<String, List<String>> typesDerivedFromBaseType = new LinkedHashMap<>();
+ baseTypeVertex.left().value().forEach(v -> {
+ baseType.addVersion((String)v.getMetadataProperty(GraphPropertyEnum.VERSION));
+ addTypesDerivedFromVertex(typesDerivedFromBaseType, v);
+ });
+
+ typesDerivedFromBaseType.forEach((k,v) -> baseTypes.add(new BaseType(k, v)));
+ }
+
+ return baseTypes;
+ }
+
+ private Map<String, List<String>> addTypesDerivedFromVertex(final Map<String, List<String>> types, final GraphVertex vertex) {
+ final Either<List<GraphVertex>, JanusGraphOperationStatus> derivedFromVertex =
+ janusGraphDao.getParentVertices(vertex, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.ParseAll);
+ if (derivedFromVertex.isLeft()) {
+ derivedFromVertex.left().value().stream().filter(v -> v.getMetadataProperty(GraphPropertyEnum.STATE).equals(LifecycleStateEnum.CERTIFIED.name()))
+ .forEach(v -> {
+ addBaseTypeVersion(types, (String) v.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME), (String) v.getMetadataProperty(GraphPropertyEnum.VERSION));
+ addTypesDerivedFromVertex(types, v);
+ });
+ }
+ return types;
+ }
+
+ private void addBaseTypeVersion(final Map<String, List<String>> baseTypes, final String baseTypeToscaResourceName, final String baseTypeVersion) {
+ List<String> versions = baseTypes.get(baseTypeToscaResourceName) == null ? new ArrayList<>(): baseTypes.get(baseTypeToscaResourceName);
+ versions.add(baseTypeVersion);
+ baseTypes.put(baseTypeToscaResourceName, versions);
+ }
+
private JanusGraphOperationStatus setSubCategories(NodeTypeEnum parentNodeType, CategoryDefinition parentCategory) {
NodeTypeEnum childNodeType = getChildNodeType(parentNodeType);
if (childNodeType != null) {
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
index f9741fc234..92149143e6 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
@@ -79,4 +79,7 @@ public class UiComponentDataTransfer {
private List<PropertyDefinition> properties;
private List<AttributeDefinition> attributes;
private Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces;
+ private String derivedFromGenericType;
+ private String derivedFromGenericVersion;
+
}
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ElementOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ElementOperationTest.java
index 3597d02834..230fbe1aba 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ElementOperationTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ElementOperationTest.java
@@ -27,10 +27,20 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.openecomp.sdc.be.config.ArtifactConfiguration;
import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.impl.HealingPipelineDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphClient;
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.HealingJanusGraphDao;
+import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.model.ArtifactType;
+import org.openecomp.sdc.be.model.BaseType;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
import org.openecomp.sdc.be.model.ModelTestBase;
import org.openecomp.sdc.be.model.PropertyScope;
import org.openecomp.sdc.be.model.Tag;
@@ -44,12 +54,16 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application-context-test.xml")
@@ -123,7 +137,7 @@ public class ElementOperationTest extends ModelTestBase {
}
private ElementOperation createTestSubject() {
- return new ElementOperation(new JanusGraphGenericDao(new JanusGraphClient()));
+ return new ElementOperation(new JanusGraphGenericDao(new JanusGraphClient()), new HealingJanusGraphDao(new HealingPipelineDao(), new JanusGraphClient()));
}
@@ -454,4 +468,91 @@ public class ElementOperationTest extends ModelTestBase {
name = "";
result = testSubject.getNewCategoryData(name, type, null);
}
+
+ @Test
+ public void testBaseTypes_serviceSpecific() {
+ Map<String, String> preExistingServiceNodeTypes = configurationManager.getConfiguration().getServiceNodeTypes();
+ Map<String, String> preExistingGenericNodeTypes =
+ configurationManager.getConfiguration().getGenericAssetNodeTypes();
+
+ try {
+ Map<String, String> serviceNodeTypes = new HashMap<>();
+ serviceNodeTypes.put("serviceCategoryA", "org.base.type");
+ configurationManager.getConfiguration().setServiceNodeTypes(serviceNodeTypes);
+
+ Map<String, String> genericNodeTypes = new HashMap<>();
+ genericNodeTypes.put("service", "org.service.default");
+ configurationManager.getConfiguration().setGenericAssetNodeTypes(genericNodeTypes);
+
+ HealingJanusGraphDao healingJanusGraphDao = mock(HealingJanusGraphDao.class);
+ ElementOperation elementOperation =
+ new ElementOperation(new JanusGraphGenericDao(new JanusGraphClient()), healingJanusGraphDao);
+
+ GraphVertex baseTypeVertex = mock(GraphVertex.class);
+ when(baseTypeVertex.getMetadataProperty(GraphPropertyEnum.VERSION)).thenReturn("1.0");
+ when(healingJanusGraphDao.getByCriteria(any(), any(), any()))
+ .thenReturn(Either.left(Collections.singletonList(baseTypeVertex)));
+
+ GraphVertex derivedTypeVertex = mock(GraphVertex.class);
+ when(derivedTypeVertex.getMetadataProperty(GraphPropertyEnum.STATE)).thenReturn(LifecycleStateEnum.CERTIFIED.name());
+ when(derivedTypeVertex.getMetadataProperty(GraphPropertyEnum.VERSION)).thenReturn("1.0");
+
+ GraphVertex derivedTypeVertexUncertified = mock(GraphVertex.class);
+ when(derivedTypeVertexUncertified.getMetadataProperty(GraphPropertyEnum.STATE)).thenReturn(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN.name());
+ when(derivedTypeVertexUncertified.getMetadataProperty(GraphPropertyEnum.VERSION)).thenReturn("1.1");
+
+ when(healingJanusGraphDao.getParentVertices(baseTypeVertex, EdgeLabelEnum.DERIVED_FROM,
+ JsonParseFlagEnum.ParseAll)).thenReturn(Either.left(Collections.singletonList(derivedTypeVertex)));
+ when(healingJanusGraphDao.getParentVertices(derivedTypeVertex, EdgeLabelEnum.DERIVED_FROM,
+ JsonParseFlagEnum.ParseAll)).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ when(derivedTypeVertex.getMetadataProperty(GraphPropertyEnum.TOSCA_RESOURCE_NAME))
+ .thenReturn("org.parent.type");
+
+ List<BaseType> baseTypes = elementOperation.getBaseTypes("serviceCategoryA");
+
+ assertEquals(2, baseTypes.size());
+ assertEquals("org.base.type", baseTypes.get(0).getToscaResourceName());
+ assertEquals(1, baseTypes.get(0).getVersions().size());
+ assertEquals("1.0", baseTypes.get(0).getVersions().get(0));
+ assertEquals("org.parent.type", baseTypes.get(1).getToscaResourceName());
+ } finally {
+ configurationManager.getConfiguration().setServiceNodeTypes(preExistingServiceNodeTypes);
+ configurationManager.getConfiguration().setGenericAssetNodeTypes(preExistingGenericNodeTypes);
+ }
+ }
+
+ @Test
+ public void testBaseTypes_default() {
+ Map<String, String> preExistingServiceNodeTypes = configurationManager.getConfiguration().getServiceNodeTypes();
+ Map<String, String> preExistingGenericNodeTypes =
+ configurationManager.getConfiguration().getGenericAssetNodeTypes();
+
+ try {
+ Map<String, String> genericNodeTypes = new HashMap<>();
+ genericNodeTypes.put("Service", "org.service.default");
+ configurationManager.getConfiguration().setGenericAssetNodeTypes(genericNodeTypes);
+ configurationManager.getConfiguration().setServiceNodeTypes(null);
+
+ HealingJanusGraphDao healingJanusGraphDao = mock(HealingJanusGraphDao.class);
+ ElementOperation elementOperation =
+ new ElementOperation(new JanusGraphGenericDao(new JanusGraphClient()), healingJanusGraphDao);
+
+ GraphVertex baseTypeVertex = mock(GraphVertex.class);
+ when(baseTypeVertex.getMetadataProperty(GraphPropertyEnum.VERSION)).thenReturn("1.0");
+ when(healingJanusGraphDao.getByCriteria(any(), any(), any()))
+ .thenReturn(Either.left(Collections.singletonList(baseTypeVertex)));
+
+ when(healingJanusGraphDao.getParentVertices(baseTypeVertex, EdgeLabelEnum.DERIVED_FROM,
+ JsonParseFlagEnum.ParseAll)).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+
+ List<BaseType> baseTypes = elementOperation.getBaseTypes("serviceCategoryA");
+
+ assertEquals(1, baseTypes.size());
+ assertEquals("org.service.default", baseTypes.get(0).getToscaResourceName());
+ assertEquals(1, baseTypes.get(0).getVersions().size());
+ } finally {
+ configurationManager.getConfiguration().setServiceNodeTypes(preExistingServiceNodeTypes);
+ configurationManager.getConfiguration().setGenericAssetNodeTypes(preExistingGenericNodeTypes);
+ }
+ }
}
diff --git a/catalog-ui/src/app/models/base-types.ts b/catalog-ui/src/app/models/base-types.ts
new file mode 100644
index 0000000000..ac5f8428f3
--- /dev/null
+++ b/catalog-ui/src/app/models/base-types.ts
@@ -0,0 +1,28 @@
+/*
+* ============LICENSE_START=======================================================
+* Copyright (C) 2021 Nordix Foundation. All rights reserved.
+* ================================================================================
+* 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=========================================================
+*/
+
+
+interface ListBaseTypesResponse {
+ baseTypes: BaseTypeResponse[];
+}
+
+interface BaseTypeResponse {
+ toscaResourceName:string;
+ versions:string[];
+}
diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts
index f787142460..be92f76200 100644
--- a/catalog-ui/src/app/models/components/component.ts
+++ b/catalog-ui/src/app/models/components/component.ts
@@ -144,6 +144,8 @@ export abstract class Component implements IComponent {
public vspArchived: boolean;
public componentMetadata: ComponentMetadata;
public categorySpecificMetadata: Metadata = new Metadata();
+ public derivedFromGenericType: string;
+ public derivedFromGenericVersion: string;
constructor(componentService:IComponentService, protected $q:ng.IQService, component?:Component) {
if (component) {
@@ -205,6 +207,9 @@ export abstract class Component implements IComponent {
this.copyCategoryMetadata(component);
this.copySubcategoryMetadata(component);
}
+
+ this.derivedFromGenericType = component.derivedFromGenericType;
+ this.derivedFromGenericVersion = component.derivedFromGenericVersion;
}
//custom properties
diff --git a/catalog-ui/src/app/modules/service-module.ts b/catalog-ui/src/app/modules/service-module.ts
index e2f4f1654a..38cd27250c 100644
--- a/catalog-ui/src/app/modules/service-module.ts
+++ b/catalog-ui/src/app/modules/service-module.ts
@@ -43,6 +43,7 @@ import { GroupsService as GroupsServiceNg2 } from '../ng2/services/groups.servic
import { HomeService } from '../ng2/services/home.service';
import { ModalService } from '../ng2/services/modal.service';
import { OnboardingService } from '../ng2/services/onboarding.service';
+import { ElementService } from '../ng2/services/element.service';
import { PluginsService } from '../ng2/services/plugins.service';
import { PoliciesService as PoliciesServiceNg2 } from '../ng2/services/policies.service';
import { SharingService } from '../ng2/services/sharing.service';
@@ -126,4 +127,5 @@ serviceModule.factory('CompositionService', downgradeInjectable(CompositionServi
serviceModule.factory('ReqAndCapabilitiesService', downgradeInjectable(ReqAndCapabilitiesService));
serviceModule.factory('NodesFactory', downgradeInjectable(NodesFactory));
serviceModule.service('OnboardingService', downgradeInjectable(OnboardingService));
+serviceModule.service('ElementService', downgradeInjectable(ElementService));
serviceModule.service('ImportVSPService', downgradeInjectable(ImportVSPService));
diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts
index e8dde94d68..55dd969a88 100644
--- a/catalog-ui/src/app/ng2/app.module.ts
+++ b/catalog-ui/src/app/ng2/app.module.ts
@@ -98,6 +98,7 @@ import {ToscaTypesServiceNg2} from "./services/tosca-types.service";
import {CapabilitiesFilterPropertiesEditorComponentModule} from "./pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.module";
import {InterfaceOperationHandlerModule} from "./pages/composition/interface-operatons/operation-creator/interface-operation-handler.module";
import {AttributesOutputsModule} from "./pages/attributes-outputs/attributes-outputs.module";
+import { ElementService } from "./services/element.service";
declare const __ENV__: string;
@@ -195,6 +196,7 @@ export function configServiceFactory(config: ConfigService, authService: Authent
ModalService,
ImportVSPService,
OnboardingService,
+ ElementService,
ServiceServiceNg2,
AutomatedUpgradeService,
WorkflowServiceNg2,
diff --git a/catalog-ui/src/app/ng2/services/element.service.ts b/catalog-ui/src/app/ng2/services/element.service.ts
new file mode 100644
index 0000000000..97efbccfef
--- /dev/null
+++ b/catalog-ui/src/app/ng2/services/element.service.ts
@@ -0,0 +1,42 @@
+/*
+* ============LICENSE_START=======================================================
+* Copyright (C) 2021 Nordix Foundation. All rights reserved.
+* ================================================================================
+* 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=========================================================
+*/
+
+import { HttpClient } from '@angular/common/http';
+import { Inject, Injectable } from '@angular/core';
+import { Response } from '@angular/http';
+import { Observable } from 'rxjs/Observable';
+import { ISdcConfig, SdcConfigToken } from '../config/sdc-config.config';
+import {map} from "rxjs/operators";
+
+@Injectable()
+export class ElementService {
+
+ protected baseUrl;
+
+ constructor(protected http: HttpClient, @Inject(SdcConfigToken) sdcConfig: ISdcConfig) {
+ this.baseUrl = sdcConfig.api.root;
+ }
+
+ getCategoryBasetypes(categoryName:string):Observable<BaseTypeResponse[]> {
+ return this.http.get<ListBaseTypesResponse>(this.baseUrl + "/v1/category/services/" + categoryName + "/baseTypes")
+ .pipe(map(response => response.baseTypes));
+ }
+
+}
+
diff --git a/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts b/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
index 09ace56965..784a3d0ac9 100644
--- a/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
+++ b/catalog-ui/src/app/ng2/services/responses/component-generic-response.ts
@@ -59,6 +59,8 @@ export class ComponentGenericResponse implements Serializable<ComponentGenericR
public derivedList:Array<any>;
public nodeFilterforNode: Array<any>;
public substitutionFilterForTopologyTemplate: Array<any>;
+ public derivedFromGenericType;
+ public derivedFromGenericVersion;
deserialize (response): ComponentGenericResponse {
@@ -130,6 +132,12 @@ export class ComponentGenericResponse implements Serializable<ComponentGenericR
if(response.substitutionFilterForTopologyTemplate) {
this.substitutionFilterForTopologyTemplate = response.substitutionFilterForTopologyTemplate;
}
+ if(response.derivedFromGenericType) {
+ this.derivedFromGenericType = response.derivedFromGenericType;
+ }
+ if(response.derivedFromGenericVersion) {
+ this.derivedFromGenericVersion = response.derivedFromGenericVersion;
+ }
return this;
}
}
diff --git a/catalog-ui/src/app/services-ng2.ts b/catalog-ui/src/app/services-ng2.ts
index e2811ba68d..119f2e3883 100644
--- a/catalog-ui/src/app/services-ng2.ts
+++ b/catalog-ui/src/app/services-ng2.ts
@@ -16,6 +16,7 @@ export * from './ng2/services/window.service';
export * from './ng2/services/dynamic-component.service';
export * from './ng2/services/event-bus.service';
export * from './ng2/services/groups.service';
+export * from './ng2/services/element.service';
export * from './ng2/services/component-services/component.service';
export * from './ng2/services/component-services/component.service.factory';
diff --git a/catalog-ui/src/app/utils/component-factory.ts b/catalog-ui/src/app/utils/component-factory.ts
index fd82c27dd8..667c6bceb3 100644
--- a/catalog-ui/src/app/utils/component-factory.ts
+++ b/catalog-ui/src/app/utils/component-factory.ts
@@ -197,6 +197,8 @@ export class ComponentFactory {
component.setUniqueId(componentId);
this.ComponentServiceNg2.getComponentMetadata(component.uniqueId, component.componentType).subscribe((response:ComponentGenericResponse) => {
component.setComponentMetadata(response.metadata);
+ component.derivedFromGenericType = response.derivedFromGenericType;
+ component.derivedFromGenericVersion = response.derivedFromGenericVersion;
deferred.resolve(component);
});
return deferred.promise;
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts
index 1065404eef..28765444b6 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts
@@ -23,7 +23,7 @@ import * as _ from "lodash";
import {ModalsHandler, ValidationUtils, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, DEFAULT_ICON,
ResourceType, ComponentState, instantiationType, ComponentFactory} from "app/utils";
import { EventListenerService, ProgressService} from "app/services";
-import {CacheService, OnboardingService, ImportVSPService} from "app/services-ng2";
+import {CacheService, OnboardingService, ImportVSPService, ElementService} from "app/services-ng2";
import {IAppConfigurtaion, IValidate, IMainCategory, Resource, ISubCategory,Service, ICsarComponent, Component, IMetadataKey} from "app/models";
import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model";
import {Dictionary} from "lodash";
@@ -79,10 +79,12 @@ export interface IGeneralScope extends IWorkspaceViewModelScope {
convertCategoryStringToOneArray(category:string, subcategory:string):Array<IMainCategory>;
onCategoryChange():void;
onEcompGeneratedNamingChange():void;
+ onBaseTypeChange():void;
openOnBoardingModal():void;
initCategoreis():void;
initEnvironmentContext():void;
initInstantiationTypes():void;
+ initBaseTypes():void;
onInstantiationTypeChange():void;
updateIcon():void;
possibleToUpdateIcon():boolean;
@@ -114,6 +116,7 @@ export class GeneralViewModel {
'OnboardingService',
'ComponentFactory',
'ImportVSPService',
+ 'ElementService',
'$stateParams'
];
@@ -139,6 +142,7 @@ export class GeneralViewModel {
private onBoardingService: OnboardingService,
private ComponentFactory:ComponentFactory,
private importVSPService: ImportVSPService,
+ private elementService: ElementService,
private $stateParams: any) {
this.initScopeValidation();
@@ -225,6 +229,7 @@ export class GeneralViewModel {
this.$scope.componentCategories = new componentCategories();
this.$scope.componentCategories.selectedCategory = this.$scope.component.selectedCategory;
+
// Init UIModel
this.$scope.component.tags = _.without(this.$scope.component.tags, this.$scope.component.name);
@@ -257,6 +262,7 @@ export class GeneralViewModel {
}
// Init Instantiation types
this.$scope.initInstantiationTypes();
+ this.$scope.initBaseTypes();
}
if (this.cacheService.get(PREVIOUS_CSAR_COMPONENT)) { //keep the old component in the cache until checkout, so we dont need to pass it around
@@ -434,6 +440,20 @@ export class GeneralViewModel {
}
};
+ this.$scope.initBaseTypes = ():void => {
+ if (this.$scope.componentType === ComponentType.SERVICE && this.$scope.component && this.$scope.component.categories) {
+ this.elementService.getCategoryBasetypes(this.$scope.component.categories[0].name).subscribe((data: BaseTypeResponse[]) => {
+ this.$scope.baseTypes = []
+ this.$scope.baseTypeVersions = []
+ data.forEach(baseType => {
+ this.$scope.baseTypes.push(baseType.toscaResourceName)
+ if (baseType.toscaResourceName === this.$scope.component.derivedFromGenericType){
+ baseType.versions.reverse().forEach(version => this.$scope.baseTypeVersions.push(version));
+ }});
+ })
+ }
+ };
+
this.$scope.initEnvironmentContext = ():void => {
if (this.$scope.componentType === ComponentType.SERVICE) {
this.$scope.environmentContextObj = this.cacheService.get('UIConfiguration').environmentContext;
@@ -645,6 +665,25 @@ export class GeneralViewModel {
}
}
}
+ if (this.$scope.componentType === ComponentType.SERVICE && this.$scope.component.categories[0]) {
+ this.elementService.getCategoryBasetypes(this.$scope.component.categories[0].name).subscribe((data: BaseTypeResponse[]) => {
+
+ if(this.$scope.isCreateMode()){
+ this.$scope.baseTypes = []
+ this.$scope.baseTypeVersions = []
+ data.forEach(baseType => this.$scope.baseTypes.push(baseType.toscaResourceName));
+ data[0].versions.reverse().forEach(version => this.$scope.baseTypeVersions.push(version));
+ this.$scope.component.derivedFromGenericType = data[0].toscaResourceName;
+ this.$scope.component.derivedFromGenericVersion = data[0].versions[0];
+ } else {
+ var isValidForBaseType:boolean = false;
+ data.forEach(baseType => {if (!this.$scope.component.derivedFromGenericType || baseType.toscaResourceName === this.$scope.component.derivedFromGenericType){
+ isValidForBaseType = true;
+ };});
+ this.$scope.editForm['category'].$setValidity('validForBaseType', isValidForBaseType);
+ }
+ });
+ }
};
this.$scope.onEcompGeneratedNamingChange = (): void => {
@@ -653,6 +692,18 @@ export class GeneralViewModel {
}
};
+ this.$scope.onBaseTypeChange = (): void => {
+ this.elementService.getCategoryBasetypes(this.$scope.component.categories[0].name).subscribe((data: BaseTypeResponse[]) => {
+ this.$scope.baseTypeVersions = []
+ data.forEach(baseType => {
+ if(baseType.toscaResourceName === this.$scope.component.derivedFromGenericType) {
+ baseType.versions.reverse().forEach(version => this.$scope.baseTypeVersions.push(version));
+ this.$scope.component.derivedFromGenericVersion = baseType.versions[0];
+ };
+ });
+ })
+ };
+
this.$scope.onVendorNameChange = (oldVendorName: string): void => {
if (this.$scope.component.icon === oldVendorName) {
this.$scope.component.icon = DEFAULT_ICON;
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html
index 40300c8021..d598e170a4 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html
@@ -109,6 +109,7 @@
<div class="input-error" data-ng-show="validateField(editForm.category)">
<span ng-show="editForm.category.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_CATEGORY_REQUIRED"></span>
+ <span ng-show="editForm.category.$error.validForBaseType" translate="NEW_SERVICE_RESOURCE_ERROR_CATEGORY_NOT_VALID"></span>
</div>
</div>
<!--------------------- CATEGORIES -------------------->
@@ -574,6 +575,40 @@
<!--------------------- Instantiation Type -------------------->
+ <!--------------------- Base Type -------------------->
+
+ <div class="w-sdc-form-columns-wrapper">
+ <div class="w-sdc-form-column">
+ <div class="i-sdc-form-item" data-ng-if="component.isService()">
+ <label class="i-sdc-form-label">Base Type</label>
+ <select class="i-sdc-form-select"
+ name="baseType"
+ data-ng-class="{'view-mode': isViewMode()}"
+ data-ng-disabled="component.isCsarComponent() || !isCreateMode()"
+ data-ng-model="component.derivedFromGenericType"
+ data-ng-change="onBaseTypeChange()"
+ data-tests-id="selectBaseType">
+ <option ng-repeat="type in baseTypes">{{type}}</option>
+ </select>
+ </div>
+ </div>
+ <div class="w-sdc-form-column">
+ <div class="i-sdc-form-item" data-ng-if="component.isService()">
+ <label class="i-sdc-form-label">Base Type Version</label>
+ <select class="i-sdc-form-select"
+ name="baseTypeVersion"
+ data-ng-class="{'view-mode': isViewMode()}"
+ data-ng-disabled="component.isCsarComponent() || !isCreateMode()"
+ data-ng-model="component.derivedFromGenericVersion"
+ data-tests-id="selectBaseTypeVersion">
+ <option ng-repeat="version in baseTypeVersions">{{version}}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+
+ <!--------------------- Instantiation Type -------------------->
+
<div class="meta-data" data-ng-if="component.creationDate">
<div>
<b>Created:</b>
diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json
index 7cc6d554fe..df869c3057 100644
--- a/catalog-ui/src/assets/languages/en_US.json
+++ b/catalog-ui/src/assets/languages/en_US.json
@@ -217,6 +217,7 @@
"NEW_SERVICE_RESOURCE_ERROR_NAME_EXISTS": "Name already exists.",
"NEW_SERVICE_RESOURCE_ERROR_SPECIAL_CHARS": "Special characters not allowed.",
"NEW_SERVICE_RESOURCE_ERROR_CATEGORY_REQUIRED": "category is required.",
+ "NEW_SERVICE_RESOURCE_ERROR_CATEGORY_NOT_VALID": "Category not valid for base type.",
"NEW_SERVICE_RESOURCE_ERROR_CONTACT_REQUIRED": "Contact is required.",
"NEW_SERVICE_RESOURCE_ERROR_CONTACT_NOT_VALID": "Contact is not valid.",
"NEW_SERVICE_RESOURCE_ERROR_SERVICE_DESCRIPTION_REQUIRED": "Service description is required.",