diff options
author | Talio <tali.orenbach@amdocs.com> | 2019-01-31 18:00:36 +0200 |
---|---|---|
committer | Avi Gaffa <avi.gaffa@amdocs.com> | 2019-02-04 11:00:09 +0000 |
commit | 0953785bfd6a3af5e506f8a55a8520c0fb7ef358 (patch) | |
tree | 2f900e3f09a60a5a9a75ddcdd30930d3164eeeed | |
parent | 47c8af4d7241f20755ea97a6119bae2f500cfffa (diff) |
Add property mapping feature to ONAP
Add service property assignment
Change-Id: I29748ce12bacab06b8bc27f8875b39d80ffe5af7
Issue-ID: SDC-1988
Signed-off-by: Talio <tali.orenbach@amdocs.com>
56 files changed, 2969 insertions, 1106 deletions
diff --git a/catalog-be/pom.xml b/catalog-be/pom.xml index 8bbe456c9d..4c0cbbfae0 100644 --- a/catalog-be/pom.xml +++ b/catalog-be/pom.xml @@ -588,6 +588,36 @@ <groupId>io.netty</groupId> <artifactId>netty-handler</artifactId> </dependency> + <dependency> + <groupId>org.onap.sdc.common</groupId> + <artifactId>onap-tosca-datatype</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.1</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdc.be</groupId> + <artifactId>catalog-model</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.sdc.common</groupId> + <artifactId>onap-tosca-datatype</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.1</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdc.be</groupId> + <artifactId>catalog-model</artifactId> + <version>${project.version}</version> + </dependency> </dependencies> <build> diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java index 5f40606177..f49f531e28 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java @@ -7,9 +7,9 @@ * 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. @@ -22,19 +22,27 @@ package org.openecomp.sdc.be.components.impl; import com.google.gson.JsonElement; import fj.data.Either; +import java.util.Map.Entry; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.impl.WebAppContextWrapper; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstanceInterface; +import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.IComplexDefaultValue; +import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.operations.api.IElementOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; @@ -45,17 +53,13 @@ import org.openecomp.sdc.be.resources.data.EntryData; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; -import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; import javax.servlet.ServletContext; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; +import java.util.*; import java.util.function.Supplier; -@Component("propertyBusinessLogic") +@org.springframework.stereotype.Component("propertyBusinessLogic") public class PropertyBusinessLogic extends BaseBusinessLogic { private static final String CREATE_PROPERTY = "CreateProperty"; @@ -77,262 +81,368 @@ public class PropertyBusinessLogic extends BaseBusinessLogic { } /** - * Create new property on resource in graph + * Create new property on component in graph * - * @param resourceId + * @param componentId * @param propertyName * @param newPropertyDefinition * @param userId * @return either properties or response format */ - public Either<EntryData<String, PropertyDefinition>, ResponseFormat> createProperty(String resourceId, String propertyName, PropertyDefinition newPropertyDefinition, String userId) { + public Either<EntryData<String, PropertyDefinition>, ResponseFormat> addPropertyToComponent(String componentId, + String propertyName, + PropertyDefinition newPropertyDefinition, + String userId) { Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null; validateUserExists(userId, "create Property", false); - StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); + Either<Component, StorageOperationStatus> serviceElement = + toscaOperationFacade.getToscaElement(componentId); + if (serviceElement.isRight()) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + return result; + } + Component component = serviceElement.left().value(); + NodeTypeEnum nodeType = component.getComponentType().getNodeType(); + StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType ); if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); - log.info("Failed to lock component {}. Error - {}", resourceId, lockResult); + BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, nodeType.name().toLowerCase(), componentId); + log.info("Failed to lock component {}. Error - {}", componentId, lockResult); result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); return result; } try { - // Get the resource from DB - Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); - if (status.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); - return result; - } - Resource resource = status.left().value(); - - // verify that resource is checked-out and the user is the last - // updater - if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { + if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) { result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); return result; } - // verify property not exist in resource - List<PropertyDefinition> resourceProperties = resource.getProperties(); + List<PropertyDefinition> properties = component.getProperties(); - if (resourceProperties != null && isPropertyExist(resourceProperties, resourceId, propertyName, newPropertyDefinition.getType())) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, propertyName)); - return result; + if(CollectionUtils.isEmpty(properties)) { + properties = new ArrayList<>(); } - Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); - if (allDataTypes.isRight()) { - result = Either.right(allDataTypes.right().value()); + if(isPropertyExistInComponent(properties, propertyName)) { + + result = + Either.right(componentsUtils.getResponseFormat(ActionStatus + .PROPERTY_ALREADY_EXIST, propertyName)); return result; - } - Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); + } else { - // validate property default values - Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); - if (defaultValuesValidation.isRight()) { - result = Either.right(defaultValuesValidation.right().value()); - return result; - } - convertProperty(newPropertyDefinition, allDataTypes); + Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); + if (allDataTypes.isRight()) { + result = Either.right(allDataTypes.right().value()); + return result; + } + Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); - // add the new property to resource on graph - // need to get StorageOpaerationStatus and convert to ActionStatus - // from componentsUtils - Either<PropertyDefinition, StorageOperationStatus> either = toscaOperationFacade.addPropertyToResource(propertyName, newPropertyDefinition, resource); - if (either.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); - return result; + // validate property default values + Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); + if (defaultValuesValidation.isRight()) { + result = Either.right(defaultValuesValidation.right().value()); + return result; + } + // convert property + ToscaPropertyType type = getType(newPropertyDefinition.getType()); + if (type != null) { + PropertyValueConverter converter = type.getConverter(); + // get inner type + String innerType = null; + if (newPropertyDefinition != null) { + SchemaDefinition schema = newPropertyDefinition.getSchema(); + if (schema != null) { + PropertyDataDefinition prop = schema.getProperty(); + if (prop != null) { + innerType = prop.getType(); + } + } + String convertedValue = null; + if (newPropertyDefinition.getDefaultValue() != null) { + convertedValue = converter.convert( + (String) newPropertyDefinition.getDefaultValue(), innerType, allDataTypes.left().value()); + newPropertyDefinition.setDefaultValue(convertedValue); + } + } + } + Either<PropertyDefinition, StorageOperationStatus> addPropertyEither = + toscaOperationFacade + .addPropertyToComponent(propertyName, newPropertyDefinition, component); + + if (addPropertyEither.isRight()) { + log.info("Failed to add new property {}. Error - {}", componentId, + addPropertyEither.right().value()); + result = Either.right(componentsUtils.getResponseFormat(ActionStatus + .GENERAL_ERROR)); + return result; + } } - PropertyDefinition createdPropertyDefinition = either.left().value(); - EntryData<String, PropertyDefinition> property = new EntryData<>(propertyName, createdPropertyDefinition); - result = Either.left(property); + result = Either.left(new EntryData<>(propertyName, newPropertyDefinition)); return result; } finally { commitOrRollback(result); // unlock component - graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); + graphLockOperation.unlockComponent(componentId, nodeType); } } - private void convertProperty(PropertyDefinition newPropertyDefinition, Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes) { - ToscaPropertyType type = getType(newPropertyDefinition.getType()); - if (type != null) { - String innerType = null; - SchemaDefinition schema = newPropertyDefinition.getSchema(); - if (schema != null && schema.getProperty() != null) { - innerType = schema.getProperty().getType(); - } - if (newPropertyDefinition.getDefaultValue() != null) { - newPropertyDefinition.setDefaultValue( - type.getConverter().convert( - newPropertyDefinition.getDefaultValue(), innerType, allDataTypes.left().value())); - } - } - } - /** - * Get property of resource + * Get property of component * - * @param resourceId + * @param componentId * @param propertyId * @param userId * @return either properties or response format */ - public Either<Entry<String, PropertyDefinition>, ResponseFormat> getProperty(String resourceId, String propertyId, String userId) { + + public Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> getComponentProperty(String componentId, String propertyId, String userId) { validateUserExists(userId, "create Component Instance", false); // Get the resource from DB - Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); + Either<Component, StorageOperationStatus> status = + toscaOperationFacade.getToscaElement(componentId); if (status.isRight()) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); } - Resource resource = status.left().value(); - - // verify property exist in resource - List<PropertyDefinition> properties = resource.getProperties(); - if (properties == null) { + Component component = status.left().value(); + List<PropertyDefinition> properties = component.getProperties(); + if(CollectionUtils.isEmpty(properties)) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "")); } - for (PropertyDefinition property : properties) { - if (property.getUniqueId().equals(propertyId) ) { - Map<String, PropertyDefinition> propMap = new HashMap<>(); - propMap.put(property.getName(), property); - return Either.left(propMap.entrySet().iterator().next()); + + for(PropertyDefinition property : properties) { + if(property.getUniqueId().equals(propertyId)) { + return Either.left(new EntryData<>(property.getName(), property)); } } return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "")); } + + public Either<List<PropertyDefinition>, ResponseFormat> getPropertiesList(String componentId, + String userId) { + validateUserExists(userId, "create Component Instance", false); + + // Get the resource from DB + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreProperties(false); + Either<Component, StorageOperationStatus> status = + toscaOperationFacade.getToscaElement(componentId); + if (status.isRight()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + } + Component component = status.left().value(); + List<PropertyDefinition> properties = component.getProperties(); + + return Either.left(properties); + } + + /** - * delete property of resource from graph + * delete property of component from graph * - * @param resourceId + * @param componentId * @param propertyId * @param userId * @return either properties or response format */ - public Either<Entry<String, PropertyDefinition>, ResponseFormat> deleteProperty(String resourceId, String propertyId, String userId) { - Either<Entry<String, PropertyDefinition>, ResponseFormat> result = null; + public Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> deletePropertyFromComponent(String componentId, String propertyId, String userId) { + + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> result = null; validateUserExists(userId, "delete Property", false); - StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); + // Get the resource from DB + Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade.getToscaElement(componentId); + if (getComponentRes.isRight()) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + return result; + } + Component component = getComponentRes.left().value(); + NodeTypeEnum nodeType = component.getComponentType().getNodeType(); + StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType); if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); + BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, nodeType.name().toLowerCase(), + componentId); result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); return result; } try { - - // Get the resource from DB - Either<Resource, StorageOperationStatus> getResourceRes = toscaOperationFacade.getToscaElement(resourceId); - if (getResourceRes.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); - return result; - } - Resource resource = getResourceRes.left().value(); - // verify that resource is checked-out and the user is the last // updater - if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { + if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) { result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); return result; } // verify property exist in resource - Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = + getComponentProperty(componentId, propertyId, userId); if (statusGetProperty.isRight()) { result = Either.right(statusGetProperty.right().value()); return result; } - StorageOperationStatus status = toscaOperationFacade.deletePropertyOfResource(resource, statusGetProperty.left().value().getKey()); + Map.Entry<String, PropertyDefinition> propertyDefinitionEntry = statusGetProperty.left().value(); + + // verify that the property is not used by operation + if (isPropertyUsedByOperation(component, propertyDefinitionEntry.getValue())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus + .PROPERTY_USED_BY_OPERATION)); + } + + StorageOperationStatus status = + toscaOperationFacade.deletePropertyOfComponent(component, propertyDefinitionEntry.getKey()); if (status != StorageOperationStatus.OK) { - result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), resource.getName())); + result = Either.right(componentsUtils.getResponseFormat(componentsUtils + .convertFromStorageResponse(status), component.getName())); return result; } - result = Either.left(statusGetProperty.left().value()); + result = Either.left(propertyDefinitionEntry); return result; } finally { commitOrRollback(result); // unlock component - graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); + graphLockOperation.unlockComponent(componentId, nodeType); + } + } + + public boolean isPropertyUsedByOperation(Component component, + PropertyDefinition propertyDefinitionEntry) { + + // Component's own interfaces + Map<String, InterfaceDefinition> interfaces = component.getInterfaces(); + if(MapUtils.isNotEmpty(interfaces)){ + for(Map.Entry<String, InterfaceDefinition> interfaceEntry : interfaces.entrySet()) { + if (isPropertyExistInOperationInterface(propertyDefinitionEntry, interfaceEntry.getValue())) { + return true; + } + } + } + + // Component's child's component interfaces + if(isPropertyUsedInCIInterfaces(component.getComponentInstancesInterfaces(), propertyDefinitionEntry)){ + return true; + } + + // Component's parent's component interfaces + Either<List<Component>, StorageOperationStatus> componentList = toscaOperationFacade.getParentComponents(component.getUniqueId()); + if(componentList.isLeft()){ + for (Component parentComponent : componentList.left().value()) { + if(isPropertyUsedInCIInterfaces(parentComponent.getComponentInstancesInterfaces(), propertyDefinitionEntry)){ + return true; + } + } + } + + return false; + } + + private boolean isPropertyUsedInCIInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces, PropertyDefinition propertyDefinitionEntry){ + if(MapUtils.isNotEmpty(componentInstanceInterfaces)){ + for (Entry<String, List<ComponentInstanceInterface>> interfaceEntry : componentInstanceInterfaces.entrySet()) { + for (ComponentInstanceInterface instanceInterface : interfaceEntry.getValue()) { + if (isPropertyExistInOperationInterface(propertyDefinitionEntry, instanceInterface)) { + return true; + } + } + } } + return false; + } + + private boolean isPropertyExistInOperationInterface(PropertyDefinition propertyDefinition, + InterfaceDefinition interfaceDefinition) { + Map<String, OperationDataDefinition> operations = + interfaceDefinition.getOperations(); + for(Map.Entry<String, OperationDataDefinition> operationEntry : operations + .entrySet()) { + Optional<OperationInputDefinition> inputWithDeletedPropertyCandidate = + getInputWithDeclaredProperty(propertyDefinition, operationEntry); + + if(inputWithDeletedPropertyCandidate.isPresent()) { + return true; + } + } + return false; + } + + private Optional<OperationInputDefinition> getInputWithDeclaredProperty(PropertyDefinition propertyDefinition, + Map.Entry<String, OperationDataDefinition> operationEntry) { + ListDataDefinition<OperationInputDefinition> inputs = + operationEntry.getValue().getInputs(); + List<OperationInputDefinition> operationInputsList = + Objects.isNull(inputs) ? null : inputs.getListToscaDataDefinition(); + + if(CollectionUtils.isEmpty(operationInputsList)) { + return Optional.empty(); + } + + return operationInputsList.stream().filter(input -> input.getInputId().equals(propertyDefinition.getUniqueId())).findAny(); } /** * update property * - * @param resourceId + * @param componentId * @param propertyId * @param newPropertyDefinition * @param userId * @return either properties or response format */ - public Either<EntryData<String, PropertyDefinition>, ResponseFormat> updateProperty(String resourceId, String propertyId, PropertyDefinition newPropertyDefinition, String userId) { + + public Either<EntryData<String, PropertyDefinition>, ResponseFormat> updateComponentProperty(String componentId, + String propertyId, + PropertyDefinition newPropertyDefinition, + String userId) { Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null; - Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); + Either<Component, StorageOperationStatus> status = toscaOperationFacade.getToscaElement( + componentId); if (status.isRight()) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); } - Resource resource = status.left().value(); + Component component = status.left().value(); + NodeTypeEnum nodeType = component.getComponentType().getNodeType(); - if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { + if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); } - StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); + StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType); if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); + BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, nodeType.name().toLowerCase(), + componentId); result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); return result; } try { - Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = + getComponentProperty(componentId, propertyId, userId); if (statusGetProperty.isRight()) { result = Either.right(statusGetProperty.right().value()); return result; } String propertyName = statusGetProperty.left().value().getKey(); - Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); - if (allDataTypes.isRight()) { - result = Either.right(allDataTypes.right().value()); - return result; - } - Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); - - Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); - if (defaultValuesValidation.isRight()) { - result = Either.right(defaultValuesValidation.right().value()); - return result; - } - - Either<PropertyDefinition, StorageOperationStatus> either = handleProperty(newPropertyDefinition, dataTypes); - if (either.isRight()) { - log.debug("Problem while updating property with id {}. Reason - {}", propertyId, either.right().value()); - result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); - return result; - } - - - either = toscaOperationFacade.updatePropertyOfResource(resource, newPropertyDefinition); + Either<PropertyDefinition, StorageOperationStatus> either = + toscaOperationFacade.updatePropertyOfComponent(component, newPropertyDefinition); if (either.isRight()) { - result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); + result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), component.getName())); return result; } @@ -342,18 +452,30 @@ public class PropertyBusinessLogic extends BaseBusinessLogic { } finally { commitOrRollback(result); - graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); + graphLockOperation.unlockComponent(componentId, nodeType); } } + private boolean isPropertyExistInComponent(List<PropertyDefinition> properties, String propertyName) { + if(CollectionUtils.isEmpty(properties)) { + return false; + } + + Optional<PropertyDefinition> propertyCandidate = + properties.stream().filter(property -> property.getName().equals(propertyName)) + .findAny(); + + return propertyCandidate.isPresent(); + } + private boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) { boolean result = false; if (!CollectionUtils.isEmpty(properties)) { for (PropertyDefinition propertyDefinition : properties) { if ( propertyDefinition.getName().equals(propertyName) && - (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) { + (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) { result = true; break; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java new file mode 100644 index 0000000000..7f49e389ef --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java @@ -0,0 +1,153 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.property; + +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; +import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@org.springframework.stereotype.Component +public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Component, PropertyDataDefinition> { + + private ToscaOperationFacade toscaOperationFacade; + PropertyBusinessLogic propertyBL; + + + public ComponentPropertyDeclarator(ComponentsUtils componentsUtils, + PropertyOperation propertyOperation, + ToscaOperationFacade toscaOperationFacade, + PropertyBusinessLogic propertyBL) { + super(componentsUtils, propertyOperation); + this.toscaOperationFacade = toscaOperationFacade; + this.propertyBL = propertyBL; + } + + @Override + PropertyDataDefinition createDeclaredProperty(PropertyDataDefinition prop) { + return new PropertyDataDefinition(prop); + } + + @Override + Either<?, StorageOperationStatus> updatePropertiesValues(Component component, + String propertiesOwnerId, + List<PropertyDataDefinition> properties) { + if(CollectionUtils.isNotEmpty(properties)) { + for(PropertyDataDefinition property : properties) { + Either<PropertyDefinition, StorageOperationStatus> + storageStatus = toscaOperationFacade + .updatePropertyOfComponent(component, new PropertyDefinition(property)); + if(storageStatus.isRight()) { + return Either.right(storageStatus.right().value()); + } + } + } + return Either.left(properties); + } + + @Override + Optional<Component> resolvePropertiesOwner(Component component, String propertiesOwnerId) { + return Optional.of( component); + } + + @Override + void addPropertiesListToInput(PropertyDataDefinition declaredProp, + InputDefinition input) { + + List<ComponentInstanceProperty> propertiesList = input.getProperties(); + if(propertiesList == null) { + propertiesList = new ArrayList<>(); // adding the property with the new value for UI + } + propertiesList.add(new ComponentInstanceProperty(declaredProp)); + input.setProperties(propertiesList); + } + + @Override + public StorageOperationStatus unDeclarePropertiesAsInputs(Component component, + InputDefinition input) { + PropertyDefinition propertyDefinition = new PropertyDefinition(input); + + if(propertyBL.isPropertyUsedByOperation(component, propertyDefinition)) { + return StorageOperationStatus.DECLARED_INPUT_USED_BY_OPERATION; + } + + Optional<PropertyDefinition> propertyToUpdateCandidate = + getDeclaredPropertyByInputId(component, input.getUniqueId()); + + if(propertyToUpdateCandidate.isPresent()) { + PropertyDefinition propertyToUpdate = propertyToUpdateCandidate.get(); + return unDeclareInput(component, input, propertyToUpdate); + } + + + return StorageOperationStatus.OK; + } + + private StorageOperationStatus unDeclareInput(Component component, + InputDefinition input, + PropertyDefinition propertyToUpdate) { + prepareValueBeforeDelete(input, propertyToUpdate, Collections.emptyList()); + propertyToUpdate.setValue(input.getDefaultValue()); + Either<PropertyDefinition, StorageOperationStatus> status = toscaOperationFacade + .updatePropertyOfComponent(component, propertyToUpdate); + if(status.isRight()) { + return status.right().value(); + } + + return StorageOperationStatus.OK; + } + + private Optional<PropertyDefinition> getDeclaredPropertyByInputId(Component component, + String inputId) { + List<PropertyDefinition> properties = component.getProperties(); + + if(CollectionUtils.isEmpty(properties)) { + return Optional.empty(); + } + + for(PropertyDefinition propertyDefinition : properties) { + List<GetInputValueDataDefinition> getInputValues = propertyDefinition.getGetInputValues(); + if(CollectionUtils.isEmpty(getInputValues)) { + continue; + } + + Optional<GetInputValueDataDefinition> getInputCandidate = + getInputValues.stream().filter(getInput -> getInput.getInputId().equals(inputId)) + .findAny(); + + if(getInputCandidate.isPresent()) { + return Optional.of(propertyDefinition); + } + } + + return Optional.empty(); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java index a5ba0003d2..437ae2d67d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java @@ -87,20 +87,44 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties } private InputDefinition createInput(String componentId, PROPERTYOWNER propertiesOwner, ComponentInstancePropInput propInput, PropertyDataDefinition prop) { - String generatedInputName = generateInputName(propertiesOwner.getNormalizedName(), propInput); + String generatedInputName = generateInputName(propertiesOwner instanceof + Service ? null : propertiesOwner.getNormalizedName(), + propInput); return createInputFromProperty(componentId, propertiesOwner, generatedInputName, propInput, prop); } private String generateInputName(String inputName, ComponentInstancePropInput propInput) { + String declaredInputName = inputName; String[] parsedPropNames = propInput.getParsedPropNames(); + if(parsedPropNames != null){ - for(String str: parsedPropNames){ - inputName += "_" + str; - } + declaredInputName = handleInputName(inputName, parsedPropNames); } else { - inputName += "_" + propInput.getName(); + String[] propName = {propInput.getName()}; + declaredInputName = handleInputName(inputName, propName); } - return inputName; + + return declaredInputName; + } + + private String handleInputName(String inputName, String[] parsedPropNames) { + String prefix; + int startingIndex; + + if(Objects.isNull(inputName)) { + prefix = parsedPropNames[0]; + startingIndex = 1; + } else { + prefix = inputName; + startingIndex = 0; + } + + while(startingIndex < parsedPropNames.length){ + prefix += "_" + parsedPropNames[startingIndex]; + startingIndex ++; + } + + return prefix; } private PropertyDataDefinition resolveProperty(List<PROPERTYTYPE> propertiesToCreate, ComponentInstancePropInput propInput) { @@ -131,14 +155,20 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties input.setPropertyId(propInput.getUniqueId()); input.setValue(null); changePropertyValueToGetInputValue(inputName, parsedPropNames, input, prop, complexProperty); - ((IComponentInstanceConnectedElement)prop).setComponentInstanceId(propertiesOwner.getUniqueId()); - ((IComponentInstanceConnectedElement)prop).setComponentInstanceName(propertiesOwner.getName()); + + if(prop instanceof IComponentInstanceConnectedElement) { + ((IComponentInstanceConnectedElement) prop) + .setComponentInstanceId(propertiesOwner.getUniqueId()); + ((IComponentInstanceConnectedElement) prop) + .setComponentInstanceName(propertiesOwner.getName()); + } return input; } private void changePropertyValueToGetInputValue(String inputName, String[] parsedPropNames, InputDefinition input, PropertyDataDefinition prop, boolean complexProperty) { JSONObject jobject = new JSONObject(); - if(prop.getValue() == null || prop.getValue().isEmpty()){ + String value = (String) prop.getValue(); + if(value == null || value.isEmpty()){ if(complexProperty){ jobject = createJSONValueForProperty(parsedPropNames.length -1, parsedPropNames, jobject, inputName); @@ -153,7 +183,7 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties }else{ - String value = prop.getValue(); + //String value = value; Object objValue = new Yaml().load(value); if( objValue instanceof Map || objValue instanceof List){ if(!complexProperty){ diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarationOrchestrator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarationOrchestrator.java index 937e2ccfc8..babddc4da1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarationOrchestrator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarationOrchestrator.java @@ -22,14 +22,21 @@ public class PropertyDeclarationOrchestrator { private ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator; private PolicyPropertyDeclarator policyPropertyDeclarator; private GroupPropertyDeclarator groupPropertyDeclarator; + private ComponentPropertyDeclarator servicePropertyDeclarator; private List<PropertyDeclarator> propertyDeclarators; - public PropertyDeclarationOrchestrator(ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDeclarator, ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator, PolicyPropertyDeclarator policyPropertyDeclarator, GroupPropertyDeclarator groupPropertyDeclarator) { + public PropertyDeclarationOrchestrator( + ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDeclarator, + ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator, + PolicyPropertyDeclarator policyPropertyDeclarator, + GroupPropertyDeclarator groupPropertyDeclarator, + ComponentPropertyDeclarator servicePropertyDeclarator) { this.componentInstanceInputPropertyDeclarator = componentInstanceInputPropertyDeclarator; this.componentInstancePropertyDeclarator = componentInstancePropertyDeclarator; this.policyPropertyDeclarator = policyPropertyDeclarator; this.groupPropertyDeclarator = groupPropertyDeclarator; - propertyDeclarators = Arrays.asList(componentInstanceInputPropertyDeclarator, componentInstancePropertyDeclarator, policyPropertyDeclarator, groupPropertyDeclarator); + this.servicePropertyDeclarator = servicePropertyDeclarator; + propertyDeclarators = Arrays.asList(componentInstanceInputPropertyDeclarator, componentInstancePropertyDeclarator, policyPropertyDeclarator, groupPropertyDeclarator, servicePropertyDeclarator); } public Either<List<InputDefinition>, StorageOperationStatus> declarePropertiesToInputs(Component component, ComponentInstInputsMap componentInstInputsMap) { @@ -64,6 +71,9 @@ public class PropertyDeclarationOrchestrator { if (isNotEmpty(componentInstInputsMap.getGroupProperties())) { return groupPropertyDeclarator; } + if(isNotEmpty(componentInstInputsMap.getServiceProperties())) { + return servicePropertyDeclarator; + } throw new IllegalStateException("there are no properties selected for declaration"); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java index 5b8d6dcc17..4502012bd9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java @@ -23,8 +23,27 @@ package org.openecomp.sdc.be.servlets; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; import fj.data.Either; -import org.openecomp.sdc.be.components.impl.*; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic; +import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ElementBusinessLogic; +import org.openecomp.sdc.be.components.impl.GroupBusinessLogic; +import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic; +import org.openecomp.sdc.be.components.impl.MonitoringBusinessLogic; +import org.openecomp.sdc.be.components.impl.PolicyBusinessLogic; +import org.openecomp.sdc.be.components.impl.PolicyTypeBusinessLogic; +import org.openecomp.sdc.be.components.impl.ProductBusinessLogic; +import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; import org.openecomp.sdc.be.components.scheduledtasks.ComponentsCleanBusinessLogic; import org.openecomp.sdc.be.components.upgrade.UpgradeBusinessLogic; @@ -35,8 +54,11 @@ import org.openecomp.sdc.be.ecomp.converters.AssetMetadataConverter; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.PropertyConstraint; +import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintJacksonDeserializer; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; @@ -51,8 +73,12 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.function.Supplier; public class BeGenericServlet extends BasicServlet { @@ -79,8 +105,8 @@ public class BeGenericServlet extends BasicServlet { private static Response buildOkResponseStatic(Object entity) { return Response.status(Response.Status.OK) - .entity(entity) - .build(); + .entity(entity) + .build(); } protected Response buildOkResponse(ResponseFormat errorResponseWrapper, Object entity) { @@ -215,8 +241,8 @@ public class BeGenericServlet extends BasicServlet { protected String getContentDispositionValue(String artifactFileName) { return new StringBuilder().append("attachment; filename=\"").append(artifactFileName).append("\"").toString(); } - - + + protected ComponentBusinessLogic getComponentBL(ComponentTypeEnum componentTypeEnum, ServletContext context) { ComponentBusinessLogic businessLogic; @@ -243,8 +269,8 @@ public class BeGenericServlet extends BasicServlet { <T> void convertJsonToObjectOfClass(String json, Wrapper<T> policyWrapper, Class<T> clazz, Wrapper<Response> errorWrapper) { T object = null; ObjectMapper mapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); try { log.trace("Starting to convert json to object. Json=\n{}", json); @@ -266,4 +292,143 @@ public class BeGenericServlet extends BasicServlet { errorWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT))); } } + + protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertyModel(String componentId, + String data) { + JSONParser parser = new JSONParser(); + JSONObject root; + try { + Map<String, PropertyDefinition> properties = new HashMap<String, PropertyDefinition>(); + root = (JSONObject) parser.parse(data); + + Set entrySet = root.entrySet(); + Iterator iterator = entrySet.iterator(); + while (iterator.hasNext()) { + Entry next = (Entry) iterator.next(); + String propertyName = (String) next.getKey(); + JSONObject value = (JSONObject) next.getValue(); + String jsonString = value.toJSONString(); + Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, PropertyDefinition.class); + if (convertJsonToObject.isRight()) { + return Either.right(convertJsonToObject.right().value()); + } + PropertyDefinition propertyDefinition = convertJsonToObject.left().value(); + String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(componentId, (String) propertyName); + propertyDefinition.setUniqueId(uniqueId); + properties.put(propertyName, propertyDefinition); + } + + return Either.left(properties); + } catch (ParseException e) { + log.info("Property conetnt is invalid - {}", data); + return Either.right(ActionStatus.INVALID_CONTENT); + } + } + + protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertiesListForUpdate(String data) { + + Map<String, PropertyDefinition> properties = new HashMap<>(); + JSONParser parser = new JSONParser(); + JSONArray jsonArray; + + try { + jsonArray = (JSONArray) parser.parse(data); + for (Object jsonElement : jsonArray) { + String propertyAsString = jsonElement.toString(); + Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(propertyAsString, PropertyDefinition.class); + + if (convertJsonToObject.isRight()) { + return Either.right(convertJsonToObject.right().value()); + } + + PropertyDefinition propertyDefinition = convertJsonToObject.left().value(); + properties.put(propertyDefinition.getName(), propertyDefinition); + } + + return Either.left(properties); + } catch (Exception e) { + log.info("Property content is invalid - {}", data); + return Either.right(ActionStatus.INVALID_CONTENT); + } + + } + + + protected String propertyToJson(Map.Entry<String, PropertyDefinition> property) { + JSONObject root = new JSONObject(); + String propertyName = property.getKey(); + PropertyDefinition propertyDefinition = property.getValue(); + JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition); + root.put(propertyName, propertyDefinitionO); + propertyDefinition.getType(); + return root.toString(); + } + + private JSONObject getPropertyDefinitionJSONObject(PropertyDefinition propertyDefinition) { + + Either<String, ActionStatus> either = convertObjectToJson(propertyDefinition); + if (either.isRight()) { + return new JSONObject(); + } + String value = either.left().value(); + try { + JSONObject root = (JSONObject) new JSONParser().parse(value); + return root; + } catch (ParseException e) { + log.info("failed to convert input to json"); + log.debug("failed to convert to json", e); + return new JSONObject(); + } + + } + + protected <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) { + T t = null; + Type constraintType = new TypeToken<PropertyConstraint>() { + }.getType(); + Gson + gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintDeserialiser()).create(); + try { + log.trace("convert json to object. json=\n {}", data); + t = gson.fromJson(data, clazz); + if (t == null) { + log.info("object is null after converting from json"); + return Either.right(ActionStatus.INVALID_CONTENT); + } + } catch (Exception e) { + // INVALID JSON + log.info("failed to convert from json"); + log.debug("failed to convert from json", e); + return Either.right(ActionStatus.INVALID_CONTENT); + } + return Either.left(t); + } + + private <T> Either<String, ActionStatus> convertObjectToJson(PropertyDefinition propertyDefinition) { + Type constraintType = new TypeToken<PropertyConstraint>() { + }.getType(); + Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintSerialiser()).create(); + try { + log.trace("convert object to json. propertyDefinition= {}", propertyDefinition); + String json = gson.toJson(propertyDefinition); + if (json == null) { + log.info("object is null after converting to json"); + return Either.right(ActionStatus.INVALID_CONTENT); + } + return Either.left(json); + } catch (Exception e) { + // INVALID JSON + log.info("failed to convert to json"); + log.debug("failed to convert fto json", e); + return Either.right(ActionStatus.INVALID_CONTENT); + } + + } + + protected PropertyBusinessLogic getPropertyBL(ServletContext context) { + WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); + WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); + PropertyBusinessLogic propertytBl = webApplicationContext.getBean(PropertyBusinessLogic.class); + return propertytBl; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java index 042303e2c3..b5e28148da 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java @@ -1139,7 +1139,7 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { return Either.left(requirementCapabilityRelDef); } - private <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) { + public <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) { try { log.trace("convert json to object. json=\n {}", data); T t; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java new file mode 100644 index 0000000000..0edce61bae --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java @@ -0,0 +1,390 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.servlets; + +import com.jcabi.aspects.Loggable; +import fj.data.Either; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.resources.data.EntryData; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Singleton; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; +import java.util.Map; + +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog") +@Api(value = "Component Property Servlet", description = "Property Servlet - used to create properties in Service and Resource") +@Singleton +public class ComponentPropertyServlet extends BeGenericServlet { + + private static final Logger log = LoggerFactory.getLogger(ComponentPropertyServlet.class); + + @POST + @Path("services/{serviceId}/properties") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Create Service Property", httpMethod = "POST", notes = "Returns created service property", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 201, message = "Service property created"), + @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "Service property already exist") }) + public Response createPropertyInService(@ApiParam(value = "service id to update with new property", required = true) @PathParam("serviceId") final String serviceId, + @ApiParam(value = "Service property to be created", required = true) String data, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return createProperty(serviceId, data, request, userId); + } + + @POST + @Path("resources/{resourceId}/properties") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Create Resource Property", httpMethod = "POST", notes = "Returns created service property", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource property created"), + @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "Resource property already exist") }) + public Response createPropertyInResource(@ApiParam(value = "Resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId, + @ApiParam(value = "Resource property to be created", required = true) String data, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return createProperty(resourceId, data, request, userId); + } + + + @GET + @Path("services/{serviceId}/properties/{propertyId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get Service Property", httpMethod = "GET", notes = "Returns property of service", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Service property not found") }) + public Response getPropertyInService(@ApiParam(value = "service id of property", required = true) + @PathParam("serviceId") final String serviceId, @ApiParam(value = "property id to get", required = true) @PathParam("propertyId") final String propertyId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return getProperty(serviceId, propertyId, request, userId); + } + + @GET + @Path("resources/{resourceId}/properties/{propertyId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get Resource Property", httpMethod = "GET", notes = "Returns property of resource", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Resource property not found") }) + public Response getPropertyInResource(@ApiParam(value = "resource id of property", required = true) + @PathParam("resourceId") final String resourceId, @ApiParam(value = "property id to get", required = true) @PathParam("propertyId") final String propertyId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return getProperty(resourceId, propertyId, request, userId); + } + + @GET + @Path("services/{serviceId}/properties") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get Service Property", httpMethod = "GET", notes = "Returns property list of service", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Service property not found") }) + public Response getPropertyListInService(@ApiParam(value = "service id of property", required = true) @PathParam("serviceId") final String serviceId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return getPropertyList(serviceId, request, userId); + } + + @GET + @Path("resources/{resourceId}/properties") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get Resource Property", httpMethod = "GET", notes = "Returns property list of resource", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Resource property not found") }) + public Response getPropertyListInResource(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return getPropertyList(resourceId, request, userId); + } + + @DELETE + @Path("services/{serviceId}/properties/{propertyId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Delete Service Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Service property not found") }) + public Response deletePropertyInService(@ApiParam(value = "service id of property", required = true) @PathParam("serviceId") final String serviceId, + @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return deleteProperty(serviceId, propertyId, request, userId); + } + + @DELETE + @Path("resources/{resourceId}/properties/{propertyId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Delete Resource Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Resource property not found") }) + public Response deletePropertyInResource(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId, + @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return deleteProperty(resourceId, propertyId, request, userId); + } + + @PUT + @Path("services/{serviceId}/properties") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Update Service Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "Service property updated"), + @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") }) + public Response updatePropertyInService(@ApiParam(value = "service id to update with new property", required = true) @PathParam("serviceId") final String serviceId, + @ApiParam(value = "Service property to update", required = true) String data, @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return updateProperty(serviceId, data, request, userId); + } + + @PUT + @Path("resources/{resourceId}/properties") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Update Resource Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource property updated"), + @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") }) + public Response updatePropertyInResource(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId, + @ApiParam(value = "Resource property to update", required = true) String data, @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return updateProperty(resourceId, data, request, userId); + } + + private Response createProperty(String componentId, String data, HttpServletRequest request,String userId) { + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data); + + try{ + Either<Map<String, PropertyDefinition>, ActionStatus> propertyDefinition = + getPropertyModel(componentId, data); + if (propertyDefinition.isRight()) { + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(propertyDefinition.right().value()); + return buildErrorResponse(responseFormat); + } + + Map<String, PropertyDefinition> properties = propertyDefinition.left().value(); + if (properties == null || properties.size() != 1) { + log.info("Property content is invalid - {}", data); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); + return buildErrorResponse(responseFormat); + } + + Map.Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next(); + PropertyDefinition newPropertyDefinition = entry.getValue(); + newPropertyDefinition.setParentUniqueId(componentId); + String propertyName = newPropertyDefinition.getName(); + + PropertyBusinessLogic propertyBL = getPropertyBL(context); + Either<EntryData<String, PropertyDefinition>, ResponseFormat> addPropertyEither = + propertyBL.addPropertyToComponent(componentId, propertyName, newPropertyDefinition, userId); + + if(addPropertyEither.isRight()) { + return buildErrorResponse(addPropertyEither.right().value()); + } + + return buildOkResponse(newPropertyDefinition); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property"); + log.debug("create property failed with exception", e); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } + + + private Response updateProperty(String componentId, String data, HttpServletRequest request, String userId) { + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}", url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); +// + try { + // convert json to PropertyDefinition + + Either<Map<String, PropertyDefinition>, ActionStatus> propertiesListEither = + getPropertiesListForUpdate(data); + if (propertiesListEither.isRight()) { + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(propertiesListEither.right().value()); + return buildErrorResponse(responseFormat); + } + Map<String, PropertyDefinition> properties = propertiesListEither.left().value(); + if (properties == null) { + log.info("Property content is invalid - {}", data); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); + return buildErrorResponse(responseFormat); + } + + // update property + + PropertyBusinessLogic businessLogic = getPropertyBL(context); + for(PropertyDefinition propertyDefinition : properties.values()) { + Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = + businessLogic.updateComponentProperty( + componentId, propertyDefinition.getUniqueId(), propertyDefinition, userId); + if (status.isRight()) { + log.info("Failed to update Property. Reason - ", status.right().value()); + return buildErrorResponse(status.right().value()); + } + EntryData<String, PropertyDefinition> property = status.left().value(); + PropertyDefinition updatedPropertyDefinition = property.getValue(); + + log.debug("Property id {} updated successfully ", updatedPropertyDefinition.getUniqueId()); + } + + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK); + return buildOkResponse(responseFormat, properties); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property"); + log.debug("update property failed with exception", e); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + + } + } + + private Response getProperty(String componentId, String propertyId, HttpServletRequest request, String userId) { + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} modifier id is {}", url, userId); + + try { + PropertyBusinessLogic propertyBL = getPropertyBL(context); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> retrievedPropertyEither = + propertyBL.getComponentProperty(componentId, propertyId, userId); + + if(retrievedPropertyEither.isRight()) { + return buildErrorResponse(retrievedPropertyEither.right().value()); + } + + return buildOkResponse(retrievedPropertyEither.left().value()); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property"); + log.debug("get property failed with exception", e); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } + private Response getPropertyList(String componentId, HttpServletRequest request, String userId) { + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} modifier id is {}", url, userId); + + try { + PropertyBusinessLogic propertyBL = getPropertyBL(context); + Either<List<PropertyDefinition>, ResponseFormat> propertiesListEither = + propertyBL.getPropertiesList(componentId, userId); + + if(propertiesListEither.isRight()) { + return buildErrorResponse(propertiesListEither.right().value()); + } + + return buildOkResponse(propertiesListEither.left().value()); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property"); + log.debug("get property failed with exception", e); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } + private Response deleteProperty(String componentId, String propertyId, HttpServletRequest request, String userId) { + ServletContext context = request.getSession().getServletContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} modifier id is {}", url, userId); + + try { + + // delete the property + PropertyBusinessLogic businessLogic = getPropertyBL(context); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> status = + businessLogic.deletePropertyFromComponent(componentId, propertyId, userId); + if (status.isRight()) { + log.debug("Failed to delete Property. Reason - ", status.right().value()); + return buildErrorResponse(status.right().value()); + } + Map.Entry<String, PropertyDefinition> property = status.left().value(); + String name = property.getKey(); + PropertyDefinition propertyDefinition = property.getValue(); + + log.debug("Property {} deleted successfully with id {}", name, propertyDefinition.getUniqueId()); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT); + return buildOkResponse(responseFormat, propertyToJson(property)); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property"); + log.debug("delete property failed with exception", e); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + + } + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/PropertyServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/PropertyServlet.java deleted file mode 100644 index 12d788dd45..0000000000 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/PropertyServlet.java +++ /dev/null @@ -1,369 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.servlets; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; -import com.jcabi.aspects.Loggable; -import fj.data.Either; -import io.swagger.annotations.*; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; -import org.openecomp.sdc.be.config.BeEcompErrorManager; -import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.impl.WebAppContextWrapper; -import org.openecomp.sdc.be.model.PropertyConstraint; -import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.User; -import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser; -import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintSerialiser; -import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; -import org.openecomp.sdc.be.resources.data.EntryData; -import org.openecomp.sdc.common.api.Constants; -import org.openecomp.sdc.common.log.wrappers.Logger; -import org.openecomp.sdc.exception.ResponseFormat; -import org.springframework.web.context.WebApplicationContext; - -import javax.inject.Singleton; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) -@Path("/v1/catalog") -@Api(value = "Resource Property Servlet", description = "Resource Property Servlet") -@Singleton -public class PropertyServlet extends BeGenericServlet { - - private static final Logger log = Logger.getLogger(PropertyServlet.class.getName()); - - @POST - @Path("resources/{resourceId}/properties") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Create Resource Property", httpMethod = "POST", notes = "Returns created resource property", response = Response.class) - @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource property created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), - @ApiResponse(code = 409, message = "Resource property already exist") }) - public Response createProperty(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId, @ApiParam(value = "Resource property to be created", required = true) String data, - @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { - - ServletContext context = request.getSession().getServletContext(); - - String url = request.getMethod() + " " + request.getRequestURI(); - log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data); - - try { - // convert json to PropertyDefinition - Either<Map<String, PropertyDefinition>, ActionStatus> either = getPropertyModel(resourceId, data); - if (either.isRight()) { - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(either.right().value()); - return buildErrorResponse(responseFormat); - } - Map<String, PropertyDefinition> properties = either.left().value(); - if (properties == null || properties.size() != 1) { - log.info("Property conetnt is invalid - {}", data); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); - return buildErrorResponse(responseFormat); - } - Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next(); - String propertyName = entry.getKey(); - PropertyDefinition newPropertyDefinition = entry.getValue(); - - // create the new property - PropertyBusinessLogic businessLogic = getPropertyBL(context); - Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = businessLogic.createProperty(resourceId, propertyName, newPropertyDefinition, userId); - if (status.isRight()) { - log.info("Failed to create Property. Reason - ", status.right().value()); - return buildErrorResponse(status.right().value()); - } - EntryData<String, PropertyDefinition> property = status.left().value(); - String name = property.getKey(); - PropertyDefinition propertyDefinition = property.getValue(); - - log.debug("Property {} created successfully with id {}", name, propertyDefinition.getUniqueId()); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.CREATED); - return buildOkResponse(responseFormat, propertyToJson(property)); - - } catch (Exception e) { - BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property"); - log.debug("create property failed with exception", e); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); - return buildErrorResponse(responseFormat); - - } - } - - @GET - @Path("resources/{resourceId}/properties/{propertyId}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Create Resource Property", httpMethod = "GET", notes = "Returns property of resource", response = Response.class) - @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), - @ApiResponse(code = 404, message = "Resource property not found") }) - public Response getProperty(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId, @ApiParam(value = "proerty id to get", required = true) @PathParam("propertyId") final String propertyId, - @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { - - ServletContext context = request.getSession().getServletContext(); - - String url = request.getMethod() + " " + request.getRequestURI(); - log.debug("Start handle request of {}, modifier id is {}", url, userId); - - try { - - // - PropertyBusinessLogic businessLogic = getPropertyBL(context); - Either<Entry<String, PropertyDefinition>, ResponseFormat> status = businessLogic.getProperty(resourceId, propertyId, userId); - - if (status.isRight()) { - log.info("Failed to get Property. Reason - ", status.right().value()); - return buildErrorResponse(status.right().value()); - } - Entry<String, PropertyDefinition> property = status.left().value(); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK); - return buildOkResponse(responseFormat, propertyToJson(property)); - } catch (Exception e) { - BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Property"); - log.debug("get property failed with exception", e); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); - return buildErrorResponse(responseFormat); - - } - } - - @DELETE - @Path("resources/{resourceId}/properties/{propertyId}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Create Resource Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class) - @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), - @ApiResponse(code = 404, message = "Resource property not found") }) - public Response deleteProperty(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId, - @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { - - ServletContext context = request.getSession().getServletContext(); - - String url = request.getMethod() + " " + request.getRequestURI(); - log.debug("Start handle request of {} modifier id is {}", url, userId); - - try { - - // delete the property - PropertyBusinessLogic businessLogic = getPropertyBL(context); - Either<Entry<String, PropertyDefinition>, ResponseFormat> status = businessLogic.deleteProperty(resourceId, propertyId, userId); - if (status.isRight()) { - log.debug("Failed to delete Property. Reason - ", status.right().value()); - return buildErrorResponse(status.right().value()); - } - Entry<String, PropertyDefinition> property = status.left().value(); - String name = property.getKey(); - PropertyDefinition propertyDefinition = property.getValue(); - - log.debug("Property {} deleted successfully with id {}", name, propertyDefinition.getUniqueId()); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT); - return buildOkResponse(responseFormat, propertyToJson(property)); - - } catch (Exception e) { - BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property"); - log.debug("delete property failed with exception", e); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); - return buildErrorResponse(responseFormat); - - } - } - - @PUT - @Path("resources/{resourceId}/properties/{propertyId}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Update Resource Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class) - @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource property updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") }) - public Response updateProperty(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId, - @ApiParam(value = "proerty id to update", required = true) @PathParam("propertyId") final String propertyId, @ApiParam(value = "Resource property to update", required = true) String data, @Context final HttpServletRequest request, - @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { - - ServletContext context = request.getSession().getServletContext(); - - String url = request.getMethod() + " " + request.getRequestURI(); - log.debug("Start handle request of {}", url); - - // get modifier id - User modifier = new User(); - modifier.setUserId(userId); - log.debug("modifier id is {}", userId); - - try { - // convert json to PropertyDefinition - Either<Map<String, PropertyDefinition>, ActionStatus> either = getPropertyModel(resourceId, data); - if (either.isRight()) { - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(either.right().value()); - return buildErrorResponse(responseFormat); - } - Map<String, PropertyDefinition> properties = either.left().value(); - if (properties == null || properties.size() != 1) { - log.info("Property conetnt is invalid - {}", data); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); - return buildErrorResponse(responseFormat); - } - Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next(); - PropertyDefinition newPropertyDefinition = entry.getValue(); - - // update property - PropertyBusinessLogic businessLogic = getPropertyBL(context); - Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = businessLogic.updateProperty(resourceId, propertyId, newPropertyDefinition, userId); - if (status.isRight()) { - log.info("Failed to update Property. Reason - ", status.right().value()); - return buildErrorResponse(status.right().value()); - } - EntryData<String, PropertyDefinition> property = status.left().value(); - PropertyDefinition propertyDefinition = property.getValue(); - - log.debug("Property id {} updated successfully ", propertyDefinition.getUniqueId()); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK); - return buildOkResponse(responseFormat, propertyToJson(property)); - - } catch (Exception e) { - BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property"); - log.debug("update property failed with exception", e); - ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); - return buildErrorResponse(responseFormat); - - } - } - - private Either<Map<String, PropertyDefinition>, ActionStatus> getPropertyModel(String resourceId, String data) { - JSONParser parser = new JSONParser(); - JSONObject root; - try { - Map<String, PropertyDefinition> properties = new HashMap<>(); - root = (JSONObject) parser.parse(data); - - Set entrySet = root.entrySet(); - Iterator iterator = entrySet.iterator(); - while (iterator.hasNext()) { - Entry next = (Entry) iterator.next(); - String propertyName = (String) next.getKey(); - JSONObject value = (JSONObject) next.getValue(); - String jsonString = value.toJSONString(); - Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, PropertyDefinition.class); - if (convertJsonToObject.isRight()) { - return Either.right(convertJsonToObject.right().value()); - } - PropertyDefinition propertyDefinition = convertJsonToObject.left().value(); - String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId, (String) propertyName); - propertyDefinition.setUniqueId(uniqueId); - properties.put(propertyName, propertyDefinition); - } - - return Either.left(properties); - } catch (ParseException e) { - log.info("Property conetnt is invalid - {}", data); - return Either.right(ActionStatus.INVALID_CONTENT); - } - } - - private String propertyToJson(Map.Entry<String, PropertyDefinition> property) { - JSONObject root = new JSONObject(); - String propertyName = property.getKey(); - PropertyDefinition propertyDefinition = property.getValue(); - JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition); - root.put(propertyName, propertyDefinitionO); - propertyDefinition.getType(); - return root.toString(); - } - - private JSONObject getPropertyDefinitionJSONObject(PropertyDefinition propertyDefinition) { - - Either<String, ActionStatus> either = convertObjectToJson(propertyDefinition); - if (either.isRight()) { - return new JSONObject(); - } - String value = either.left().value(); - try { - return (JSONObject) new JSONParser().parse(value); - } catch (ParseException e) { - log.info("failed to convert input to json"); - log.debug("failed to convert to json", e); - return new JSONObject(); - } - - } - - private <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) { - T t = null; - Type constraintType = new TypeToken<PropertyConstraint>() { - }.getType(); - Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create(); - try { - log.trace("convert json to object. json=\n {}", data); - t = gson.fromJson(data, clazz); - if (t == null) { - log.info("object is null after converting from json"); - return Either.right(ActionStatus.INVALID_CONTENT); - } - } catch (Exception e) { - // INVALID JSON - log.info("failed to convert from json"); - log.debug("failed to convert from json", e); - return Either.right(ActionStatus.INVALID_CONTENT); - } - return Either.left(t); - } - - private <T> Either<String, ActionStatus> convertObjectToJson(PropertyDefinition propertyDefinition) { - Type constraintType = new TypeToken<PropertyConstraint>() { - }.getType(); - Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintSerialiser()).create(); - try { - log.trace("convert object to json. propertyDefinition= {}", propertyDefinition); - String json = gson.toJson(propertyDefinition); - if (json == null) { - log.info("object is null after converting to json"); - return Either.right(ActionStatus.INVALID_CONTENT); - } - return Either.left(json); - } catch (Exception e) { - // INVALID JSON - log.info("failed to convert to json"); - log.debug("failed to convert fto json", e); - return Either.right(ActionStatus.INVALID_CONTENT); - } - - } - - private PropertyBusinessLogic getPropertyBL(ServletContext context) { - WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); - WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); - return webApplicationContext.getBean(PropertyBusinessLogic.class); - } - -} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java index ddb405779d..00b04a4ffc 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java @@ -105,12 +105,6 @@ public class TypesFetchServlet extends AbstractValidationsServlet { } } - private PropertyBusinessLogic getPropertyBL(ServletContext context) { - WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); - WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); - return webApplicationContext.getBean(PropertyBusinessLogic.class); - } - @GET @Path("interfaceLifecycleTypes") @Consumes(MediaType.APPLICATION_JSON) diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java index 6a06c943a0..04119fed7b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java @@ -488,7 +488,7 @@ public class CapabilityRequirementConverter { if (isNotEmpty(properties)) { Map<String, ToscaProperty> toscaProperties = new HashMap<>(); for (PropertyDefinition property : properties) { - ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true); + ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY); toscaProperties.put(property.getName(), toscaProperty); } toscaCapability.setProperties(toscaProperties); @@ -520,7 +520,7 @@ public class CapabilityRequirementConverter { if (isNotEmpty(properties)) { Map<String, ToscaProperty> toscaProperties = new HashMap<>(); for (PropertyDefinition property : properties) { - ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true); + ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY); toscaProperties.put(property.getName(), toscaProperty); } toscaCapability.setProperties(toscaProperties); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java index d128d5349f..04c7c69daa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java @@ -20,11 +20,13 @@ package org.openecomp.sdc.be.tosca; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.gson.stream.JsonReader; -import fj.data.Either; +import java.io.StringReader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Supplier; + import org.apache.commons.lang3.StringUtils; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; @@ -35,6 +37,7 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.DataTypePropertyConverter; import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter; +import org.openecomp.sdc.be.model.tosca.converters.ToscaStringConvertor; import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter; import org.openecomp.sdc.be.model.tosca.converters.ToscaValueConverter; import org.openecomp.sdc.be.tosca.model.EntrySchema; @@ -42,18 +45,24 @@ import org.openecomp.sdc.be.tosca.model.ToscaNodeType; import org.openecomp.sdc.be.tosca.model.ToscaProperty; import org.openecomp.sdc.common.log.wrappers.Logger; -import java.io.StringReader; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; + +import fj.data.Either; public class PropertyConvertor { private static PropertyConvertor instance; private JsonParser jsonParser = new JsonParser(); private static final Logger log = Logger.getLogger(PropertyConvertor.class); + public enum PropertyType { + CAPABILITY, + INPUT, + PROPERTY + } Gson gson = new Gson(); - protected PropertyConvertor() { + public PropertyConvertor() { } @@ -74,7 +83,7 @@ public class PropertyConvertor { // take only the properties of this resource props.stream().filter(p -> p.getOwnerId() == null || p.getOwnerId().equals(component.getUniqueId())).forEach(property -> { - properties.put(property.getName(), convertProperty(dataTypes, property, false)); + properties.put(property.getName(), convertProperty(dataTypes, property, PropertyType.PROPERTY)); }); if (!properties.isEmpty()) { toscaNodeType.setProperties(properties); @@ -84,7 +93,7 @@ public class PropertyConvertor { return Either.left(toscaNodeType); } - public ToscaProperty convertProperty(Map<String, DataTypeDefinition> dataTypes, PropertyDataDefinition property, boolean isCapabiltyProperty) { + public ToscaProperty convertProperty(Map<String, DataTypeDefinition> dataTypes, PropertyDefinition property, PropertyType propertyType) { ToscaProperty prop = new ToscaProperty(); String innerType = null; @@ -96,22 +105,35 @@ public class PropertyConvertor { eschema.setDescription(schema.getProperty().getDescription()); prop.setEntry_schema(eschema); } - return getToscaProperty(dataTypes, property, isCapabiltyProperty, prop, innerType); + return getToscaProperty(dataTypes, property, prop, innerType, propertyType); } - private ToscaProperty getToscaProperty(Map<String, DataTypeDefinition> dataTypes, PropertyDataDefinition property, boolean isCapabiltyProperty, ToscaProperty prop, String innerType) { + private ToscaProperty getToscaProperty(Map<String, DataTypeDefinition> dataTypes, + PropertyDataDefinition property, + ToscaProperty prop, + String innerType, + PropertyType propertyType) { log.trace("try to convert property {} from type {} with default value [{}]", property.getName(), property.getType(), property.getDefaultValue()); - Object convertedObj = convertToToscaObject(property.getType(), property.getDefaultValue(), innerType, dataTypes, false); + String defaultValue = property.getDefaultValue(); + if(Objects.isNull(defaultValue)) { + defaultValue = property.getValue(); + } + Object convertedObj = + convertToToscaObject(property.getType(), defaultValue, innerType, dataTypes, false); if (convertedObj != null) { prop.setDefaultp(convertedObj); } prop.setType(property.getType()); prop.setDescription(property.getDescription()); - if (isCapabiltyProperty) { - prop.setStatus(property.getStatus()); - } prop.setRequired(property.isRequired()); + switch (propertyType) { + case CAPABILITY: + prop.setStatus(property.getStatus()); + break; + default: + break; + } return prop; } @@ -198,9 +220,9 @@ public class PropertyConvertor { } private boolean valueStartsWithNonJsonChar(String value) { - return value.startsWith("/") || value.startsWith(":") || value.startsWith("#"); + return value.startsWith("/") || value.startsWith(":"); } - + public void convertAndAddValue(Map<String, DataTypeDefinition> dataTypes, Map<String, Object> props, PropertyDataDefinition prop, Supplier<String> supplier) { Object convertedValue = convertValue(dataTypes, prop, supplier); 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 d0286d72d9..ecead12478 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 @@ -20,10 +20,11 @@ package org.openecomp.sdc.be.tosca; -import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement; -import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement; - +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutableTriple; @@ -32,48 +33,24 @@ import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundExcept import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.CapabilityDefinition; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.ComponentParametersView; -import org.openecomp.sdc.be.model.DataTypeDefinition; -import org.openecomp.sdc.be.model.GroupInstance; -import org.openecomp.sdc.be.model.InputDefinition; -import org.openecomp.sdc.be.model.InterfaceDefinition; -import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.RelationshipInfo; -import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.RequirementDefinition; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; -import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; -import org.openecomp.sdc.be.tosca.model.SubstitutionMapping; -import org.openecomp.sdc.be.tosca.model.ToscaCapability; -import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate; -import org.openecomp.sdc.be.tosca.model.ToscaMetadata; -import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate; -import org.openecomp.sdc.be.tosca.model.ToscaNodeType; -import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate; -import org.openecomp.sdc.be.tosca.model.ToscaProperty; -import org.openecomp.sdc.be.tosca.model.ToscaTemplate; -import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement; -import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate; +import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter; +import org.openecomp.sdc.be.tosca.model.*; import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil; import org.openecomp.sdc.be.tosca.utils.InputConverter; +import org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil; import org.openecomp.sdc.common.log.wrappers.Logger; -import org.openecomp.sdc.exception.ResponseFormat; +import org.openecomp.sdc.externalupload.utils.ServiceUtils; import org.springframework.beans.factory.annotation.Autowired; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions.FlowStyle; @@ -89,15 +66,8 @@ import org.yaml.snakeyaml.representer.Represent; import org.yaml.snakeyaml.representer.Representer; import java.beans.IntrospectionException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -105,6 +75,8 @@ import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.apache.commons.collections.MapUtils.isNotEmpty; import static org.apache.commons.lang.StringUtils.isNotEmpty; +import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement; +import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement; @org.springframework.stereotype.Component("tosca-export-handler") public class ToscaExportHandler { @@ -145,6 +117,8 @@ public class ToscaExportHandler { private static final List<Map<String, Map<String, String>>> DEFAULT_IMPORTS = ConfigurationManager .getConfigurationManager().getConfiguration().getDefaultImports(); + public ToscaExportHandler(){} + public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) { Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertToToscaTemplate(component); @@ -274,12 +248,16 @@ public class ToscaExportHandler { } List<ComponentInstance> componentInstances = component.getComponentInstances(); - Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component - .getComponentInstancesProperties(); + Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = + component.getComponentInstancesProperties(); + Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = + component.getComponentInstancesInterfaces(); if (componentInstances != null && !componentInstances.isEmpty()) { - Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates = convertNodeTemplates(component, - componentInstances, componentInstancesProperties, componentCache, dataTypes, topologyTemplate); + Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates = + convertNodeTemplates(component, componentInstances, + componentInstancesProperties, componentInstanceInterfaces, + componentCache, dataTypes, topologyTemplate); if (nodeTemplates.isRight()) { return Either.right(nodeTemplates.right().value()); } @@ -335,7 +313,27 @@ public class ToscaExportHandler { return Either.left(toscaNode); } - private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) { + private Either<ToscaTopolgyTemplate, ToscaError> fillInputs(Component component, + ToscaTopolgyTemplate topologyTemplate, Map<String, DataTypeDefinition> dataTypes) { + if (log.isDebugEnabled()) { + log.debug("fillInputs for component {}", component.getUniqueId()); + } + List<InputDefinition> inputDef = component.getInputs(); + Map<String, ToscaProperty> inputs = new HashMap<>(); + + if (inputDef != null) { + inputDef.forEach(i -> { + ToscaProperty property = propertyConvertor.convertProperty(dataTypes, i, PropertyConvertor.PropertyType.INPUT); + inputs.put(i.getName(), property); + }); + if (!inputs.isEmpty()) { + topologyTemplate.setInputs(inputs); + } + } + return Either.left(topologyTemplate); + } + + private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) { Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component); @@ -436,8 +434,6 @@ public class ToscaExportHandler { Map<String, Component> componentCache = new HashMap<>(); if (!ModelConverter.isAtomicComponent(component)) { - List<ComponentInstance> componentInstances = component.getComponentInstances(); - List<Map<String, Map<String, String>>> additionalImports = toscaTemplate.getImports() == null ? new ArrayList<>(DEFAULT_IMPORTS) : new ArrayList<>(toscaTemplate.getImports()); @@ -457,6 +453,7 @@ public class ToscaExportHandler { additionalImports.add(importsListMember); } } + List<ComponentInstance> componentInstances = component.getComponentInstances(); if (componentInstances != null && !componentInstances.isEmpty()) { componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci)); } @@ -582,20 +579,35 @@ public class ToscaExportHandler { Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value(); List<InputDefinition> inputDef = component.getInputs(); - Map<String, ToscaProperty> inputs = new HashMap<>(); - addInterfaceDefinitionElement(component, toscaNodeType, isAssociatedResourceComponent); + Map<String, ToscaProperty> mergedProperties = new HashMap<>(); + addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedResourceComponent); if (inputDef != null) { - inputDef.forEach(i -> { - ToscaProperty property = propertyConvertor.convertProperty(dataTypes, i, false); - inputs.put(i.getName(), property); - }); - if (!inputs.isEmpty()) { - toscaNodeType.setProperties(inputs); - } + addInputsToProperties(dataTypes, inputDef, mergedProperties); + } + + if(CollectionUtils.isNotEmpty(component.getProperties())) { + List<PropertyDefinition> properties = component.getProperties(); + mergedProperties = properties.stream().collect(Collectors.toMap( + PropertyDataDefinition::getName, + property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))); } + if (!mergedProperties.isEmpty()) { + toscaNodeType.setProperties(mergedProperties); + } + // Extracted to method for code reuse return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes); } + private void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes, + List<InputDefinition> inputDef, + Map<String, ToscaProperty> mergedProperties) { + for(InputDefinition input : inputDef) { + ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT); + mergedProperties.put(input.getName(), property); + } + } + + private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode, Map<String, ToscaNodeType> nodeTypes, ToscaNodeType toscaNodeType, Map<String, DataTypeDefinition> dataTypes) { @@ -635,9 +647,11 @@ public class ToscaExportHandler { return Either.left(toscaNode); } - private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(Component component, + protected Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates( + Component component, List<ComponentInstance> componentInstances, Map<String, List<ComponentInstanceProperty>> componentInstancesProperties, + Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces, Map<String, Component> componentCache, Map<String, DataTypeDefinition> dataTypes, ToscaTopolgyTemplate topologyTemplate) { @@ -704,7 +718,11 @@ public class ToscaExportHandler { addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props); } - if (!props.isEmpty()) { + //M3[00001] - NODE TEMPLATE INTERFACES - START + handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, + instanceUniqueId, component); + //M3[00001] - NODE TEMPLATE INTERFACES - END + if (props != null && !props.isEmpty()) { nodeTemplate.setProperties(props); } @@ -749,6 +767,70 @@ public class ToscaExportHandler { return convertNodeTemplatesRes; } + private void handleInstanceInterfaces( + Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces, + ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate, + String instanceUniqueId, + Component parentComponent) { + + Map<String, Object> interfaces; + + // we need to handle service proxy interfaces + if(isComponentOfTypeServiceProxy(componentInstance)) { + if(MapUtils.isEmpty(componentInstanceInterfaces) + || !componentInstanceInterfaces.containsKey(instanceUniqueId)) { + interfaces = null; + } else { + List<ComponentInstanceInterface> currServiceInterfaces = + componentInstanceInterfaces.get(instanceUniqueId); + + Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>(); + currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface + .getUniqueId(), instInterface)); + + interfaces = InterfacesOperationsToscaUtil + .getInterfacesMap(parentComponent, tmpInterfaces, dataTypes, true, true); + } + } else { + interfaces = + getComponentInstanceInterfaceInstances(componentInstanceInterfaces, + componentInstance, instanceUniqueId); + } + nodeTemplate.setInterfaces(interfaces); + } + + private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) { + return Objects.nonNull(componentInstance.getOriginType()) + && componentInstance.getOriginType().getValue().equals("Service Proxy"); + } + + //M3[00001] - NODE TEMPLATE INTERFACES - START + private Map<String, Object> getComponentInstanceInterfaceInstances(Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces, + ComponentInstance componentInstance, + String instanceUniqueId) { + if(MapUtils.isEmpty(componentInstancesInterfaces)) { + return null; + } + + List<ComponentInstanceInterface> componentInstanceInterfaces = + componentInstancesInterfaces.get(instanceUniqueId); + + if(CollectionUtils.isEmpty(componentInstanceInterfaces)) { + return null; + } + + Map<String, Object> interfaces = new HashMap<>(); + for(ComponentInstanceInterface componentInstanceInterface : componentInstanceInterfaces) { + interfaces.put(componentInstanceInterface.getInterfaceId(), + removeOperationsKeyFromInterface(componentInstanceInterface.getInterfaceInstanceDataDefinition())); + } + + componentInstance.setInterfaces(interfaces); + + return interfaces; + } + //M3[00001] - NODE TEMPLATE INTERFACES - END + private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes, Map<String, List<ComponentInstanceInput>> componentInstancesInputs, String instanceUniqueId, Map<String, Object> props) { @@ -791,6 +873,34 @@ public class ToscaExportHandler { } } + /** + * @param dataTypes + * @param componentInstance + * @param props + * @param prop + * @param supplier + */ + private void convertAndAddValue(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, + Map<String, Object> props, PropertyDefinition prop, Supplier<String> supplier) { + Object convertedValue = convertValue(dataTypes, componentInstance, prop, supplier); + if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue)) { + props.put(prop.getName(), convertedValue); + } + } + + private <T extends PropertyDefinition> Object convertValue(Map<String, DataTypeDefinition> dataTypes, + ComponentInstance componentInstance, T input, Supplier<String> supplier) { + log.debug("Convert property or input value {} for instance {}", input.getName(), + componentInstance.getUniqueId()); + String propertyType = input.getType(); + String innerType = null; + if (input.getSchema() != null && input.getSchema().getProperty() != null) { + innerType = input.getSchema().getProperty().getType(); + } + return propertyConvertor.convertToToscaObject(propertyType, supplier.get(), innerType, + dataTypes, true); + } + private ToscaNodeType createNodeType(Component component) { ToscaNodeType toscaNodeType = new ToscaNodeType(); if (ModelConverter.isAtomicComponent(component)) { @@ -1128,5 +1238,22 @@ public class ToscaExportHandler { } } + private Object removeOperationsKeyFromInterface(Object interfaceInstanceDataDefinition) { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); + + Map<String, Object> interfaceAsMap = ServiceUtils.getObjectAsMap(interfaceInstanceDataDefinition); + Map<String, Object> operations = (Map<String, Object>) interfaceAsMap.remove("operations"); + interfaceAsMap.remove("empty"); + + if(MapUtils.isNotEmpty(operations)) { + interfaceAsMap.putAll(operations); + } + + Object interfaceObject = objectMapper.convertValue(interfaceAsMap, Object.class); + + return interfaceObject; + + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java index c27944e8ee..b67a2cf233 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java @@ -20,6 +20,9 @@ package org.openecomp.sdc.be.tosca.model; +import org.apache.commons.collections.MapUtils; + +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,6 +33,7 @@ public class ToscaNodeTemplate { private Map<String, Object> properties; private List<Map<String, ToscaTemplateRequirement>> requirements; private Map<String, ToscaTemplateCapability> capabilities; + private Map<String, Object> interfaces; public String getType() { return type; @@ -78,4 +82,17 @@ public class ToscaNodeTemplate { public void setDescription(String description) { this.description = description; } + + public void setInterfaces( + Map<String, Object> interfaces) { + this.interfaces = interfaces; + } + + public void addInterface(String interfaceName, Object interfaceDataDefinition) { + if (MapUtils.isEmpty(this.interfaces)) { + this.interfaces = new HashMap<>(); + } + + this.interfaces.put(interfaceName, interfaceDataDefinition); + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InputConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InputConverter.java index f6619b9aaa..c7e4d9b635 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InputConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InputConverter.java @@ -42,7 +42,8 @@ public class InputConverter { if (inputDef != null) { inputDef.forEach(i -> { //Extract input the same as property - ToscaProperty toscaProperty = propertyConvertor.convertProperty(dataTypes, i, false); + ToscaProperty toscaProperty = propertyConvertor.convertProperty(dataTypes, i, + PropertyConvertor.PropertyType.INPUT); //now that we have Tosca property we create new object called tosca input which drives from it ToscaInput toscaInput = new ToscaInput(toscaProperty); List<Annotation> annotations = i.getAnnotations(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java index 106aa58133..a72f57d61c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java @@ -30,6 +30,7 @@ import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.Product; import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition; @@ -103,6 +104,7 @@ public class InterfacesOperationsToscaUtil { * @param nodeType to which the interfaces element will be added */ public static void addInterfaceDefinitionElement(Component component, ToscaNodeType nodeType, + Map<String, DataTypeDefinition> dataTypes, boolean isAssociatedResourceComponent) { if (component instanceof Product) { return; @@ -111,6 +113,28 @@ public class InterfacesOperationsToscaUtil { if (MapUtils.isEmpty(interfaces)) { return; } + Map<String, Object> toscaInterfaceDefinitions = getInterfacesMap(component, dataTypes, + isAssociatedResourceComponent); + if (MapUtils.isNotEmpty(toscaInterfaceDefinitions)) { + nodeType.setInterfaces(toscaInterfaceDefinitions); + } + } + + private static Map<String, Object> getInterfacesMap(Component component, + Map<String, DataTypeDefinition> dataTypes, + boolean isAssociatedResourceComponent) { + return getInterfacesMap(component, component.getInterfaces(), dataTypes, isAssociatedResourceComponent, false); + } + + public static Map<String, Object> getInterfacesMap(Component component, + Map<String, InterfaceDefinition> interfaces, + Map<String, DataTypeDefinition> dataTypes, + boolean isAssociatedResourceComponent, + boolean isServiceProxyInterface) { + if(MapUtils.isEmpty(interfaces)) { + return null; + } + Map<String, Object> toscaInterfaceDefinitions = new HashMap<>(); for (InterfaceDefinition interfaceDefinition : interfaces.values()) { ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition(); @@ -137,13 +161,46 @@ public class InterfacesOperationsToscaUtil { toscaInterfaceDefinition.setOperations(toscaOperations); Map<String, Object> interfaceDefAsMap = getObjectAsMap(toscaInterfaceDefinition); Map<String, Object> operationsMap = (Map<String, Object>) interfaceDefAsMap.remove(OPERATIONS_KEY); - handleDefaults(operationsMap); + if (isServiceProxyInterface) { + handleServiceProxyOperationInputValue(operationsMap, interfaceType); + } else { + handleDefaults(operationsMap); + } interfaceDefAsMap.putAll(operationsMap); toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefAsMap); } - if (MapUtils.isNotEmpty(toscaInterfaceDefinitions)) { - nodeType.setInterfaces(toscaInterfaceDefinitions); + + return toscaInterfaceDefinitions; + } + + private static void handleServiceProxyOperationInputValue(Map<String, Object> operationsMap, String parentKey) { + for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) { + final Object value = operationEntry.getValue(); + final String key = operationEntry.getKey(); + if (value instanceof Map) { + if ("inputs".equals(parentKey)) { + Object defaultValue = getDefaultValue((Map<String, Object>) value); + operationsMap.put(key, defaultValue); + } else { + handleServiceProxyOperationInputValue((Map<String, Object>) value, key); + } + } + } + } + + private static Object getDefaultValue(Map<String, Object> inputValueMap) { + Object defaultValue = null; + for (Map.Entry<String, Object> operationEntry : inputValueMap.entrySet()) { + final Object value = operationEntry.getValue(); + if (value instanceof Map) { + getDefaultValue((Map<String, Object>) value); + } + final String key = operationEntry.getKey(); + if (key.equals(DEFAULTP)) { + defaultValue = inputValueMap.remove(key); + } } + return defaultValue; } /* diff --git a/catalog-be/src/main/java/org/openecomp/sdc/externalupload/utils/ServiceUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/externalupload/utils/ServiceUtils.java new file mode 100644 index 0000000000..ba6f9c233c --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/externalupload/utils/ServiceUtils.java @@ -0,0 +1,89 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.externalupload.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.beanutils.BeanUtils; + +import java.lang.reflect.Field; +import java.util.*; + +public class ServiceUtils { + private static final char[] CHARS = new char[]{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + private static final String TYPE = "type"; + private static final String NODE = "node"; + + public static <T> Optional<T> createObjectUsingSetters(Object objectCandidate, + Class<T> classToCreate) + throws Exception { + if (Objects.isNull(objectCandidate)) { + return Optional.empty(); + } + + Map<String, Object> objectAsMap = getObjectAsMap(objectCandidate); + T result = classToCreate.newInstance(); + + List<Field> declaredFields = getAllFields(classToCreate); + for( Field field : declaredFields){ + if(isComplexClass(field)){ + Optional<?> objectUsingSetters = + createObjectUsingSetters(objectAsMap.get(field.getName()), field.getType()); + if( objectUsingSetters.isPresent()){ + objectAsMap.remove(field.getName()); + objectAsMap.put(field.getName(), objectUsingSetters.get()); + } + } + } + BeanUtils.populate(result, objectAsMap); + + return Optional.of(result); + } + + private static <T> List<Field> getAllFields(Class<T> clazz) { + List<Field> fields = new ArrayList<>(); + for(Class<?> c = clazz; c != null; c = c.getSuperclass()) { + fields.addAll(Arrays.asList(c.getDeclaredFields())); + } + + return fields; + } + + private static boolean isComplexClass(Field field) { + return !field.getType().equals(Map.class) + && !field.getType().equals(String.class) + && !field.getType().equals(Integer.class) + && !field.getType().equals(Float.class) + && !field.getType().equals(Double.class) + && !field.getType().equals(Set.class) + && !field.getType().equals(Object.class) + && !field.getType().equals(List.class); + } + public static Map<String, Object> getObjectAsMap(Object obj) { + return new ObjectMapper().convertValue(obj, Map.class); + } + + public static Set<String> getClassFieldNames(Class<? extends Object> classType) { + Set<String> fieldNames = new HashSet<>(); + List<Field> allFields = getAllFields(classType); + allFields.forEach(field -> fieldNames.add(field.getName())); + + return fieldNames; + } +}
\ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/PropertyBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/PropertyBusinessLogicTest.java index f55f461ce9..4f2bb78079 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/PropertyBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/PropertyBusinessLogicTest.java @@ -23,19 +23,15 @@ package org.openecomp.sdc.be.components; import fj.data.Either; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.mockito.junit.MockitoJUnitRunner; -import org.openecomp.sdc.be.components.impl.BaseBusinessLogic; import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; import org.openecomp.sdc.be.components.validation.UserValidations; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; -import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.*; @@ -50,27 +46,18 @@ import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.impl.ExternalConfiguration; import org.openecomp.sdc.common.impl.FSConfigurationSource; import org.openecomp.sdc.exception.ResponseFormat; +import org.openecomp.sdc.test.utils.InterfaceOperationTestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.WebApplicationContext; + import javax.servlet.ServletContext; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.runner.Request.method; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import java.util.*; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; public class PropertyBusinessLogicTest { @@ -89,20 +76,22 @@ public class PropertyBusinessLogicTest { private ComponentsUtils componentsUtils; @Mock private ToscaOperationFacade toscaOperationFacade; - @Mock private UserValidations userValidations; - @Mock IGraphLockOperation graphLockOperation; + @Mock + TitanDao titanDao; @InjectMocks private PropertyBusinessLogic bl = new PropertyBusinessLogic(); private User user = null; private String resourceId = "resourceforproperty.0.1"; - - @Mock - TitanDao titanDao; + private String serviceId = "serviceForProperty.0.1"; + private static final String interfaceType = "interfaceType"; + private static final String operationType = "operationType"; + private static final String operationId = "operationId"; + private static final String operationId2 = "operationId2"; @Before public void setup() { @@ -144,7 +133,7 @@ public class PropertyBusinessLogicTest { resource.setUniqueId(resourceId); Mockito.when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource)); - Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> nonExistingProperty = bl.getProperty(resourceId, "NonExistingProperty", user.getUserId()); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> nonExistingProperty = bl.getComponentProperty(resourceId, "NonExistingProperty", user.getUserId()); assertTrue(nonExistingProperty.isRight()); Mockito.verify(componentsUtils).getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, ""); } @@ -158,7 +147,7 @@ public class PropertyBusinessLogicTest { resource.setUniqueId(resourceId); Mockito.when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource)); - Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> notFoundProperty = bl.getProperty(resourceId, "invalidId", user.getUserId()); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> notFoundProperty = bl.getComponentProperty(resourceId, "invalidId", user.getUserId()); assertTrue(notFoundProperty.isRight()); Mockito.verify(componentsUtils).getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, ""); } @@ -171,11 +160,105 @@ public class PropertyBusinessLogicTest { resource.setProperties(Arrays.asList(property1)); Mockito.when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource)); - Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> foundProperty = bl.getProperty(resourceId, property1.getUniqueId(), user.getUserId()); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> foundProperty = bl.getComponentProperty(resourceId, property1.getUniqueId(), user.getUserId()); assertTrue(foundProperty.isLeft()); assertEquals(foundProperty.left().value().getValue().getUniqueId(), property1.getUniqueId()); } + @Test + public void testGetPropertyFromService() { + Service service = new Service(); + service.setUniqueId(serviceId); + + PropertyDefinition property1 = createPropertyObject("someProperty", null); + service.setProperties(Arrays.asList(property1)); + + Mockito.when(toscaOperationFacade.getToscaElement(serviceId)).thenReturn(Either.left(service)); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> serviceProperty = + bl.getComponentProperty(serviceId, property1.getUniqueId(), user.getUserId()); + + assertTrue(serviceProperty.isLeft()); + assertEquals(serviceProperty.left().value().getValue().getUniqueId(), property1.getUniqueId()); + } + + @Test + public void testPropertyNotFoundOnService() { + Service service = new Service(); + service.setUniqueId(serviceId); + + PropertyDefinition property1 = createPropertyObject("someProperty", null); + service.setProperties(Arrays.asList(property1)); + + Mockito.when(toscaOperationFacade.getToscaElement(serviceId)).thenReturn(Either.left(service)); + Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> serviceProperty = + bl.getComponentProperty(serviceId, "notExistingPropId", user.getUserId()); + + assertTrue(serviceProperty.isRight()); + } + + @Test + public void isPropertyUsedByComponentInterface(){ + Service service = new Service(); + service.setUniqueId(serviceId); + service.setInterfaces(InterfaceOperationTestUtils.createMockInterfaceDefinitionMap(interfaceType, operationId, operationType)); + + PropertyDefinition propDef1 = new PropertyDefinition(); + propDef1.setUniqueId("ComponentInput1_uniqueId"); + assertTrue(bl.isPropertyUsedByOperation(service, propDef1)); + + PropertyDefinition propDef2 = new PropertyDefinition(); + propDef1.setUniqueId("inputId2"); + Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(new ArrayList<>())); + assertFalse(bl.isPropertyUsedByOperation(service, propDef2)); + } + + @Test + public void isPropertyUsedByComponentInstanceInterface(){ + Map<String, InterfaceDefinition> newInterfaceDefinition = InterfaceOperationTestUtils.createMockInterfaceDefinitionMap(interfaceType, operationId, operationType); + ComponentInstanceInterface componentInstanceInterface = new ComponentInstanceInterface(interfaceType, newInterfaceDefinition.get(interfaceType)); + + Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = new HashMap<>(); + componentInstanceInterfaces.put("Test", Arrays.asList(componentInstanceInterface)); + + Service service = new Service(); + service.setUniqueId(serviceId); + service.setComponentInstancesInterfaces(componentInstanceInterfaces); + + PropertyDefinition propDef1 = new PropertyDefinition(); + propDef1.setUniqueId("ComponentInput1_uniqueId"); + assertTrue(bl.isPropertyUsedByOperation(service, propDef1)); + + PropertyDefinition propDef2 = new PropertyDefinition(); + propDef1.setUniqueId("inputId2"); + Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(new ArrayList<>())); + assertFalse(bl.isPropertyUsedByOperation(service, propDef2)); + } + + @Test + public void isPropertyUsedByComponentParentComponentInstanceInterface(){ + Map<String, InterfaceDefinition> newInterfaceDefinition = InterfaceOperationTestUtils.createMockInterfaceDefinitionMap(interfaceType, operationId, operationType); + ComponentInstanceInterface componentInstanceInterface = new ComponentInstanceInterface(interfaceType, newInterfaceDefinition.get(interfaceType)); + + Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = new HashMap<>(); + componentInstanceInterfaces.put("Test", Arrays.asList(componentInstanceInterface)); + + Service parentService = new Service(); + parentService.setComponentInstancesInterfaces(componentInstanceInterfaces); + Service childService = new Service(); + childService.setUniqueId(serviceId); + + PropertyDefinition propDef1 = new PropertyDefinition(); + propDef1.setUniqueId("ComponentInput1_uniqueId"); + Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(Arrays.asList(parentService))); + assertTrue(bl.isPropertyUsedByOperation(childService, propDef1)); + + PropertyDefinition propDef2 = new PropertyDefinition(); + propDef1.setUniqueId("inputId2"); + Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(new ArrayList<>())); + assertFalse(bl.isPropertyUsedByOperation(childService, propDef2)); + } + + private PropertyDefinition createPropertyObject(String propertyName, String resourceId) { PropertyDefinition pd = new PropertyDefinition(); pd.setConstraints(null); @@ -193,7 +276,8 @@ public class PropertyBusinessLogicTest { public void deleteProperty_CONNECTION_FAILURE() { StorageOperationStatus lockResult = StorageOperationStatus.CONNECTION_FAILURE; when(graphLockOperation.lockComponent(any(), any())).thenReturn(lockResult); - assertTrue(bl.deleteProperty("resourceforproperty.0.1", "someProperty","i726").isRight()); + when(toscaOperationFacade.getToscaElement(anyString())).thenReturn(Either.left(new Resource())); + assertTrue(bl.deletePropertyFromComponent("resourceforproperty.0.1", "someProperty","i726").isRight()); } @Test @@ -229,7 +313,7 @@ public class PropertyBusinessLogicTest { when(toscaOperationFacade.getToscaElement("RES01")).thenReturn(toscastatus); - assertTrue(bl.deleteProperty("RES01", "someProperty","i726").isRight()); + assertTrue(bl.deletePropertyFromComponent("RES01", "someProperty","i726").isRight()); } @Test @@ -265,7 +349,7 @@ public class PropertyBusinessLogicTest { when(toscaOperationFacade.getToscaElement("RES01")).thenReturn(toscastatus); - assertTrue(bl.deleteProperty("RES01", "someProperty","i726").isRight()); + assertTrue(bl.deletePropertyFromComponent("RES01", "someProperty","i726").isRight()); } @Test @@ -299,8 +383,9 @@ public class PropertyBusinessLogicTest { Either<Component, StorageOperationStatus> toscastatus=Either.left(resource); when(toscaOperationFacade.getToscaElement("RES01")).thenReturn(toscastatus); - when(toscaOperationFacade.deletePropertyOfResource(anyObject(),anyString())).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.deletePropertyOfComponent(anyObject(),anyString())).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.getParentComponents(anyString())).thenReturn(Either.left(new ArrayList<>())); - assertTrue(bl.deleteProperty("RES01", "PROP","USR01").isRight()); + assertTrue(bl.deletePropertyFromComponent("RES01", "PROP","USR01").isRight()); } } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidationTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidationTest.java index e2d83aef29..fe1e384546 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidationTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidationTest.java @@ -337,7 +337,7 @@ public class InterfaceOperationValidationTest { .validateInterfaceOperations(inputInterfaceDefinition, component, component.getInterfaces().get(interfaceType1), InterfaceOperationTestUtils.createMockInterfaceTypeMap( - interfaceType1, operationType1), false).isRight()); + interfaceType1, operationType1 ), false).isRight()); } @Test diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/PropertyServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/PropertyServletTest.java deleted file mode 100644 index fe147b19a9..0000000000 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/PropertyServletTest.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.openecomp.sdc.be.servlets; - -import java.util.Map; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response; - -import org.codehaus.jettison.json.JSONObject; -import org.junit.Test; -import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; -import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.model.PropertyDefinition; - -import fj.data.Either; - -public class PropertyServletTest { - - private PropertyServlet createTestSubject() { - return new PropertyServlet(); - } - - - @Test - public void testCreateProperty() throws Exception { - PropertyServlet testSubject; - String resourceId = ""; - String data = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetProperty() throws Exception { - PropertyServlet testSubject; - String resourceId = ""; - String propertyId = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testDeleteProperty() throws Exception { - PropertyServlet testSubject; - String resourceId = ""; - String propertyId = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testUpdateProperty() throws Exception { - PropertyServlet testSubject; - String resourceId = ""; - String propertyId = ""; - String data = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetPropertyModel() throws Exception { - PropertyServlet testSubject; - String resourceId = ""; - String data = ""; - Either<Map<String, PropertyDefinition>, ActionStatus> result; - - // default test - testSubject = createTestSubject(); - } - - - - - - @Test - public void testGetPropertyDefinitionJSONObject() throws Exception { - PropertyServlet testSubject; - PropertyDefinition propertyDefinition = null; - JSONObject result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetPropertyBL() throws Exception { - PropertyServlet testSubject; - ServletContext context = null; - PropertyBusinessLogic result; - - // default test - testSubject = createTestSubject(); - } -}
\ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/PropertyConvertorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/PropertyConvertorTest.java index a06ba84b4e..35b8ed0278 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/PropertyConvertorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/PropertyConvertorTest.java @@ -37,12 +37,12 @@ public class PropertyConvertorTest { property.setSchema(schema); - PropertyConvertor.getInstance().convertProperty(dataTypes, property, true); + PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY); } @Test public void convertPropertyWhenValueAndDefaultNull() { - ToscaProperty prop = PropertyConvertor.getInstance().convertProperty(dataTypes, property, false); + ToscaProperty prop = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY); assertNotNull(prop); assertNull(prop.getDefaultp()); } @@ -51,7 +51,7 @@ public class PropertyConvertorTest { public void convertPropertyWhenValueNullAndDefaultNotEmpty() { final String def = "1"; property.setDefaultValue(def); - ToscaProperty result = PropertyConvertor.getInstance().convertProperty(dataTypes, property, false); + ToscaProperty result = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY); assertNotNull(result); assertEquals(Integer.valueOf(def), result.getDefaultp()); } @@ -129,7 +129,7 @@ public class PropertyConvertorTest { .setDefaultValue("::") .setType(ToscaPropertyType.STRING.getType()) .build(); - ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, false); + ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, PropertyConvertor.PropertyType.PROPERTY); assertThat(toscaProperty.getDefaultp()).isEqualTo("::"); } @@ -139,7 +139,7 @@ public class PropertyConvertorTest { .setDefaultValue("/") .setType(ToscaPropertyType.STRING.getType()) .build(); - ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, false); + ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, PropertyConvertor.PropertyType.PROPERTY); assertThat(toscaProperty.getDefaultp()).isEqualTo("/"); } 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 592d27ec5d..a61ea0410a 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 @@ -498,6 +498,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { Component component = getNewService(); List<ComponentInstance> componentInstances = new ArrayList<>(); Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>(); + Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>(); Map<String, Component> componentCache = new HashMap<>(); Map<String, DataTypeDefinition> dataTypes = new HashMap<>(); ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate(); @@ -542,6 +543,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { componentCache.put("uid", component); componentInstancesProperties.put("id", new ArrayList<>()); + componentInstancesInterfaces.put("id", new ArrayList<>()); componentInstancesInputs.put("id", new ArrayList<>()); Mockito.when(capabiltyRequirementConvertor.getOriginComponent(Mockito.any(Map.class), @@ -553,7 +555,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { // default test result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances, - componentInstancesProperties, componentCache, dataTypes, topologyTemplate); + componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate); } @Test @@ -561,6 +563,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { Component component = getNewResource(); List<ComponentInstance> componentInstances = new ArrayList<>(); Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>(); + Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>(); Map<String, Component> componentCache = new HashMap<>(); Map<String, DataTypeDefinition> dataTypes = new HashMap<>(); ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate(); @@ -597,7 +600,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { // default test result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances, - componentInstancesProperties, componentCache, dataTypes, topologyTemplate); + componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate); } @Test @@ -605,6 +608,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { Component component = getNewResource(); List<ComponentInstance> componentInstances = new ArrayList<>(); Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>(); + Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>(); Map<String, Component> componentCache = new HashMap<>(); Map<String, DataTypeDefinition> dataTypes = new HashMap<>(); ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate(); @@ -637,7 +641,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { // default test result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances, - componentInstancesProperties, componentCache, dataTypes, topologyTemplate); + componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate); } @Test @@ -645,6 +649,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { Component component = new Resource(); List<ComponentInstance> componentInstances = new ArrayList<>(); Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>(); + Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>(); Map<String, Component> componentCache = new HashMap<>(); Map<String, DataTypeDefinition> dataTypes = new HashMap<>(); ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate(); @@ -677,7 +682,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { // default test result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances, - componentInstancesProperties, componentCache, dataTypes, topologyTemplate); + componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate); } @Test diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtilTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtilTest.java index 156d280a6e..fc017c8483 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtilTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtilTest.java @@ -122,7 +122,7 @@ public class InterfacesOperationsToscaUtilTest { component.setInterfaces(new HashMap<>()); component.getInterfaces().put(interfaceType, addedInterface); ToscaNodeType nodeType = new ToscaNodeType(); - addInterfaceDefinitionElement(component, nodeType, false); + addInterfaceDefinitionElement(component, nodeType, null, false); ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null); ToscaTemplate template = new ToscaTemplate(NODE_TYPE_NAME); @@ -153,7 +153,7 @@ public class InterfacesOperationsToscaUtilTest { component.setInterfaces(new HashMap<>()); component.getInterfaces().put(interfaceType, addedInterface); ToscaNodeType nodeType = new ToscaNodeType(); - addInterfaceDefinitionElement(component, nodeType, false); + addInterfaceDefinitionElement(component, nodeType, null, false); ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null); ToscaTemplate template = new ToscaTemplate("testService"); @@ -183,7 +183,7 @@ public class InterfacesOperationsToscaUtilTest { component.setInterfaces(new HashMap<>()); component.getInterfaces().put(interfaceType, addedInterface); ToscaNodeType nodeType = new ToscaNodeType(); - addInterfaceDefinitionElement(component, nodeType, false); + addInterfaceDefinitionElement(component, nodeType, null, false); ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null); ToscaTemplate template = new ToscaTemplate("test"); @@ -218,7 +218,7 @@ public class InterfacesOperationsToscaUtilTest { component.setInterfaces(new HashMap<>()); component.getInterfaces().put(addedInterfaceType, addedInterface); ToscaNodeType nodeType = new ToscaNodeType(); - addInterfaceDefinitionElement(component, nodeType, false); + addInterfaceDefinitionElement(component, nodeType, null, false); ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null); ToscaTemplate template = new ToscaTemplate("test"); @@ -266,7 +266,7 @@ public class InterfacesOperationsToscaUtilTest { component.getInterfaces().put(secondInterfaceType, secondInterface); ToscaNodeType nodeType = new ToscaNodeType(); - addInterfaceDefinitionElement(component, nodeType, false); + addInterfaceDefinitionElement(component, nodeType, null,false); ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null); ToscaTemplate template = new ToscaTemplate("test"); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/test/utils/InterfaceOperationTestUtils.java b/catalog-be/src/test/java/org/openecomp/sdc/test/utils/InterfaceOperationTestUtils.java index 1cc5b56ca9..25c0d651c6 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/test/utils/InterfaceOperationTestUtils.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/test/utils/InterfaceOperationTestUtils.java @@ -103,7 +103,7 @@ public class InterfaceOperationTestUtils { } public static Map<String, InterfaceDefinition> createMockInterfaceTypeMap(String interfaceType, - String operationType) { + String operationType) { Map<String, Operation> operationMap = createMockOperationTypeMap(operationType); Map<String, InterfaceDefinition> interfaceDefinitionMap = new HashMap<>(); interfaceDefinitionMap.put(interfaceType, @@ -118,5 +118,4 @@ public class InterfaceOperationTestUtils { operationMap.put(operationType, operation); return operationMap; } - } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index 33515c3d78..6acdb32493 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -122,12 +122,13 @@ public enum ActionStatus { //InterfaceOperation INTERFACE_OPERATION_NOT_FOUND, INTERFACE_OPERATION_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_NAME_MANDATORY, - INTERFACE_OPERATION_NAME_INVALID, INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE, + INTERFACE_OPERATION_NAME_INVALID, INTERFACE_OPERATION_DESCRIPTION_MAX_LENGTH, INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_NOT_DELETED, INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED, INTERFACE_OPERATION_INPUT_NAME_MANDATORY, INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY, INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE, INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE, + PROPERTY_USED_BY_OPERATION, DECLARED_INPUT_USED_BY_OPERATION, //NodeFilter NODE_FILTER_NOT_FOUND, diff --git a/catalog-model/pom.xml b/catalog-model/pom.xml index 91c1d96acc..994b2f7960 100644 --- a/catalog-model/pom.xml +++ b/catalog-model/pom.xml @@ -270,11 +270,21 @@ <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>${commons.collections.version}</version> + </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-handler</artifactId> </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.1</version> + </dependency> </dependencies> <build> diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java index 7c5368887b..24386bc42e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java @@ -25,17 +25,19 @@ import com.google.common.collect.Maps; import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.utils.MapUtil; +import org.openecomp.sdc.be.datatypes.elements.*; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.category.SubCategoryDefinition; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; -import static java.util.Collections.emptyList; -import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType; -import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import java.util.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -45,37 +47,38 @@ import static java.util.stream.Collectors.toMap; import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.collections.MapUtils.isEmpty; -public abstract class Component { - - private ComponentMetadataDefinition componentMetadataDefinition; - private Map<String, ArtifactDefinition> artifacts; - private Map<String, ArtifactDefinition> deploymentArtifacts; - private Map<String, ArtifactDefinition> toscaArtifacts; - private List<CategoryDefinition> categories; - private List<ComponentInstance> componentInstances; - private List<RequirementCapabilityRelDef> componentInstancesRelations; - private Map<String, List<ComponentInstanceInput>> componentInstancesInputs; - private Map<String, List<ComponentInstanceProperty>> componentInstancesProperties; - private Map<String, List<ComponentInstanceProperty>> componentInstancesAttributes; - private Map<String, List<CapabilityDefinition>> capabilities; - private Map<String, List<RequirementDefinition>> requirements; - private List<InputDefinition> inputs; - private List<GroupDefinition> groups; - private Map<String, PolicyDefinition> policies; - private String derivedFromGenericType; - private String derivedFromGenericVersion; - private String toscaType; - protected List<AdditionalInformationDefinition> additionalInformation; - protected List<PropertyDefinition> properties; - private Map<String, InterfaceDefinition> interfaces; - - public Map<String, InterfaceDefinition> getInterfaces() { - return interfaces; - } - - public void setInterfaces(Map<String, InterfaceDefinition> interfaces) { - this.interfaces = interfaces; - } +public abstract class Component implements PropertiesOwner { + + private ComponentMetadataDefinition componentMetadataDefinition; + private Map<String, ArtifactDefinition> artifacts; + private Map<String, ArtifactDefinition> deploymentArtifacts; + private Map<String, ArtifactDefinition> toscaArtifacts; + private List<CategoryDefinition> categories; + private List<ComponentInstance> componentInstances; + private List<RequirementCapabilityRelDef> componentInstancesRelations; + private Map<String, List<ComponentInstanceInput>> componentInstancesInputs; + private Map<String, List<ComponentInstanceProperty>> componentInstancesProperties; + private Map<String, List<ComponentInstanceProperty>> componentInstancesAttributes; + private Map<String, List<CapabilityDefinition>> capabilities; + private Map<String, List<RequirementDefinition>> requirements; + private Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces; + private List<InputDefinition> inputs; + private List<GroupDefinition> groups; + private Map<String, PolicyDefinition> policies; + private String derivedFromGenericType; + private String derivedFromGenericVersion; + private String toscaType; + protected List<AdditionalInformationDefinition> additionalInformation; + protected List<PropertyDefinition> properties; + private Map<String, InterfaceDefinition> interfaces; + + public Map<String, InterfaceDefinition> getInterfaces() { + return interfaces; + } + + public void setInterfaces(Map<String, InterfaceDefinition> interfaces) { + this.interfaces = interfaces; + } public Component(ComponentMetadataDefinition componentMetadataDefinition) { this.componentMetadataDefinition = componentMetadataDefinition; @@ -119,9 +122,10 @@ public abstract class Component { this.toscaArtifacts = toscaArtifacts; } - public String getUniqueId() { - return componentMetadataDefinition.getMetadataDataDefinition().getUniqueId(); - } + @Override + public String getUniqueId() { + return componentMetadataDefinition.getMetadataDataDefinition().getUniqueId(); + } public void setUniqueId(String uniqueId) { componentMetadataDefinition.getMetadataDataDefinition().setUniqueId(uniqueId); @@ -203,9 +207,10 @@ public abstract class Component { this.componentMetadataDefinition.getMetadataDataDefinition().setLastUpdaterFullName(lastUpdaterFullName); } - public String getName() { - return componentMetadataDefinition.getMetadataDataDefinition().getName(); - } + @Override + public String getName() { + return componentMetadataDefinition.getMetadataDataDefinition().getName(); + } public String getVersion() { return componentMetadataDefinition.getMetadataDataDefinition().getVersion(); @@ -317,9 +322,10 @@ public abstract class Component { this.categories = categories; } - public String getNormalizedName() { - return componentMetadataDefinition.getMetadataDataDefinition().getNormalizedName(); - } + @Override + public String getNormalizedName() { + return componentMetadataDefinition.getMetadataDataDefinition().getNormalizedName(); + } public void setNormalizedName(String normalizedName) { componentMetadataDefinition.getMetadataDataDefinition().setNormalizedName(normalizedName); @@ -355,7 +361,7 @@ public abstract class Component { public List<ComponentInstance> getComponentInstances() { return componentInstances; } - + public List<ComponentInstance> safeGetComponentInstances() { if(componentInstances != null) { return componentInstances; @@ -418,10 +424,14 @@ public abstract class Component { return this.safeGetComponentInstanceEntity(comptInstanceId, this.componentInstancesInputs); } - public void setComponentInstancesProperties( - Map<String, List<ComponentInstanceProperty>> resourceInstancesProperties) { - this.componentInstancesProperties = resourceInstancesProperties; - } + public List<ComponentInstanceInterface> safeGetComponentInstanceInterfaces(String cmptInstacneId) { + return this.safeGetComponentInstanceEntity(cmptInstacneId, this.componentInstancesInterfaces); + } + + public void setComponentInstancesProperties( + Map<String, List<ComponentInstanceProperty>> resourceInstancesProperties) { + this.componentInstancesProperties = resourceInstancesProperties; + } public Boolean getIsDeleted() { return componentMetadataDefinition.getMetadataDataDefinition().isDeleted(); @@ -515,58 +525,69 @@ public abstract class Component { .findAny(); } - public void setGroups(List<GroupDefinition> groups) { - this.groups = groups; - } + public Map<String, List<ComponentInstanceInterface>> getComponentInstancesInterfaces() { + return componentInstancesInterfaces; + } - public void addGroups(List<GroupDefinition> groupsToAdd) { - if (groups == null) { - groups = new ArrayList<>(); - } - groups.addAll(groupsToAdd); - } + public void setComponentInstancesInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces) { + this.componentInstancesInterfaces = componentInstancesInterfaces; + } - public Map<String, PolicyDefinition> getPolicies() { - return policies; - } + public void setGroups(List<GroupDefinition> groups) { + this.groups = groups; + } - public void setPolicies(Map<String, PolicyDefinition> policies) { - this.policies = policies; + public void addGroups(List<GroupDefinition> groupsToAdd) { + if (groups == null) { + groups = new ArrayList<>(); } + groups.addAll(groupsToAdd); + } - public List<PropertyDefinition> getProperties() { - return properties; - } + public Map<String, PolicyDefinition> getPolicies() { + return policies; + } - public void setProperties(List<PropertyDefinition> properties) { - this.properties = properties; + public void setPolicies(Map<String, PolicyDefinition> policies) { + this.policies = policies; } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((artifacts == null) ? 0 : artifacts.hashCode()); - result = prime * result + ((categories == null) ? 0 : categories.hashCode()); - result = prime * result + ((componentMetadataDefinition == null) ? 0 : componentMetadataDefinition.hashCode()); - result = prime * result + ((deploymentArtifacts == null) ? 0 : deploymentArtifacts.hashCode()); - result = prime * result + ((capabilities == null) ? 0 : capabilities.hashCode()); - result = prime * result + ((requirements == null) ? 0 : requirements.hashCode()); - result = prime * result + ((componentInstances == null) ? 0 : componentInstances.hashCode()); - result = prime * result - + ((componentInstancesProperties == null) ? 0 : componentInstancesProperties.hashCode()); - result = prime * result - + ((componentInstancesAttributes == null) ? 0 : componentInstancesAttributes.hashCode()); - result = prime * result + ((componentInstancesInputs == null) ? 0 : componentInstancesInputs.hashCode()); - result = prime * result + ((componentInstancesRelations == null) ? 0 : componentInstancesRelations.hashCode()); - result = prime * result + ((groups == null) ? 0 : groups.hashCode()); - result = prime * result + ((policies == null) ? 0 : policies.hashCode()); - result = prime * result + ((derivedFromGenericType == null) ? 0 : derivedFromGenericType.hashCode()); - result = prime * result + ((derivedFromGenericVersion == null) ? 0 : derivedFromGenericVersion.hashCode()); - result = prime * result + ((interfaces == null) ? 0 : interfaces.hashCode()); - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); - return result; - } + public List<PropertyDefinition> getProperties() { + return properties; + } + + public void setProperties(List<PropertyDefinition> properties) { + this.properties = properties; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((artifacts == null) ? 0 : artifacts.hashCode()); + result = prime * result + ((categories == null) ? 0 : categories.hashCode()); + result = prime * result + ((componentMetadataDefinition == null) ? 0 : componentMetadataDefinition.hashCode()); +// result = prime * result + ((creatorUserId == null) ? 0 : creatorUserId.hashCode()); +// result = prime * result + ((creatorFullName == null) ? 0 : creatorFullName.hashCode()); + result = prime * result + ((deploymentArtifacts == null) ? 0 : deploymentArtifacts.hashCode()); +// result = prime * result + ((lastUpdaterUserId == null) ? 0 : lastUpdaterUserId.hashCode()); +// result = prime * result + ((lastUpdaterFullName == null) ? 0 : lastUpdaterFullName.hashCode()); + result = prime * result + ((capabilities == null) ? 0 : capabilities.hashCode()); + result = prime * result + ((requirements == null) ? 0 : requirements.hashCode()); + result = prime * result + ((componentInstances == null) ? 0 : componentInstances.hashCode()); + result = prime * result + + ((componentInstancesProperties == null) ? 0 : componentInstancesProperties.hashCode()); + result = prime * result + + ((componentInstancesAttributes == null) ? 0 : componentInstancesAttributes.hashCode()); + result = prime * result + ((componentInstancesInputs == null) ? 0 : componentInstancesInputs.hashCode()); + result = prime * result + ((componentInstancesRelations == null) ? 0 : componentInstancesRelations.hashCode()); + result = prime * result + ((groups == null) ? 0 : groups.hashCode()); + result = prime * result + ((policies == null) ? 0 : policies.hashCode()); + result = prime * result + ((derivedFromGenericType == null) ? 0 : derivedFromGenericType.hashCode()); + result = prime * result + ((derivedFromGenericVersion == null) ? 0 : derivedFromGenericVersion.hashCode()); + result = prime * result + ((interfaces == null) ? 0 : interfaces.hashCode()); + return result; + } @Override public boolean equals(Object obj) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstInputsMap.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstInputsMap.java index 306992d2fc..9d0877d8f9 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstInputsMap.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstInputsMap.java @@ -31,6 +31,7 @@ public class ComponentInstInputsMap { private Map<String, List<ComponentInstancePropInput>> componentInstanceInputsMap; private Map<String, List<ComponentInstancePropInput>> componentInstanceProperties; + private Map<String, List<ComponentInstancePropInput>> serviceProperties; private Map<String, List<ComponentInstancePropInput>> policyProperties; private Map<String, List<ComponentInstancePropInput>> groupProperties; @@ -44,6 +45,9 @@ public class ComponentInstInputsMap { if (isNotEmpty(policyProperties)) { return singleMapEntry(policyProperties); } + if(isNotEmpty(serviceProperties)) { + return singleMapEntry(serviceProperties); + } if (isNotEmpty(groupProperties)) { return singleMapEntry(groupProperties); } @@ -79,6 +83,15 @@ public class ComponentInstInputsMap { this.policyProperties = policyProperties; } + public Map<String, List<ComponentInstancePropInput>> getServiceProperties() { + return serviceProperties; + } + + public void setServiceProperties( + Map<String, List<ComponentInstancePropInput>> serviceProperties) { + this.serviceProperties = serviceProperties; + } + public Map<String, List<ComponentInstancePropInput>> getGroupProperties() { return groupProperties; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java index ef9b409735..0d18676acc 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java @@ -20,12 +20,14 @@ package org.openecomp.sdc.be.model; +import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertiesOwner; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -36,6 +38,8 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement private Map<String, ArtifactDefinition> deploymentArtifacts; private Map<String, ArtifactDefinition> artifacts; private List<GroupInstance> groupInstances; + private Map<String, Object> interfaces; + private List<PropertyDefinition> properties; private CINodeFilterDataDefinition nodeFilter; public ComponentInstance() { @@ -109,6 +113,30 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement return safeGetInformationalArtifacts().get(artifactLabel) != null; } + public Map<String, Object> getInterfaces() { + return interfaces; + } + + public void setInterfaces(Map<String, Object> interfaces) { + this.interfaces = interfaces; + } + + public void addInterface(String interfaceName, Object interfaceDefinition) { + if(MapUtils.isEmpty(this.interfaces)) { + this.interfaces = new HashMap<>(); + } + + this.interfaces.put(interfaceName, interfaceDefinition); + } + + public List<PropertyDefinition> getProperties() { + return properties; + } + + public void setProperties(List<PropertyDefinition> properties) { + this.properties = properties; + } + public CINodeFilterDataDefinition getNodeFilter() { return nodeFilter; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInterface.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInterface.java new file mode 100644 index 0000000000..5482a51d7a --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInterface.java @@ -0,0 +1,53 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.model; + +import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition; + +public class ComponentInstanceInterface extends InterfaceDefinition { + private String interfaceId; + private InterfaceInstanceDataDefinition interfaceInstanceDataDefinition; + + public ComponentInstanceInterface(String interfaceId, + InterfaceInstanceDataDefinition interfaceInstanceDataDefinition) { + this.interfaceId = interfaceId; + this.interfaceInstanceDataDefinition = interfaceInstanceDataDefinition; + } + + public ComponentInstanceInterface(String interfaceId, InterfaceDataDefinition interfaceDataDefinition) { + super(interfaceDataDefinition); + this.interfaceId = interfaceId; + } + + public String getInterfaceId() { + return interfaceId; + } + + public void setInterfaceId(String interfaceId) { + this.interfaceId = interfaceId; + } + + public InterfaceInstanceDataDefinition getInterfaceInstanceDataDefinition() { + return interfaceInstanceDataDefinition; + } + + public void setInterfaceInstanceDataDefinition( + InterfaceInstanceDataDefinition interfaceInstanceDataDefinition) { + this.interfaceInstanceDataDefinition = interfaceInstanceDataDefinition; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/InterfaceInstanceDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/InterfaceInstanceDefinition.java new file mode 100644 index 0000000000..d16370d151 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/InterfaceInstanceDefinition.java @@ -0,0 +1,39 @@ +package org.openecomp.sdc.be.model; + +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationInstance; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class InterfaceInstanceDefinition extends InterfaceInstanceDataDefinition { + + public InterfaceInstanceDefinition(InterfaceInstanceDataDefinition inter) { + super(inter); + } + + public InterfaceInstanceDefinition(){} + + public Map<String, Object> getInputs() { + return this.inputs; + } + + public void setInputs( + Map<String, Object> inputs) { + this.inputs = inputs; + } + + public Map<String, OperationInstance> getOperations() { + return operations; + } + + public void addInstanceOperation(String operationName, OperationInstance operation) { + if(MapUtils.isEmpty(this.operations)) { + this.operations = new HashMap<>(); + } + + this.operations.put(operationName, operation); + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceDataDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceDataDefinition.java new file mode 100644 index 0000000000..c58131f542 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceDataDefinition.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition; + +import java.util.Map; + +public class MapInterfaceDataDefinition extends MapDataDefinition<InterfaceDataDefinition> { + + public MapInterfaceDataDefinition() { + + } + + @JsonCreator + public MapInterfaceDataDefinition(Map<String, InterfaceDataDefinition > mapToscaDataDefinition) { + super(mapToscaDataDefinition); + } + + @JsonValue + @Override + public Map<String, InterfaceDataDefinition> getMapToscaDataDefinition() { + return mapToscaDataDefinition; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceInstanceDataDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceInstanceDataDefinition.java new file mode 100644 index 0000000000..6efa0ed404 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceInstanceDataDefinition.java @@ -0,0 +1,43 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition; + +import java.util.Map; + +public class MapInterfaceInstanceDataDefinition extends + MapDataDefinition<InterfaceInstanceDataDefinition> { + + public MapInterfaceInstanceDataDefinition() { + + } + + @JsonCreator + public MapInterfaceInstanceDataDefinition(Map<String, InterfaceInstanceDataDefinition> mapToscaDataDefinition) { + super(mapToscaDataDefinition); + } + + @JsonValue + @Override + public Map<String, InterfaceInstanceDataDefinition> getMapToscaDataDefinition() { + return mapToscaDataDefinition; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInstance.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInstance.java new file mode 100644 index 0000000000..fb958eb7b6 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInstance.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.model; + +import org.openecomp.sdc.be.datatypes.elements.OperationImplementation; + +import java.util.Map; +import java.util.Objects; + +public class OperationInstance/* extends Operation*/ { + private OperationImplementation implementation; + private Map<String, Object> inputs; + + + public OperationImplementation getImplementation() { + return implementation; + } + + public void setImplementation(OperationImplementation implementation) { + this.implementation = implementation; + } + + public Map<String, Object> getInputs() { + return inputs; + } + + public void setInputs(Map<String, Object> inputs) { + this.inputs = inputs; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof OperationInstance)) { + return false; + } + OperationInstance that = (OperationInstance) o; + return Objects.equals(implementation, that.implementation) && + Objects.equals(inputs, that.inputs); + } + + @Override + public int hashCode() { + + return Objects.hash(implementation, inputs); + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java index f3996ed42b..0603538833 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java @@ -42,12 +42,15 @@ public class Resource extends Component { private List<PropertyDefinition> attributes; - private List<String> defaultCapabilities; - - public Resource() { - super(new ResourceMetadataDefinition()); - this.getComponentMetadataDefinition().getMetadataDataDefinition().setComponentType(ComponentTypeEnum.RESOURCE); - } + private Map<String, InterfaceInstanceDefinition> instInterfaces; + + private List<String> defaultCapabilities; + + public Resource() { + super(new ResourceMetadataDefinition()); + this.getComponentMetadataDefinition().getMetadataDataDefinition() + .setComponentType(ComponentTypeEnum.RESOURCE); + } public Resource(ComponentMetadataDefinition componentMetadataDefinition) { super(componentMetadataDefinition); @@ -101,10 +104,20 @@ public class Resource extends Component { this.attributes = attributes; } - public Boolean isAbstract() { - return ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition()) - .isAbstract(); - } + public Map<String, InterfaceInstanceDefinition> getInstInterfaces() { + return instInterfaces; + } + + public void setInstInterfaces( + Map<String, InterfaceInstanceDefinition> instInterfaces) { + this.instInterfaces = instInterfaces; + } + + public Boolean isAbstract() { + return ((ResourceMetadataDataDefinition) getComponentMetadataDefinition() + .getMetadataDataDefinition()) + .isAbstract(); + } public void setAbstract(Boolean isAbstract) { ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition()) diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java index 823ababcc0..3c1ca26879 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.java @@ -22,6 +22,10 @@ package org.openecomp.sdc.be.model; import org.apache.commons.lang.StringUtils; import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; @@ -51,7 +55,6 @@ public class Service extends Component { private Map<String, ArtifactDefinition> serviceApiArtifacts; private Map<String, ForwardingPathDataDefinition> forwardingPaths; - public Map<String, ArtifactDefinition> getServiceApiArtifacts() { return serviceApiArtifacts; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplate.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplate.java index 0d7b14abd1..ac9f196a92 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplate.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplate.java @@ -25,6 +25,8 @@ import org.openecomp.sdc.be.datatypes.elements.*; import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty; import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.MapInterfaceDataDefinition; +import org.openecomp.sdc.be.model.MapInterfaceInstanceDataDefinition; import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; import java.util.HashMap; @@ -54,6 +56,8 @@ public class TopologyTemplate extends ToscaElement{ private Map<String, MapArtifactDataDefinition> instDeploymentArtifacts; private Map<String, MapArtifactDataDefinition> instanceArtifacts; private Map<String, InterfaceDataDefinition> interfaces; + private Map<String, MapInterfaceInstanceDataDefinition> instInterfaces; + private Map<String, MapInterfaceDataDefinition> componentInstInterfaces; //Component Instances External References (instanceId -> ExternalRefsMap) //----------------------------------------------------------------------- @@ -76,6 +80,43 @@ public class TopologyTemplate extends ToscaElement{ this.interfaces = interfaces; } + public Map<String, MapInterfaceInstanceDataDefinition> getInstInterfaces() { + return instInterfaces; + } + + public void setInstInterfaces( + Map<String, MapInterfaceInstanceDataDefinition> instInterfaces) { + this.instInterfaces = instInterfaces; + } + + public void addInstInterface(String compId, MapInterfaceInstanceDataDefinition + mapInterfaceInstanceDataDefinition) { + if(MapUtils.isEmpty(this.instInterfaces)) { + this.instInterfaces = new HashMap<>(); + } + + this.instInterfaces.put(compId, mapInterfaceInstanceDataDefinition); + } + + public Map<String, MapInterfaceDataDefinition> getComponentInstInterfaces() { + return componentInstInterfaces; + } + + public void setComponentInstInterfaces( + Map<String, MapInterfaceDataDefinition> componentInstInterfaces) { + this.componentInstInterfaces = componentInstInterfaces; + } + + public void addComponentInstanceInterfaceMap(String componentInstanceId, MapInterfaceDataDefinition + mapInterfaceDataDefinition) { + if(MapUtils.isEmpty(this.componentInstInterfaces)) { + this.componentInstInterfaces = new HashMap<>(); + } + + this.componentInstInterfaces.put(componentInstanceId, mapInterfaceDataDefinition); + } + + public Map<String, PropertyDataDefinition> getInputs() { return inputs; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java index 5c06e97bf3..d8a4fc4af1 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java @@ -25,6 +25,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; @@ -35,8 +36,6 @@ import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.*; import org.openecomp.sdc.be.datatypes.enums.*; import org.openecomp.sdc.be.model.*; -import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty; -import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition; import org.openecomp.sdc.be.model.catalog.CatalogComponent; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; @@ -971,7 +970,35 @@ public class ToscaOperationFacade { } - public Either<List<InputDefinition>, StorageOperationStatus> updateInputsToComponent(List<InputDefinition> inputs, String componentId) { + public Either<List<InputDefinition>, StorageOperationStatus> getComponentInputs(String componentId) { + + Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + + } + + Either<ToscaElement, StorageOperationStatus> toscaElement = + topologyTemplateOperation.getToscaElement(componentId); + if(toscaElement.isRight()) { + return Either.right(toscaElement.right().value()); + } + + TopologyTemplate topologyTemplate = (TopologyTemplate) toscaElement.left().value(); + + Map<String, PropertyDataDefinition> inputsMap = topologyTemplate.getInputs(); + + List<InputDefinition> inputs = new ArrayList<>(); + if(MapUtils.isNotEmpty(inputsMap)) { + inputs = + inputsMap.values().stream().map(p -> new InputDefinition(p)).collect(Collectors.toList()); + } + + return Either.left(inputs); + } + + public Either<List<InputDefinition>, StorageOperationStatus> updateInputsToComponent(List<InputDefinition> inputs, String componentId) { Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); if (getVertexEither.isRight()) { @@ -1135,7 +1162,7 @@ public class ToscaOperationFacade { } return Either.left(instProperties); } - + public Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> addComponentInstancePropertiesToComponent(Component containerComponent, Map<String, List<ComponentInstanceProperty>> instProperties) { requireNonNull(instProperties); StorageOperationStatus status; @@ -1984,91 +2011,97 @@ public class ToscaOperationFacade { return nodeTemplateOperation.generateCustomizationUUIDOnInstanceGroup(componentId, instanceId, groupInstances); } - /* - * adds property to a resource - * @warn this method has SIDE EFFECT on ownerId ,use it with caution - * */ - public Either<PropertyDefinition, StorageOperationStatus> addPropertyToResource(String propertyName, PropertyDefinition newPropertyDefinition, Resource resource) { - - Either<PropertyDefinition, StorageOperationStatus> result = null; - Either<Component, StorageOperationStatus> getUpdatedComponentRes = null; - newPropertyDefinition.setName(propertyName); - StorageOperationStatus status = getToscaElementOperation(resource).addToscaDataToToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_ADD_THE_PROPERTY_TO_THE_RESOURCE_STATUS_IS, propertyName, resource.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreProperties(false); - getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_UPDATED_RESOURCE_STATUS_IS, resource.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - PropertyDefinition newProperty = null; - List<PropertyDefinition> properties = ((Resource) getUpdatedComponentRes.left().value()).getProperties(); - if (CollectionUtils.isNotEmpty(properties)) { - Optional<PropertyDefinition> newPropertyOptional = properties.stream().filter(p -> p.getName().equals(propertyName)).findAny(); - if (newPropertyOptional.isPresent()) { - newProperty = newPropertyOptional.get(); - } - } - if (newProperty == null) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FIND_RECENTLY_ADDED_PROPERTY_ON_THE_RESOURCE_STATUS_IS, propertyName, resource.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } else { - result = Either.left(newProperty); - } - } - return result; - } - - public StorageOperationStatus deletePropertyOfResource(Resource resource, String propertyName) { - return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME); - } - - public StorageOperationStatus deleteAttributeOfResource(Component component, String attributeName) { - return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, attributeName, JsonPresentationFields.NAME); - } + public Either<PropertyDefinition, StorageOperationStatus> addPropertyToComponent(String propertyName, + PropertyDefinition newPropertyDefinition, + Component component) { + + Either<PropertyDefinition, StorageOperationStatus> result = null; + Either<Component, StorageOperationStatus> getUpdatedComponentRes = null; + newPropertyDefinition.setName(propertyName); + + StorageOperationStatus status = getToscaElementOperation(component) + .addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the component {}. Status is {}. ", propertyName, component.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreProperties(false); + filter.setIgnoreInputs(false); + getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated component {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + PropertyDefinition newProperty = null; + List<PropertyDefinition> properties = + (getUpdatedComponentRes.left().value()).getProperties(); + if (CollectionUtils.isNotEmpty(properties)) { + Optional<PropertyDefinition> propertyOptional = properties.stream().filter( + propertyEntry -> propertyEntry.getName().equals(propertyName)).findAny(); + if (propertyOptional.isPresent()) { + newProperty = propertyOptional.get(); + } + } + if (newProperty == null) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the component {}. Status is {}. ", propertyName, component.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } else { + result = Either.left(newProperty); + } + } + return result; + } + public StorageOperationStatus deletePropertyOfComponent(Component component, String propertyName) { + return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME); + } + + public StorageOperationStatus deleteAttributeOfResource(Component component, String attributeName) { + return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, attributeName, JsonPresentationFields.NAME); + } public StorageOperationStatus deleteInputOfResource(Component resource, String inputName) { return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputName, JsonPresentationFields.NAME); } - public Either<PropertyDefinition, StorageOperationStatus> updatePropertyOfResource(Resource resource, PropertyDefinition newPropertyDefinition) { - - Either<Component, StorageOperationStatus> getUpdatedComponentRes = null; - Either<PropertyDefinition, StorageOperationStatus> result = null; - StorageOperationStatus status = getToscaElementOperation(resource).updateToscaDataOfToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); - if (status != StorageOperationStatus.OK) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_ADD_THE_PROPERTY_TO_THE_RESOURCE_STATUS_IS, newPropertyDefinition.getName(), resource.getName(), status); - result = Either.right(status); - } - if (result == null) { - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreProperties(false); - getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter); - if (getUpdatedComponentRes.isRight()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_UPDATED_RESOURCE_STATUS_IS, resource.getUniqueId(), getUpdatedComponentRes.right().value()); - result = Either.right(status); - } - } - if (result == null) { - Optional<PropertyDefinition> newProperty = ((Resource) getUpdatedComponentRes.left().value()).getProperties().stream().filter(p -> p.getName().equals(newPropertyDefinition.getName())).findAny(); - if (newProperty.isPresent()) { - result = Either.left(newProperty.get()); - } else { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FIND_RECENTLY_ADDED_PROPERTY_ON_THE_RESOURCE_STATUS_IS, newPropertyDefinition.getName(), resource.getUniqueId(), StorageOperationStatus.NOT_FOUND); - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - return result; - } - - public Either<PropertyDefinition, StorageOperationStatus> addAttributeOfResource(Component component, PropertyDefinition newAttributeDef) { + public Either<PropertyDefinition, StorageOperationStatus> updatePropertyOfComponent(Component component, + PropertyDefinition newPropertyDefinition) { + + Either<Component, StorageOperationStatus> getUpdatedComponentRes = null; + Either<PropertyDefinition, StorageOperationStatus> result = null; + StorageOperationStatus status = getToscaElementOperation(component).updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME); + if (status != StorageOperationStatus.OK) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newPropertyDefinition.getName(), component.getName(), status); + result = Either.right(status); + } + if (result == null) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreProperties(false); + getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter); + if (getUpdatedComponentRes.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value()); + result = Either.right(status); + } + } + if (result == null) { + Optional<PropertyDefinition> newProperty = (getUpdatedComponentRes.left().value()) + .getProperties().stream().filter(p -> p.getName().equals(newPropertyDefinition.getName())).findAny(); + if (newProperty.isPresent()) { + result = Either.left(newProperty.get()); + } else { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newPropertyDefinition.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND); + result = Either.right(StorageOperationStatus.NOT_FOUND); + } + } + return result; + } + + + + public Either<PropertyDefinition, StorageOperationStatus> addAttributeOfResource(Component component, PropertyDefinition newAttributeDef) { Either<Component, StorageOperationStatus> getUpdatedComponentRes = null; Either<PropertyDefinition, StorageOperationStatus> result = null; @@ -2263,10 +2296,11 @@ public class ToscaOperationFacade { .orElse(StorageOperationStatus.NOT_FOUND); } - public StorageOperationStatus updateComponentCalculatedCapabilitiesProperties(Component containerComponent) { - Map<String, MapCapabilityProperty> MapCapabilityPropertyMap = convertComponentCapabilitiesProperties(containerComponent); - return nodeTemplateOperation.overrideComponentCapabilitiesProperties(containerComponent, MapCapabilityPropertyMap); - } + public StorageOperationStatus updateComponentCalculatedCapabilitiesProperties(Component containerComponent) { + Map<String, MapCapabilityProperty> mapCapabiltyPropertyMap = + convertComponentCapabilitiesProperties(containerComponent); + return nodeTemplateOperation.overrideComponentCapabilitiesProperties(containerComponent, mapCapabiltyPropertyMap); + } public StorageOperationStatus deleteAllCalculatedCapabilitiesRequirements(String topologyTemplateId) { StorageOperationStatus status = topologyTemplateOperation.removeToscaData(topologyTemplateId, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES); @@ -2309,11 +2343,24 @@ public class ToscaOperationFacade { return topologyTemplateOperation.getComponentInstanceCapabilityProperties(componentId, instanceId, capabilityName, capabilityType, ownerId); } - private Map<String, MapCapabilityProperty> convertComponentCapabilitiesProperties(Component currComponent) { - Map<String, MapCapabilityProperty> map = ModelConverter.extractCapabilityPropertiesFromGroups(currComponent.getGroups(), true); - map.putAll(ModelConverter.extractCapabilityProperteisFromInstances(currComponent.getComponentInstances(), true)); - return map; - } + private MapInterfaceDataDefinition convertComponentInstanceInterfaces(Component currComponent, + String componentInstanceId) { + MapInterfaceDataDefinition mapInterfaceDataDefinition = new MapInterfaceDataDefinition(); + List<ComponentInstanceInterface> componentInterface = currComponent.getComponentInstancesInterfaces().get(componentInstanceId); + + if(CollectionUtils.isNotEmpty(componentInterface)) { + componentInterface.stream().forEach(interfaceDef -> mapInterfaceDataDefinition.put + (interfaceDef.getUniqueId(), interfaceDef)); + } + + return mapInterfaceDataDefinition; + } + + private Map<String, MapCapabilityProperty> convertComponentCapabilitiesProperties(Component currComponent) { + Map<String, MapCapabilityProperty> map = ModelConverter.extractCapabilityPropertiesFromGroups(currComponent.getGroups(), true); + map.putAll(ModelConverter.extractCapabilityProperteisFromInstances(currComponent.getComponentInstances(), true)); + return map; + } private Optional<MapCapabilityProperty> convertComponentInstanceProperties(Component component, String instanceId) { return component.fetchInstanceById(instanceId) @@ -2433,4 +2480,71 @@ public class ToscaOperationFacade { throw new StorageException(status); } + public Either<Boolean, StorageOperationStatus> isComponentInUse(String componentId) { + final List<EdgeLabelEnum> forbiddenEdgeLabelEnums = Arrays.asList(EdgeLabelEnum.INSTANCE_OF, EdgeLabelEnum.PROXY_OF, EdgeLabelEnum.ALLOTTED_OF); + Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(componentId); + if (vertexById.isLeft()) { + for (EdgeLabelEnum edgeLabelEnum : forbiddenEdgeLabelEnums) { + Iterator<Edge> edgeItr = vertexById.left().value().getVertex().edges(Direction.IN, edgeLabelEnum.name()); + if(edgeItr != null && edgeItr.hasNext()){ + return Either.left(true); + } + } + } + return Either.left(false); + } + + public Either<List<Component>, StorageOperationStatus> getComponentListByInvariantUuid + (String componentInvariantUuid, Map<GraphPropertyEnum, Object> additionalPropertiesToMatch) { + + Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class); + if (MapUtils.isNotEmpty(additionalPropertiesToMatch)) { + propertiesToMatch.putAll(additionalPropertiesToMatch); + } + propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, componentInvariantUuid); + + Either<List<GraphVertex>, TitanOperationStatus> vertexEither = titanDao.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata); + + if (vertexEither.isRight()) { + log.debug("Couldn't fetch metadata for component with type {} and invariantUUId {}, error: {}", componentInvariantUuid, vertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexEither.right().value())); + } + List<GraphVertex> vertexList = vertexEither.isLeft() ? vertexEither.left().value() : null; + + if (vertexList == null || vertexList.isEmpty()) { + log.debug("Component with invariantUUId {} was not found", componentInvariantUuid); + return Either.right(StorageOperationStatus.NOT_FOUND); + } + + ArrayList<Component> components = new ArrayList<>(); + for (GraphVertex vertex : vertexList) { + Either<Component, StorageOperationStatus> toscaElementByOperation = getToscaElementByOperation(vertex); + if (toscaElementByOperation.isRight()) { + log.debug("Could not fetch the following Component by Invariant UUID {}", vertex.getUniqueId()); + return Either.right(toscaElementByOperation.right().value()); + } + components.add(toscaElementByOperation.left().value()); + } + + return Either.left(components); + } + + public Either<List<Component>, StorageOperationStatus> getParentComponents(String componentId) { + List<Component> parentComponents = new ArrayList<>(); + final List<EdgeLabelEnum> relationEdgeLabelEnums = Arrays.asList(EdgeLabelEnum.INSTANCE_OF, EdgeLabelEnum.PROXY_OF); + Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(componentId); + if (vertexById.isLeft()) { + for (EdgeLabelEnum edgeLabelEnum : relationEdgeLabelEnums) { + Either<GraphVertex, TitanOperationStatus> parentVertexEither = titanDao.getParentVertex(vertexById.left().value(), edgeLabelEnum, JsonParseFlagEnum.ParseJson); + if(parentVertexEither.isLeft()){ + Either<Component, StorageOperationStatus> componentEither = getToscaElement(parentVertexEither.left().value().getUniqueId()); + if(componentEither.isLeft()){ + parentComponents.add(componentEither.left().value()); + } + } + } + } + return Either.left(parentComponents); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java index 569491cef6..6a49509d6f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java @@ -22,68 +22,17 @@ package org.openecomp.sdc.be.model.jsontitan.utils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; -import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty; -import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapListRequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.*; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.AdditionalInformationDefinition; -import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.CapabilityDefinition; -import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.DistributionStatusEnum; -import org.openecomp.sdc.be.model.GroupDefinition; -import org.openecomp.sdc.be.model.GroupInstance; -import org.openecomp.sdc.be.model.InputDefinition; -import org.openecomp.sdc.be.model.InterfaceDefinition; -import org.openecomp.sdc.be.model.PolicyDefinition; -import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.RelationshipImpl; -import org.openecomp.sdc.be.model.RelationshipInfo; -import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.RequirementDefinition; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; @@ -95,6 +44,11 @@ import org.openecomp.sdc.be.resources.data.ResourceMetadataData; import org.openecomp.sdc.be.resources.data.ServiceMetadataData; import org.openecomp.sdc.common.log.wrappers.Logger; +import java.util.*; +import java.util.Map.Entry; +import java.util.function.Function; +import java.util.stream.Collectors; + public class ModelConverter { public static final String CAP_PROP_DELIM = "#"; private static final Logger log = Logger.getLogger(ModelConverter.class); @@ -171,7 +125,11 @@ public class ModelConverter { convertComponentInstances(topologyTemplate, service); - convertInputs(topologyTemplate, service); + convertInputs(topologyTemplate, service); + + convertProperties(topologyTemplate, service); + + convertPolicies(topologyTemplate, service); convertGroups(topologyTemplate, service); @@ -591,8 +549,14 @@ public class ModelConverter { component.setDerivedFromGenericType(toscaElement.getDerivedFromGenericType()); component.setDerivedFromGenericVersion(toscaElement.getDerivedFromGenericVersion()); - //archive - component.setArchived(toscaElement.isArchived() == null ? false : toscaElement.isArchived()); + Map<String, PropertyDataDefinition> properties = toscaElement.getProperties(); + if(MapUtils.isNotEmpty(properties)) { + List<PropertyDefinition> propertiesMap = properties.values().stream().map(x -> new PropertyDefinition(x)).collect(Collectors.toList()); + component.setProperties(propertiesMap); + } + + //archive + component.setArchived(toscaElement.isArchived() == null ? false : toscaElement.isArchived()); //component.setArchiveTime(toscaElement.getArchiveTime() == null ? 0L : toscaElement.getArchiveTime()); @@ -632,14 +596,6 @@ public class ModelConverter { component.setContactId((String) toscaElement.getMetadataValue(JsonPresentationFields.CONTACT_ID)); component.setUUID((String) toscaElement.getMetadataValue(JsonPresentationFields.UUID)); component.setIsDeleted((Boolean) toscaElement.getMetadataValue(JsonPresentationFields.IS_DELETED)); - - - Map<String, PropertyDataDefinition> properties = toscaElement.getProperties(); - if (properties != null && !properties.isEmpty()) { - List<PropertyDefinition> propertiesMap = properties.values().stream().map(PropertyDefinition::new).collect(Collectors.toList()); - ((Resource) component).setProperties(propertiesMap); - } - component.setToscaType(toscaElement.getToscaType().getValue()); } @@ -944,34 +900,35 @@ public class ModelConverter { ComponentTypeEnum componentType = component.getComponentType(); topologyTemplate = new TopologyTemplate(); - if (componentType == ComponentTypeEnum.RESOURCE) { - Resource resource = (Resource) component; - topologyTemplate.setResourceType(resource.getResourceType()); - topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_UUID, resource.getCsarUUID()); - topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_VERSION, resource.getCsarVersion()); - topologyTemplate.setMetadataValue(JsonPresentationFields.IMPORTED_TOSCA_CHECKSUM, resource.getImportedToscaChecksum()); - convertInterfaces(resource, topologyTemplate); - } - if (componentType == ComponentTypeEnum.SERVICE) { - convertServiceSpecificEntities((Service) component, topologyTemplate); - } - convertCommonToscaData(component, topologyTemplate); - convertArtifacts(component, topologyTemplate); + if (componentType == ComponentTypeEnum.RESOURCE) { + Resource resource = (Resource) component; + topologyTemplate.setResourceType(resource.getResourceType()); + topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_UUID, resource.getCsarUUID()); + topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_VERSION, resource.getCsarVersion()); + topologyTemplate.setMetadataValue(JsonPresentationFields.IMPORTED_TOSCA_CHECKSUM, resource.getImportedToscaChecksum()); + convertTopologyTemplateInterfaces(resource, topologyTemplate); + } + if (componentType == ComponentTypeEnum.SERVICE) { + convertServiceSpecificEntities((Service) component, topologyTemplate); + } + convertCommonToscaData(component, topologyTemplate); + convertArtifacts(component, topologyTemplate); convertAdditionalInformation(component, topologyTemplate); convertComponentInstances(component, topologyTemplate); - convertInputs(component, topologyTemplate); - convertCapabilities(component, topologyTemplate); - convertGroups(component, topologyTemplate); - convertPolicies(component, topologyTemplate); - convertRequirements(component, topologyTemplate); - convertRelationsToComposition(component, topologyTemplate); + convertInputs(component, topologyTemplate); + convertProperties(component, topologyTemplate); + convertCapabilities(component, topologyTemplate); + convertGroups(component, topologyTemplate); + convertPolicies(component, topologyTemplate); + convertRequirements(component, topologyTemplate); + convertRelationsToComposition(component, topologyTemplate); return topologyTemplate; } - private static void convertInterfaces(Resource resource, TopologyTemplate topologyTemplate) { + private static void convertTopologyTemplateInterfaces(Resource resource, TopologyTemplate topologyTemplate) { Map<String, InterfaceDefinition> interfaces = resource.getInterfaces(); if (interfaces != null && !interfaces.isEmpty()) { Map<String, InterfaceDataDefinition> copy = interfaces.entrySet().stream() @@ -1047,17 +1004,36 @@ public class ModelConverter { } - private static void convertInputs(TopologyTemplate topologyTemplate, Component component) { - Map<String, PropertyDataDefinition> inputsMap = topologyTemplate.getInputs(); - if (inputsMap != null && !inputsMap.isEmpty()) { - List<InputDefinition> inputsList = inputsMap.values() - .stream() - .map(InputDefinition::new) - .collect(Collectors.toList()); - component.setInputs(inputsList); - } + private static void convertInputs(TopologyTemplate topologyTemplate, Component component) { + Map<String, PropertyDataDefinition> inputsMap = topologyTemplate.getInputs(); + if (inputsMap != null && !inputsMap.isEmpty()) { + List<InputDefinition> inputsList = inputsMap.values() + .stream() + .map(InputDefinition::new) + .collect(Collectors.toList()); + component.setInputs(inputsList); + } + } + + private static void convertProperties(Component component, TopologyTemplate topologyTemplate) { + List<PropertyDefinition> propertiesList = component.getProperties(); + if (propertiesList != null && !propertiesList.isEmpty()) { + Map<String, PropertyDataDefinition> propertiesMap = propertiesList.stream().map(i -> new PropertyDataDefinition(i)).collect(Collectors.toMap(i -> i.getName(), i -> i)); + topologyTemplate.setProperties(propertiesMap); + } + + } + + private static void convertProperties(TopologyTemplate topologyTemplate, Component component) { + Map<String, PropertyDataDefinition> proeprtiesMap = topologyTemplate.getProperties(); + if (proeprtiesMap != null && !proeprtiesMap.isEmpty()) { + Map<String, PropertyDefinition> copy = proeprtiesMap.entrySet().stream() + .collect(Collectors.toMap(entry -> entry.getKey(), entry -> new PropertyDefinition + (entry.getValue()))); + component.setProperties(new ArrayList<>(copy.values())); + } + } - } private static void convertCommonToscaData(Component component, ToscaElement toscaElement) { toscaElement.setUUID(component.getUUID()); @@ -1131,6 +1107,14 @@ public class ModelConverter { List<GroupInstance> groupInstances = topologyTemplate.getInstGroups().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new GroupInstance(e.getValue())).collect(Collectors.toList()); currComponentInstance.setGroupInstances(groupInstances); } + if(topologyTemplate.getInstProperties() != null && topologyTemplate.getInstProperties().containsKey(key) && topologyTemplate.getInstProperties().get(key) != null ){ + List<PropertyDefinition> instanceProps = topologyTemplate.getInstProperties().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new PropertyDefinition(e.getValue())).collect(Collectors.toList()); + currComponentInstance.setProperties(instanceProps); + } + if(topologyTemplate.getComponentInstInterfaces() != null && topologyTemplate.getComponentInstInterfaces().containsKey(key) && topologyTemplate.getComponentInstInterfaces().get(key) != null ){ + Map<String, Object> interfacesMap = topologyTemplate.getComponentInstInterfaces().get(key).getMapToscaDataDefinition().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + currComponentInstance.setInterfaces(interfacesMap); + } componentInstances.add(currComponentInstance); } component.setComponentInstances(componentInstances); @@ -1165,20 +1149,52 @@ public class ModelConverter { } } - private static void setComponentInstancesAttributesToComponent(TopologyTemplate topologyTemplate, Component component) { - if (topologyTemplate.getInstAttributes() != null) { - Map<String, List<ComponentInstanceProperty>> attributes = new HashMap<>(); - for (Map.Entry<String, MapPropertiesDataDefinition> entry : topologyTemplate.getInstAttributes().entrySet()) { - if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) { - String key = entry.getKey(); - List<ComponentInstanceProperty> componentInstanceAttributes = entry.getValue().getMapToscaDataDefinition().entrySet().stream().map(e -> new ComponentInstanceProperty(new ComponentInstanceProperty(e.getValue()))) - .collect(Collectors.toList()); - attributes.put(key, componentInstanceAttributes); - } - } - component.setComponentInstancesAttributes(attributes); - } - } + private static void setComponentInstancesInterfacesToComponent(TopologyTemplate topologyTemplate, Component component) { + if (topologyTemplate.getInstInterfaces() != null) { + Map<String, List<ComponentInstanceInterface>> interfaces = new HashMap<>(); + for (Entry<String, MapInterfaceInstanceDataDefinition> entry : topologyTemplate.getInstInterfaces().entrySet()) { + if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) { + String key = entry.getKey(); + List<ComponentInstanceInterface> componentInstanceInterfaces = entry.getValue() + .getMapToscaDataDefinition().entrySet().stream().map(e -> new + ComponentInstanceInterface(e.getKey(), e.getValue())) + .collect(Collectors.toList()); + interfaces.put(key, componentInstanceInterfaces); + } + } + component.setComponentInstancesInterfaces(interfaces); + } + else if (topologyTemplate.getComponentInstInterfaces() != null) { + Map<String, List<ComponentInstanceInterface>> interfaces = new HashMap<>(); + for (Entry<String, MapInterfaceDataDefinition> entry : topologyTemplate.getComponentInstInterfaces().entrySet()) { + if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) { + String key = entry.getKey(); + List<ComponentInstanceInterface> componentInstanceInterfaces = entry.getValue() + .getMapToscaDataDefinition().entrySet().stream().map(e -> new + ComponentInstanceInterface(e.getKey(), e.getValue())) + .collect(Collectors.toList()); + interfaces.put(key, componentInstanceInterfaces); + } + } + component.setComponentInstancesInterfaces(interfaces); + } + + } + + private static void setComponentInstancesAttributesToComponent(TopologyTemplate topologyTemplate, Component component) { + if (topologyTemplate.getInstAttributes() != null) { + Map<String, List<ComponentInstanceProperty>> attributes = new HashMap<>(); + for (Map.Entry<String, MapPropertiesDataDefinition> entry : topologyTemplate.getInstAttributes().entrySet()) { + if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) { + String key = entry.getKey(); + List<ComponentInstanceProperty> componentInstanceAttributes = entry.getValue().getMapToscaDataDefinition().entrySet().stream().map(e -> new ComponentInstanceProperty(new ComponentInstanceProperty(e.getValue()))) + .collect(Collectors.toList()); + attributes.put(key, componentInstanceAttributes); + } + } + component.setComponentInstancesAttributes(attributes); + } + } private static void setComponentInstancesRequirementsToComponent(TopologyTemplate topologyTemplate, Component component) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java index ca700b03d5..bb1096a900 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java @@ -62,6 +62,7 @@ public enum StorageOperationStatus { CANNOT_UPDATE_EXISTING_ENTITY, PROPERTY_NAME_ALREADY_EXISTS, INVALID_PROPERTY, - COMPONENT_IS_ARCHIVED; + COMPONENT_IS_ARCHIVED, + DECLARED_INPUT_USED_BY_OPERATION; } diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 7a845ef159..750563b092 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -27,6 +27,7 @@ import { UpgradeAdapter } from '@angular/upgrade'; import { UpgradeModule } from '@angular/upgrade/static'; import { SdcUiComponentsModule, SdcUiComponents } from "sdc-ui/lib/angular"; import { PropertiesAssignmentModule } from './pages/properties-assignment/properties-assignment.module'; +import { PropertyCreatorModule } from './pages/properties-assignment/property-creator/property-creator.module'; import { DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, StateServiceFactory, StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider, ScopeServiceFactory, @@ -102,6 +103,7 @@ export function configServiceFactory(config: ConfigService) { //We need to import them here since we use them in angular1 ConnectionWizardModule, PropertiesAssignmentModule, + PropertyCreatorModule, PluginFrameModule, InterfaceOperationModule, OperationCreatorModule, diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html index 65072f8185..2068b170b3 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html @@ -58,6 +58,9 @@ </div> <span *ngIf="property.description" class="property-description-icon sprite-new show-desc" tooltip="{{property.description}}" tooltipDelay="0"></span> + <div class="delete-button-container"> + <span *ngIf="showDelete" class="sprite-new delete-btn" [ngClass]="{'disabled' : property.isDisabled || property.isDeclared}" (click)="openDeleteModal(property)" data-tests-id="delete-input-button"></span> + </div> </div> <div class="table-cell col2" *ngIf="!hidePropertyType"> <div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}"> diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less index 0f6dd512e2..86832e57f0 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less @@ -189,6 +189,11 @@ } } + .delete-button-container { + max-height: 24px; + cursor: pointer; + } + .filtered { /deep/ .checkbox-label-content{ background-color: yellow; diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts index b11bc02fb9..167509b1e6 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts @@ -22,6 +22,7 @@ import { Component, Input, Output, EventEmitter} from "@angular/core"; import {PropertyFEModel, DerivedFEProperty, InstanceFePropertiesMap} from "app/models"; import {PropertiesService} from "../../../services/properties.service"; +import {ModalService} from "../../../services/modal.service"; import { InstanceFeDetails } from "../../../../models/instance-fe-details"; @Component({ @@ -40,10 +41,13 @@ export class PropertiesTableComponent { @Input() isLoading:boolean; @Input() hasDeclareOption:boolean; @Input() hidePropertyType:boolean; + @Input() showDelete:boolean; @Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>(); @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>(); @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption + @Output() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>(); + private selectedPropertyToDelete: PropertyFEModel; sortBy: String; reverse: boolean; @@ -57,7 +61,7 @@ export class PropertiesTableComponent { this.path = sortBy.split('.'); } - constructor (private propertiesService:PropertiesService ){ + constructor (private propertiesService:PropertiesService, private modalService: ModalService){ } ngOnInit() { @@ -92,6 +96,17 @@ export class PropertiesTableComponent { this.updateCheckedPropertyCount.emit(isChecked); } + onDeleteProperty = () => { + this.deleteProperty.emit(this.selectedPropertyToDelete); + this.modalService.closeCurrentModal(); + }; + + openDeleteModal = (property:PropertyFEModel) => { + this.selectedPropertyToDelete = property; + this.modalService.createActionModal("Delete Property", "Are you sure you want to delete this property?", + "Delete", this.onDeleteProperty, "Close").instance.open(); + } + } export class PropertyRowSelectedEvent { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html index ca3e90fbc2..8a3e8d23ee 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html @@ -29,12 +29,14 @@ [readonly]="isReadonly || resourceIsReadonly" [isLoading]="loadingProperties || savingChangedData" [hasDeclareOption]="true" + [showDelete]="!isReadOnly && isSelf()" (propertyChanged)="dataChanged($event)" (propertySelected)="propertySelected($event)" (selectPropertyRow)="selectPropertyRow($event)" (selectChildProperty)="selectChildProperty($event)" (updateCheckedPropertyCount)="updateCheckedPropertyCount($event)" - (selectInstanceRow)="selectInstanceRow($event)"> + (selectInstanceRow)="selectInstanceRow($event)" + (deleteProperty)="deleteProperty($event)"> </properties-table> </tab> <tab tabTitle="Inputs"> @@ -63,8 +65,10 @@ <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button">Declare</button> </div> </div> - <div class="right-column gray-border"> - <tabs #hierarchyNavTabs tabStyle="simple-tabs"> + <div class="right-column"> + <div *ngIf="!isReadonly" class="add-btn" + (click)="addProperty()" [ngClass]="{'disabled': !isSelf()}">Add Property</div> + <tabs #hierarchyNavTabs tabStyle="simple-tabs" class="gray-border"> <tab tabTitle="Composition"> <div class="hierarchy-nav-container"> <loader [display]="loadingInstances" [size]="'medium'" [relative]="true" [loaderDelay]="500"></loader> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less index 6de6dda7bb..95ff94317c 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less @@ -131,8 +131,14 @@ display:flex; flex:0 0 350px; flex-direction:column; - margin: 45px 0 0 1em; + margin: 0px 0 0 1em; overflow-x:auto; + .add-btn{ + + align-self: flex-end; + margin-top: 10px; + margin-bottom: 19px; + } /deep/ .tabs { border-bottom: solid 1px #d0d0d0; diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 5a21e86879..953c973d1a 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -38,12 +38,14 @@ import {ComponentModeService} from "../../services/component-services/component- import {ModalService} from "../../services/modal.service"; import {Tabs, Tab} from "../../components/ui/tabs/tabs.component"; import {InputsUtils} from "./services/inputs.utils"; +import {PropertyCreatorComponent} from "./property-creator/property-creator.component"; import { InstanceFeDetails } from "../../../models/instance-fe-details"; import { SdcUiComponents } from "sdc-ui/lib/angular"; //import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service"; import { IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config"; import { UnsavedChangesComponent } from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component"; +const SERVICE_SELF_TITLE = "SELF"; @Component({ templateUrl: './properties-assignment.page.component.html', styleUrls: ['./properties-assignment.page.component.less'] @@ -84,6 +86,7 @@ export class PropertiesAssignmentComponent { isValidChangedData:boolean; savingChangedData:boolean; stateChangeStartUnregister:Function; + serviceBePropertiesMap: InstanceBePropertiesMap; @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs; @ViewChild('propertyInputTabs') propertyInputTabs: Tabs; @@ -132,7 +135,7 @@ export class PropertiesAssignmentComponent { }); this.loadingInputs = false; - }, error => {}); //ignore error + }); this.componentServiceNg2 .getComponentResourcePropertiesData(this.component) .subscribe(response => { @@ -141,6 +144,12 @@ export class PropertiesAssignmentComponent { this.instances.push(...response.groupInstances); this.instances.push(...response.policies); + // add the service self instance to the top of the list. + const serviceInstance = new ComponentInstance(); + serviceInstance.name = SERVICE_SELF_TITLE; + serviceInstance.uniqueId = this.component.uniqueId; + this.instances.unshift(serviceInstance); + _.forEach(this.instances, (instance) => { this.instancesNavigationData.push(instance); this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{name: instance.name, iconClass:instance.iconClass, originArchived:instance.originArchived}; @@ -150,7 +159,7 @@ export class PropertiesAssignmentComponent { this.loadingProperties = false; } this.selectFirstInstanceByDefault(); - }, error => {}); //ignore error + }); this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => { // stop if has changed properties @@ -183,6 +192,23 @@ export class PropertiesAssignmentComponent { this.updateViewMode(); } + isSelf = ():boolean => { + return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId; + } + + getServiceProperties(){ + this.loadingProperties = false; + this.componentServiceNg2 + .getServiceProperties(this.component) + .subscribe(response => { + this.serviceBePropertiesMap = new InstanceBePropertiesMap(); + this.serviceBePropertiesMap[this.component.uniqueId] = response; + this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false); + this.loadingProperties = false; + }, error => { + this.loadingProperties = false; + }); + } onInstanceSelectedUpdate = (instance: ComponentInstance|GroupInstance|PolicyInstance) => { // stop if has changed properties @@ -210,6 +236,8 @@ export class PropertiesAssignmentComponent { this.loadingProperties = false; }, error => { }); //ignore error + } else if (this.isSelf()) { + this.getServiceProperties(); } else { this.componentInstanceServiceNg2 .getComponentInstanceProperties(this.component, instance.uniqueId) @@ -391,7 +419,7 @@ export class PropertiesAssignmentComponent { let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties); this.componentServiceNg2 - .createInput(this.component, inputsToCreate) + .createInput(this.component, inputsToCreate, this.isSelf()) .subscribe(response => { this.setInputTabIndication(response.length); this.checkedPropertiesCount = 0; @@ -439,8 +467,12 @@ export class PropertiesAssignmentComponent { console.log('updated instance inputs:', response); }; } else { - request = this.componentInstanceServiceNg2 - .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties) + if (this.isSelf()) { + request = this.componentServiceNg2.updateServiceProperties(this.component, changedProperties); + } else { + request = this.componentInstanceServiceNg2 + .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties); + } handleSuccess = (response) => { // reset each changed property with new value and remove it from changed properties list response.forEach((resProp) => { @@ -650,7 +682,57 @@ export class PropertiesAssignmentComponent { }, error => {}); //ignore error }; + deleteProperty = (property: PropertyFEModel) => { + let propertyToDelete = new PropertyFEModel(property); + this.loadingProperties = true; + let feMap = this.instanceFePropertiesMap; + this.componentServiceNg2 + .deleteServiceProperty(this.component, propertyToDelete) + .subscribe(response => { + const props = feMap[this.component.uniqueId]; + props.splice(props.findIndex(p => p.uniqueId === response),1); + this.loadingProperties = false; + }, error => { + this.loadingProperties = false; + console.error(error); + }); + }; + + /*** addProperty ***/ + addProperty = () => { + let modalTitle = 'Add Property'; + const modal = this.ModalService.createCustomModal(new ModalModel( + 'sm', + modalTitle, + null, + [ + new ButtonModel('Save', 'blue', () => { + modal.instance.dynamicContent.instance.isLoading = true; + const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel; + this.componentServiceNg2.createServiceProperty(this.component, newProperty) + .subscribe(response => { + modal.instance.dynamicContent.instance.isLoading = false; + let newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response); + this.instanceFePropertiesMap[this.component.uniqueId].push(newProp); + modal.instance.close(); + }, (error) => { + modal.instance.dynamicContent.instance.isLoading = false; + this.Notification.error({ + message: 'Failed to add property:' + error, + title: 'Failure' + }); + }); + }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()), + new ButtonModel('Cancel', 'outline grey', () => { + modal.instance.close(); + }), + ], + null + )); + this.ModalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {}); + modal.instance.open(); + }; /*** SEARCH RELATED FUNCTIONS ***/ searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html new file mode 100644 index 0000000000..e97ec79c04 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html @@ -0,0 +1,46 @@ +<div class="property-creator"> + <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader> + <form class="w-sdc-form"> + + <div class="side-by-side"> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label required">Name</label> + <input class="i-sdc-form-input" + type="text" + name="propertyName" + data-tests-id="property-name" + [(ngModel)]="propertyModel.name" + [ngModelOptions]="{ debounce: 200 }" + autofocus/> + </div> + <!-- Type --> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label required">Type</label> + <ui-element-dropdown [testId]="'property-type'" + class="cell link-selector" + [values]="typesProperties" + [(value)]="propertyModel.type"></ui-element-dropdown> + </div> + <div class="i-sdc-form-item propertySchemaType" *ngIf="showSchema()"> + <label class="i-sdc-form-label required">Schema Type</label> + <ui-element-dropdown [testId]="'property-type'" + class="cell link-selector" + [values]="typesSchemaProperties" + [(value)]="propertyModel.schema.property.type"></ui-element-dropdown> + </div> + </div> + + <!-- Description --> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label">Description</label> + <textarea class="i-sdc-form-textarea" + [pattern]="commentValidationPattern" + name="propertyDescription" + [(ngModel)]="propertyModel.description" + [ngModelOptions]="{ debounce: 200 }" + data-tests-id="property-description" + ></textarea> + </div> + + </form> +</div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less new file mode 100644 index 0000000000..d17a45e2c9 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less @@ -0,0 +1,35 @@ +@import '../../../../../assets/styles/variables.less'; + +.property-creator { + font-family: @font-opensans-regular; + user-select: none; + padding-top: 12px; + padding-bottom: 20px; + + .i-sdc-form-label { + font-size: 12px; + } + + .w-sdc-form .i-sdc-form-item { + margin-bottom: 15px; + } + + .side-by-side { + display: flex; + + .i-sdc-form-item { + flex-basis: 100%; + + &:first-child { + flex-basis: 50%; + margin-right: 10px; + } + + } + .propertySchemaType{ + margin-left: 10px; + } + } + + +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts new file mode 100644 index 0000000000..d5946d2e4a --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts @@ -0,0 +1,78 @@ +import * as _ from "lodash"; +import {Component} from '@angular/core'; +import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component"; +import { DataTypeService } from "app/ng2/services/data-type.service"; +import {PropertyBEModel, DataTypesMap} from "app/models"; +import {PROPERTY_DATA} from "app/utils"; +import {PROPERTY_TYPES} from "../../../../utils"; + + + +@Component({ + selector: 'property-creator', + templateUrl: './property-creator.component.html', + styleUrls:['./property-creator.component.less'], +}) + +export class PropertyCreatorComponent { + + typesProperties: Array<DropdownValue>; + typesSchemaProperties: Array<DropdownValue>; + propertyModel: PropertyBEModel; + //propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/; + //commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/; + //types:Array<string>; + dataTypes:DataTypesMap; + isLoading:boolean; + + constructor(protected dataTypeService:DataTypeService) {} + + ngOnInit() { + this.propertyModel = new PropertyBEModel(); + this.propertyModel.type = ''; + this.propertyModel.schema.property.type = ''; + const types: Array<string> = PROPERTY_DATA.TYPES; //All types - simple type + map + list + this.dataTypes = this.dataTypeService.getAllDataTypes(); //Get all data types in service + const nonPrimitiveTypes :Array<string> = _.filter(Object.keys(this.dataTypes), (type:string)=> { + return types.indexOf(type) == -1; + }); + + this.typesProperties = _.map(PROPERTY_DATA.TYPES, + (type: string) => new DropdownValue(type, type) + ); + let typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES, + (type: string) => new DropdownValue(type, type) + ); + let nonPrimitiveTypesValues = _.map(nonPrimitiveTypes, + (type: string) => new DropdownValue(type, + type.replace("org.openecomp.datatypes.heat.","")) + ); + this.typesProperties = _.concat(this.typesProperties,nonPrimitiveTypesValues); + this.typesSchemaProperties = _.concat(typesSimpleProperties,nonPrimitiveTypesValues); + this.typesProperties.unshift(new DropdownValue('','Select Type...')); + this.typesSchemaProperties.unshift(new DropdownValue('','Select Schema Type...')); + + } + + checkFormValidForSubmit(){ + const showSchema:boolean = this.showSchema(); + let isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type)? false : true; + if (!showSchema){ + this.propertyModel.schema.property.type = ''; + } + return this.propertyModel.name && this.propertyModel.type && isSchemaValid; + } + + showSchema():boolean { + return [PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP].indexOf(this.propertyModel.type) > -1; + }; + + onSchemaTypeChange():void { + if (this.propertyModel.type == PROPERTY_TYPES.MAP) { + this.propertyModel.value = JSON.stringify({'': null}); + } else if (this.propertyModel.type == PROPERTY_TYPES.LIST) { + this.propertyModel.value = JSON.stringify([]); + } + }; + +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts new file mode 100644 index 0000000000..92accb26b5 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts @@ -0,0 +1,27 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {PropertyCreatorComponent} from "./property-creator.component"; +import {FormsModule} from "@angular/forms"; +import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module"; +import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; +import {TranslateModule} from "../../../shared/translator/translate.module"; + +@NgModule({ + declarations: [ + PropertyCreatorComponent, + ], + imports: [ + CommonModule, + FormsModule, + FormElementsModule, + UiElementsModule, + TranslateModule + ], + exports: [], + entryComponents: [ + PropertyCreatorComponent + ], + providers: [] +}) + +export class PropertyCreatorModule {} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts index e7b59b96ba..3ed535d6a0 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts @@ -75,6 +75,14 @@ export class PropertiesUtils { return instanceFePropertiesMap; } + public convertAddPropertyBAToPropertyFE = (property: PropertyBEModel):PropertyFEModel => { + let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE + this.initValueObjectRef(newFEProp); + newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children + this.dataTypeService.checkForCustomBehavior(newFEProp); + return newFEProp; + } + public createListOrMapChildren = (property:PropertyFEModel | DerivedFEProperty, key: string, valueObj: any): Array<DerivedFEProperty> => { let newProps: Array<DerivedFEProperty> = []; let parentProp = new DerivedFEProperty(property, property.propertiesName, true, key, valueObj); diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts index 97e62daba7..69871abe04 100644 --- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts @@ -24,7 +24,7 @@ import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; import {Response, URLSearchParams} from '@angular/http'; -import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, OperationModel, BEOperationModel, CreateOperationResponse} from "app/models"; +import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, PropertyBEModel, OperationModel, BEOperationModel, CreateOperationResponse} from "app/models"; import {downgradeInjectable} from '@angular/upgrade/static'; import {COMPONENT_FIELDS, CommonUtils} from "app/utils"; import {ComponentGenericResponse} from "../responses/component-generic-response"; @@ -205,8 +205,9 @@ export class ComponentServiceNg2 { return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_RELATION, COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_GROUPS]); } - createInput(component:Component, inputsToCreate:InstancePropertiesAPIMap):Observable<any> { - return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputsToCreate) + createInput(component:Component, inputsToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> { + let inputs = isSelf ? { serviceProperties: inputsToCreate.componentInstanceProperties } : inputsToCreate; + return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputs) .map(res => { return res.json(); }) @@ -247,6 +248,42 @@ export class ComponentServiceNg2 { }); } + createServiceProperty(component: Component, propertyModel:PropertyBEModel): Observable<PropertyBEModel> { + let serverObject = {}; + serverObject[propertyModel.name] = propertyModel; + return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', serverObject) + .map(res => { + let property:PropertyBEModel = new PropertyBEModel(res.json()); + return property; + }) + } + + getServiceProperties(component: Component): Observable<Array<PropertyBEModel>> { + return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties') + .map((res: Response) => { + if (!res.text()){ + return new Array<PropertyBEModel>(); + } + return CommonUtils.initBeProperties(res.json()); + }); + } + + updateServiceProperties(component: Component, properties: PropertyBEModel[]) { + return this.http.put( this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', properties) + .map((res: Response) => { + const resJson = res.json(); + return _.map(resJson, + (resValue:PropertyBEModel) => new PropertyBEModel(resValue)); + }); + } + + deleteServiceProperty(component:Component, property:PropertyBEModel):Observable<string> { + return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties/' + property.uniqueId ) + .map((res:Response) => { + return property.uniqueId; + }) + } + getDependencies(componentType:string, componentId: string):Observable<Array<IDependenciesServerResponse>> { return this.http.get(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies') .map((res:Response) => { diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/InterfaceInstanceDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/InterfaceInstanceDataDefinition.java new file mode 100644 index 0000000000..29859cb279 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/InterfaceInstanceDataDefinition.java @@ -0,0 +1,81 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.datatypes.elements; + +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class InterfaceInstanceDataDefinition extends ToscaDataDefinition implements Serializable { + protected Map<String, Object> inputs; + protected Map<String, OperationInstance> operations; + + public InterfaceInstanceDataDefinition( + InterfaceInstanceDataDefinition inter) { + this.toscaPresentation = null; + this.inputs = inter.inputs == null? new HashMap():new HashMap<>(inter.inputs); + this.operations = new HashMap<>(inter.operations); + } + + public InterfaceInstanceDataDefinition(){ + this.toscaPresentation = null; + } + + public Map<String, Object> getInputs() { + return this.inputs; + } + + public void setInputs( + Map<String, Object> inputs) { + this.inputs = inputs; + } + + public Map<String, OperationInstance> getOperations() { + return operations; + } + + public void addInstanceOperation(String operationName, OperationInstance operation) { + if(MapUtils.isEmpty(this.operations)) { + this.operations = new HashMap<>(); + } + + this.operations.put(operationName, operation); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof InterfaceInstanceDataDefinition)) { + return false; + } + InterfaceInstanceDataDefinition that = (InterfaceInstanceDataDefinition) o; + return Objects.equals(inputs, that.inputs); + } + + @Override + public int hashCode() { + + return Objects.hash(inputs); + } + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationImplementation.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationImplementation.java new file mode 100644 index 0000000000..7d6ebdd2ed --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationImplementation.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.datatypes.elements; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; + +public class OperationImplementation { + + private String primary; + private List<String> dependencies; + + public String getPrimary() { + return primary; + } + + public void setPrimary(String primary) { + this.primary = primary; + } + + public List<String> getDependencies() { + return dependencies; + } + + public void setDependencies(List<String> dependencies) { + this.dependencies = dependencies; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof OperationImplementation)) { + return false; + } + OperationImplementation that = (OperationImplementation) o; + return Objects.equals(primary, that.primary) && + Objects.equals(new HashSet<>(dependencies), new HashSet<>(that.dependencies)); + } + + @Override + public int hashCode() { + return Objects.hash(primary, dependencies); + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInstance.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInstance.java new file mode 100644 index 0000000000..59a235b554 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInstance.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.datatypes.elements; + +import java.util.Map; +import java.util.Objects; + +public class OperationInstance/* extends Operation*/ { + private OperationImplementation implementation; + private Map<String, Object> inputs; + + + public OperationImplementation getImplementation() { + return implementation; + } + + public void setImplementation(OperationImplementation implementation) { + this.implementation = implementation; + } + + public Map<String, Object> getInputs() { + return inputs; + } + + public void setInputs(Map<String, Object> inputs) { + this.inputs = inputs; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof OperationInstance)) { + return false; + } + OperationInstance that = (OperationInstance) o; + return Objects.equals(implementation, that.implementation) && + Objects.equals(inputs, that.inputs); + } + + @Override + public int hashCode() { + + return Objects.hash(implementation, inputs); + } +} |