diff options
author | Toshimichi Fukuda <t_fukuda@jp.fujitsu.com> | 2019-04-18 21:38:46 +0900 |
---|---|---|
committer | Ofir Sonsino <ofir.sonsino@intl.att.com> | 2019-05-07 16:09:28 +0000 |
commit | 51411acd1d4b06fc9bbc40338a27dd061dba425f (patch) | |
tree | 51cbc4bb3372b7aa06e566eec6181b7a1838eee5 | |
parent | 55c536e65dcbd1981de61c6c8bea318585324d22 (diff) |
Change to enable SDC list type input
Change-Id: Ic3a9c6e714a5afd22b58bf2cb066932b1ec2a5c0
Issue-ID: SDC-2046
Signed-off-by: Toshimichi Fukuda <t_fukuda@jp.fujitsu.com>
Signed-off-by: Satoshi Fujii <fujii-satoshi@jp.fujitsu.com>
Signed-off-by: Ayumu Ueha <ueha.ayumu@jp.fujitsu.com>
58 files changed, 3698 insertions, 472 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogic.java new file mode 100644 index 0000000000..e020876b3b --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogic.java @@ -0,0 +1,138 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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.components.impl; + +import fj.data.Either; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@org.springframework.stereotype.Component("dataTypeBusinessLogic") +public class DataTypeBusinessLogic extends BaseBusinessLogic { + + /** + * Get a list of data types that the Component has. + * + * @param componentId Unique ID of the Component + * @return list of data types + */ + public Either<List<DataTypeDefinition>, StorageOperationStatus> getPrivateDataTypes(String componentId) { + ComponentParametersView filter = new ComponentParametersView(); + filter.disableAll(); + filter.setIgnoreDataType(false); + + // Get Component object + Either<? extends Component, StorageOperationStatus> componentResult = + toscaOperationFacade.getToscaElement(componentId, filter); + if (componentResult.isRight()) { + return Either.right(componentResult.right().value()); + } + Component component = componentResult.left().value(); + + List<DataTypeDefinition> dataTypesToReturn = component.getDataTypes(); + if (dataTypesToReturn == null) { + // this means there is no DATA_TYPES graph vertex. + // in this case, returns empty list. + dataTypesToReturn = new ArrayList<>(); + } + + return Either.left(dataTypesToReturn); + } + + /** + * Get a data type in a Component + * + * @param componentId Unique ID of the Component + * @param dataTypeName Data type name + * @return found data type + */ + public Either<DataTypeDefinition, StorageOperationStatus> getPrivateDataType(String componentId, String dataTypeName) { + Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypesResult = this.getPrivateDataTypes(componentId); + if (dataTypesResult.isRight()) { + return Either.right(dataTypesResult.right().value()); + } + List<DataTypeDefinition> dataTypes = dataTypesResult.left().value(); + Optional<DataTypeDefinition> findResult = dataTypes.stream().filter(e -> e.getName().equals(dataTypeName)).findAny(); + if (!findResult.isPresent()) { + return Either.right(StorageOperationStatus.NOT_FOUND); + } + return Either.left(findResult.get()); + } + + /** + * Delete a data type from the Component. + * + * @param componentId Unique ID of the Component + * @param dataTypeName Data type name to be deleted + * @return deleted data type + */ + public Either<DataTypeDefinition, StorageOperationStatus> deletePrivateDataType(String componentId, String dataTypeName) { + ComponentParametersView filter = new ComponentParametersView(); + filter.disableAll(); + filter.setIgnoreDataType(false); + + // Get Component object + Either<? extends Component, StorageOperationStatus> componentResult = + toscaOperationFacade.getToscaElement(componentId, filter); + if (componentResult.isRight()) { + // not exists + return Either.right(componentResult.right().value()); + } + + return deletePrivateDataType(componentResult.left().value(), dataTypeName); + } + + /** + * Delete a data type from the Component. + * + * @param component Component object which has data types. + * needs to be fetched with componentParametersView.setIgnoreDataType(false) + * @param dataTypeName Data type name to be deleted + * @return deleted data type + */ + public Either<DataTypeDefinition, StorageOperationStatus> deletePrivateDataType(Component component, String dataTypeName) { + // check the specified data type exists + List<DataTypeDefinition> dataTypes = component.getDataTypes(); + if (CollectionUtils.isEmpty(dataTypes)) { + return Either.right(StorageOperationStatus.NOT_FOUND); + } + Optional<DataTypeDefinition> dataTypeResult = + dataTypes.stream().filter(e -> e.getName().equals(dataTypeName)).findFirst(); + if (!dataTypeResult.isPresent()) { + return Either.right(StorageOperationStatus.NOT_FOUND); + } + + // delete it + StorageOperationStatus deleteResult = toscaOperationFacade.deleteDataTypeOfComponent(component, dataTypeName); + if (deleteResult != StorageOperationStatus.OK) { + return Either.right(deleteResult); + } + + // return deleted data type if ok + return Either.left(dataTypeResult.get()); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java index 214b5df4e1..a98694626f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java @@ -22,7 +22,9 @@ package org.openecomp.sdc.be.components.impl; import fj.data.Either; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -31,6 +33,10 @@ import java.util.stream.Collectors; import javax.inject.Inject; import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator; import org.openecomp.sdc.be.components.validation.ComponentValidations; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -42,14 +48,18 @@ import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; import org.openecomp.sdc.be.model.ComponentInstInputsMap; +import org.openecomp.sdc.be.model.ComponentInstListInput; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceInput; +import org.openecomp.sdc.be.model.ComponentInstancePropInput; 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.InputDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; import org.openecomp.sdc.common.log.wrappers.Logger; @@ -73,6 +83,9 @@ public class InputsBusinessLogic extends BaseBusinessLogic { private PropertyDeclarationOrchestrator propertyDeclarationOrchestrator; @Inject private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + @Inject + private DataTypeBusinessLogic dataTypeBusinessLogic; + /** * associate inputs to a given component with paging * @@ -280,7 +293,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } //Validate value and Constraint of input - Either<Boolean, ResponseFormat> constraintValidatorResponse = validateInputValueConstraint(component, inputs); + Either<Boolean, ResponseFormat> constraintValidatorResponse = validateInputValueConstraint(inputs); if (constraintValidatorResponse.isRight()) { log.error("Failed validation value and constraint of property: {}", constraintValidatorResponse.right().value()); @@ -339,8 +352,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } } - private Either<Boolean, ResponseFormat> validateInputValueConstraint( - org.openecomp.sdc.be.model.Component component, List<InputDefinition> inputs) { + private Either<Boolean, ResponseFormat> validateInputValueConstraint(List<InputDefinition> inputs) { PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil = PropertyValueConstraintValidationUtil.getInstance(); List<InputDefinition> inputDefinitions = new ArrayList<>(); @@ -408,46 +420,107 @@ public class InputsBusinessLogic extends BaseBusinessLogic { try { validateUserExists(userId, GET_PROPERTIES_BY_INPUT, false); - ComponentParametersView componentParametersView = new ComponentParametersView(); - componentParametersView.disableAll(); - componentParametersView.setIgnoreInputs(false); - componentParametersView.setIgnoreComponentInstancesInputs(false); - componentParametersView.setIgnoreComponentInstances(false); - componentParametersView.setIgnoreComponentInstancesProperties(false); - componentParametersView.setIgnorePolicies(false); - componentParametersView.setIgnoreGroups(false); - componentParametersView.setIgnoreUsers(false); + component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp); - Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(componentId, componentType, componentParametersView); + result = propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi) + .left() + .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)) + .right() + .map(componentsUtils::getResponseFormat); - if (validateComponent.isRight()) { - result = Either.right(validateComponent.right().value()); - return result; - } - component = validateComponent.left().value(); + return result; - if (shouldLockComp) { - Either<Boolean, ResponseFormat> lockComponent = lockComponent(component, CREATE_INPUT); - if (lockComponent.isRight()) { - result = Either.right(lockComponent.right().value()); - return result; + } catch (ComponentException e) { + log.error("#createMultipleInputs: Exception thrown: ", e); + result = Either.right(e.getResponseFormat()); + return result; + } finally { + + if (!inTransaction) { + if (result == null || result.isRight()) { + log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP); + titanDao.rollback(); + } else { + log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP); + titanDao.commit(); } } + // unlock resource + if (shouldLockComp && component != null) { + graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); + } - Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component, userId); - if (canWork.isRight()) { - result = Either.right(canWork.right().value()); - return result; + } + } + + /** + * Creates a list input with a data type which has properties specified. + * + * @param userId User ID + * @param componentId Component ID + * @param componentType Component type + * @param componentListInput Properties to be declared and input to be created + * @param shouldLockComp true if the component should be locked + * @param inTransaction true if already in transaction + */ + public Either<List<InputDefinition>, ResponseFormat> createListInput(String userId, String componentId, + ComponentTypeEnum componentType, ComponentInstListInput componentListInput, boolean shouldLockComp, + boolean inTransaction) { + + Either<List<InputDefinition>, ResponseFormat> result = null; + org.openecomp.sdc.be.model.Component component = null; + + log.trace("#createListInput: enter"); + + try { + /* check if user exists */ + validateUserExists(userId, GET_PROPERTIES_BY_INPUT, false); + + component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp); + + InputDefinition listInput = componentListInput.getListInput(); + DataTypeDefinition dataType = + prepareDataTypeForListInput(componentListInput.getComponentInstInputsMap(), listInput); + Map<String, DataTypeDefinition> dataTypesMap = new HashMap<>(); + dataTypesMap.put(dataType.getName(), dataType); + if (log.isDebugEnabled()) { + log.debug("#createListInput: dataTypesMap={}", ReflectionToStringBuilder.toString(dataTypesMap)); } - result = propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi) - .left() - .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)) - .right() - .map(componentsUtils::getResponseFormat); + Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypeResult = + toscaOperationFacade.addDataTypesToComponent(dataTypesMap, componentId); + if (dataTypeResult.isRight()) { + log.debug("#createListInput: DataType creation failed."); + throw new ComponentException(componentsUtils.getResponseFormat(dataTypeResult.right().value())); + } + + // create list input + listInput.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(componentId, listInput.getName())); + listInput.setInstanceUniqueId( + propertyDeclarationOrchestrator.getPropOwnerId(componentListInput.getComponentInstInputsMap())); + listInput.setIsDeclaredListInput(true); + Map<String, InputDefinition> listInputMap = new HashMap<>(); + listInputMap.put(listInput.getName(), listInput); + result = createListInputsInGraph(listInputMap, dataTypesMap, component); + if (result.isRight()) { + log.debug("#createListInput: createListInputsInGraph failed."); + throw new ComponentException(result.right().value()); + } + + // update properties + result = propertyDeclarationOrchestrator + .declarePropertiesToListInput(component, componentListInput.getComponentInstInputsMap(), listInput) + .right().map(err -> componentsUtils.getResponseFormat(err)) + .left().map(Arrays::asList); + + log.trace("#createListInput: leave"); return result; + } catch (ComponentException e) { + log.error("#createListInput: Exception thrown", e); + result = Either.right(e.getResponseFormat()); + return result; } finally { if (!inTransaction) { @@ -463,8 +536,65 @@ public class InputsBusinessLogic extends BaseBusinessLogic { if (shouldLockComp && component != null) { graphLockOperation.unlockComponent(componentId, componentType.getNodeType()); } + } + } + private ComponentParametersView getBaseComponentParametersView() { + ComponentParametersView componentParametersView = new ComponentParametersView(); + componentParametersView.disableAll(); + componentParametersView.setIgnoreInputs(false); + componentParametersView.setIgnoreComponentInstances(false); + componentParametersView.setIgnoreComponentInstancesInputs(false); + componentParametersView.setIgnoreComponentInstancesProperties(false); + componentParametersView.setIgnorePolicies(false); + componentParametersView.setIgnoreGroups(false); + componentParametersView.setIgnoreUsers(false); + return componentParametersView; + } + + private org.openecomp.sdc.be.model.Component getAndValidateComponentForCreate( + String userId, String componentId, ComponentTypeEnum componentType, boolean shouldLockComp + ) { + + ComponentParametersView componentParametersView = getBaseComponentParametersView(); + + Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither = + // get Component Object + validateComponentExists(componentId, componentType, componentParametersView) + .left().bind(component -> { + if (shouldLockComp) { + // lock the component + return lockComponent(component, CREATE_INPUT).left().map(result -> component); + } + return Either.left(component); + }).left().bind(component -> validateCanWorkOnComponent(component, userId).left().map(result -> component)); + if (componentEither.isRight()) { + throw new ComponentException(componentEither.right().value()); + } + return componentEither.left().value(); + } + + private DataTypeDefinition prepareDataTypeForListInput(ComponentInstInputsMap inputsMap, InputDefinition input) { + // Confirm if type is list + if (StringUtils.isEmpty(input.getType()) || !input.getType().equals(ToscaPropertyType.LIST.getType())) { + log.debug("#prepareDataTypeForListInput: Type of input is not list."); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE)); } + + // Confirm schema type is not empty + String desiredTypeName = input.getSchemaType(); + if (StringUtils.isEmpty(desiredTypeName)) { + log.debug("#prepareDataTypeForListInput: Schema type of list input is empty."); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE)); + } + + DataTypeDefinition dataType = new DataTypeDefinition(); + List<ComponentInstancePropInput> propInputs = inputsMap.resolvePropertiesToDeclare().getRight(); + dataType.setName(desiredTypeName); + dataType.setDerivedFromName(ToscaPropertyType.Root.getType()); + // Copy properties from inputsMap + dataType.setProperties(propInputs.stream().map(PropertyDefinition::new).collect(Collectors.toList())); + return dataType; } private Either<List<InputDefinition>, StorageOperationStatus> prepareInputsForCreation(String userId, String cmptId, List<InputDefinition> inputsToCreate) { @@ -519,6 +649,42 @@ public class InputsBusinessLogic extends BaseBusinessLogic { return Either.left(associateInputsEither.left().value()); } + private Either<List<InputDefinition>, ResponseFormat> createListInputsInGraph(Map<String, InputDefinition> inputs, + Map<String, DataTypeDefinition> privateDataTypes, org.openecomp.sdc.be.model.Component component) { + + log.trace("#createListInputsInGraph: enter"); + Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes( + applicationDataTypeCache); + if (allDataTypes.isRight()) { + return Either.right(allDataTypes.right().value()); + } + + Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); + dataTypes.putAll(privateDataTypes); + + for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) { + String inputName = inputDefinition.getKey(); + inputDefinition.getValue().setName(inputName); + + Either<InputDefinition, ResponseFormat> preparedInputEither = + prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes); + if (preparedInputEither.isRight()) { + return Either.right(preparedInputEither.right().value()); + } + } + + Either<List<InputDefinition>, StorageOperationStatus> addInputsEither = toscaOperationFacade + .addInputsToComponent(inputs, component.getUniqueId()); + if (addInputsEither.isRight()) { + log.debug("#createListInputsInGraph: Failed to create inputs under component {}. Status is {}", + component.getUniqueId(), addInputsEither.right().value()); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(addInputsEither.right().value()))); + } + log.trace("#createListInputsInGraph: leave"); + return Either.left(addInputsEither.left().value()); + } + /** * Delete input from service * @@ -536,21 +702,16 @@ public class InputsBusinessLogic extends BaseBusinessLogic { validateUserExists(userId, "Delete input", true); - ComponentParametersView componentParametersView = new ComponentParametersView(); - componentParametersView.disableAll(); - componentParametersView.setIgnoreInputs(false); - componentParametersView.setIgnoreComponentInstances(false); - componentParametersView.setIgnoreComponentInstancesInputs(false); - componentParametersView.setIgnoreComponentInstancesProperties(false); - componentParametersView.setIgnorePolicies(false); - componentParametersView.setIgnoreGroups(false); - componentParametersView.setIgnoreUsers(false); + ComponentParametersView componentParametersView = getBaseComponentParametersView(); componentParametersView.setIgnoreInterfaces(false); + componentParametersView.setIgnoreDataType(false); componentParametersView.setIgnoreProperties(false); - Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither = toscaOperationFacade.getToscaElement(componentId, componentParametersView); + Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither = + toscaOperationFacade.getToscaElement(componentId, componentParametersView); if (componentEither.isRight()) { - deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentEither.right().value()))); + deleteEither = Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(componentEither.right().value()))); return deleteEither; } org.openecomp.sdc.be.model.Component component = componentEither.left().value(); @@ -562,13 +723,15 @@ public class InputsBusinessLogic extends BaseBusinessLogic { // Get the input findAny(); if (!optionalInput.isPresent()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId)); + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId)); } InputDefinition inputForDelete = optionalInput.get(); // Lock component - Either<Boolean, ResponseFormat> lockResultEither = lockComponent(componentId, component, "deleteInput"); + Either<Boolean, ResponseFormat> lockResultEither = + lockComponent(componentId, component, "deleteInput"); if (lockResultEither.isRight()) { ResponseFormat responseFormat = lockResultEither.right().value(); deleteEither = Either.right(responseFormat); @@ -577,18 +740,29 @@ public class InputsBusinessLogic extends BaseBusinessLogic { // Delete input operations try { - StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName()); + StorageOperationStatus status = + toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName()); if (status != StorageOperationStatus.OK) { log.debug("Component id: {} delete input id: {} failed", componentId, inputId); - deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName())); + deleteEither = Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(status), component.getName())); + return deleteEither; + } + + if (BooleanUtils.isTrue(inputForDelete.getIsDeclaredListInput())){ + deleteEither = deleteListInput(componentId, inputId, component, inputForDelete, status); return deleteEither; } - StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete); + + StorageOperationStatus storageOperationStatus = + propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete); if (storageOperationStatus != StorageOperationStatus.OK) { log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId); - deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName())); + deleteEither = Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(status), component.getName())); return deleteEither; } + deleteEither = Either.left(inputForDelete); return deleteEither; } finally { @@ -603,8 +777,31 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } } - private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition, Map<String, DataTypeDefinition> dataTypes) { + private Either<InputDefinition, ResponseFormat> deleteListInput(String componentId, String inputId, + org.openecomp.sdc.be.model.Component component, + InputDefinition inputForDelete, StorageOperationStatus status) { + // the input is created by 'Declare List'. + // need to 1. undeclare properties, 2. delete input, 3. delete private data type + + StorageOperationStatus storageOperationStatus = + propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(component, inputForDelete); + if (storageOperationStatus != StorageOperationStatus.OK) { + log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(status), component.getName())); + } + Either<DataTypeDefinition, StorageOperationStatus> deleteResult = + dataTypeBusinessLogic.deletePrivateDataType(component, inputForDelete.getSchemaType()); + if (deleteResult.isRight()) { + log.debug("Component id: {} delete datatype name: {} failed", componentId, inputForDelete.getSchemaType()); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(deleteResult.right().value()), component.getName())); + } + log.trace("deleteInput: deletePrivateDataType (OK)"); + return Either.left(inputForDelete); + } + private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition, Map<String, DataTypeDefinition> dataTypes) { // validate input default values Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, dataTypes); @@ -613,24 +810,22 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } // convert property ToscaPropertyType type = getType(newInputDefinition.getType()); - if (type != null) { + if (type != null && newInputDefinition != null) { PropertyValueConverter converter = type.getConverter(); // get inner type + SchemaDefinition schema = newInputDefinition.getSchema(); String innerType = null; - if (newInputDefinition != null) { - SchemaDefinition schema = newInputDefinition.getSchema(); - if (schema != null) { - PropertyDataDefinition prop = schema.getProperty(); - if (prop != null) { - innerType = prop.getType(); - } - } - String convertedValue; - if (newInputDefinition.getDefaultValue() != null) { - convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes); - newInputDefinition.setDefaultValue(convertedValue); + if (schema != null) { + PropertyDataDefinition prop = schema.getProperty(); + if (prop != null) { + innerType = prop.getType(); } } + String convertedValue; + if (newInputDefinition.getDefaultValue() != null) { + convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes); + newInputDefinition.setDefaultValue(convertedValue); + } } return Either.left(newInputDefinition); } @@ -696,5 +891,4 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } - } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclarator.java index faeca88d60..d7b366e0a8 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclarator.java @@ -79,6 +79,16 @@ public class ComponentInstanceInputPropertyDeclarator extends DefaultPropertyDec } @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) { + List<ComponentInstanceInput> componentInstanceInputsByInputId = componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, input.getUniqueId()); + if (isEmpty(componentInstanceInputsByInputId)) { + return StorageOperationStatus.OK; + } + componentInstanceInputsByInputId.forEach(cmptInstanceInput -> prepareValueBeforeDelete(input, cmptInstanceInput, cmptInstanceInput.getPath())); + return toscaOperationFacade.updateComponentInstanceInputs(component, componentInstanceInputsByInputId.get(0).getComponentInstanceId(), componentInstanceInputsByInputId); + } + + @Override InputDefinition createInputFromProperty(String componentId, ComponentInstance propertiesOwner, String inputName, ComponentInstancePropInput propInput, PropertyDataDefinition prop) { InputDefinition inputFromProperty = super.createInputFromProperty(componentId, propertiesOwner, inputName, propInput, prop); Component propertiesOwnerNodeType = getInstanceOriginType(propertiesOwner); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java index c716e24440..973e5985f9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java @@ -70,4 +70,13 @@ public class ComponentInstancePropertyDeclarator extends DefaultPropertyDeclarat return toscaOperationFacade.updateComponentInstanceProperties(component, componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(), componentInstancePropertiesDeclaredAsInput); } + @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) { + List<ComponentInstanceProperty> componentInstancePropertiesDeclaredAsInput = componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, input.getUniqueId()); + if (CollectionUtils.isEmpty(componentInstancePropertiesDeclaredAsInput)) { + return StorageOperationStatus.OK; + } + componentInstancePropertiesDeclaredAsInput.forEach(cmptInstanceProperty -> prepareValueBeforeDelete(input, cmptInstanceProperty, cmptInstanceProperty.getPath())); + return toscaOperationFacade.updateComponentInstanceProperties(component, componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(), componentInstancePropertiesDeclaredAsInput); + } } 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 index d382499172..ae76dadbf0 100644 --- 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 @@ -110,6 +110,40 @@ public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Compo return StorageOperationStatus.OK; } + @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, + InputDefinition input) { + PropertyDefinition propertyDefinition = new PropertyDefinition(input); + + if(propertyBL.isPropertyUsedByOperation(component, propertyDefinition)) { + return StorageOperationStatus.DECLARED_INPUT_USED_BY_OPERATION; + } + + Optional<List <PropertyDefinition>> propertyToUpdateCandidate = + getDeclaredPropertiesByInputId(component, input.getUniqueId()); + + if(propertyToUpdateCandidate.isPresent()) { + List<PropertyDefinition> propertiesToUpdate = propertyToUpdateCandidate.get(); + if (!propertiesToUpdate.isEmpty()) { + return unDeclareInputs(component, input, propertiesToUpdate); + } + } + + return StorageOperationStatus.OK; + } + + private StorageOperationStatus unDeclareInputs(Component component, + InputDefinition input, + List <PropertyDefinition> propertiesToUpdate) { + for (PropertyDefinition propertyToUpdate : propertiesToUpdate) { + StorageOperationStatus storageOperationStatus = unDeclareInput(component, input, propertyToUpdate); + if (StorageOperationStatus.OK != storageOperationStatus) { + return storageOperationStatus; + } + } + return StorageOperationStatus.OK; + } + private StorageOperationStatus unDeclareInput(Component component, InputDefinition input, PropertyDefinition propertyToUpdate) { @@ -124,9 +158,34 @@ public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Compo return StorageOperationStatus.OK; } - private Optional<PropertyDefinition> getDeclaredPropertyByInputId(Component component, + 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(); + } + + private Optional<List <PropertyDefinition>> getDeclaredPropertiesByInputId(Component component, String inputId) { List<PropertyDefinition> properties = component.getProperties(); + List<PropertyDefinition> propertiesToUpdate = new ArrayList<>(); if(CollectionUtils.isEmpty(properties)) { return Optional.empty(); @@ -139,14 +198,14 @@ public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Compo } Optional<GetInputValueDataDefinition> getInputCandidate = - getInputValues.stream().filter(getInput -> getInput.getInputId().equals(inputId)) - .findAny(); + getInputValues.stream().filter(getInput -> getInput.getInputId().equals(inputId)) + .findAny(); if(getInputCandidate.isPresent()) { - return Optional.of(propertyDefinition); + propertiesToUpdate.add(propertyDefinition); } } - return Optional.empty(); + return Optional.of(propertiesToUpdate); } } 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 02b261b132..46c1c009bc 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 @@ -11,12 +11,14 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Arrays; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; import org.json.simple.JSONObject; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; @@ -45,6 +47,7 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties private final Gson gson = new Gson(); private ComponentsUtils componentsUtils; private PropertyOperation propertyOperation; + private static final String GET_INPUT_INDEX = "INDEX"; public DefaultPropertyDeclarator(ComponentsUtils componentsUtils, PropertyOperation propertyOperation) { this.componentsUtils = componentsUtils; @@ -75,7 +78,17 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties return resolvePropertiesOwner(component, propertiesOwnerId) .map(propertyOwner -> declarePropertiesAsPolicies(component, propertyOwner, propsToDeclare)) .orElse(Either.right(onPropertiesOwnerNotFound(component.getUniqueId(), propertiesOwnerId))); + } + @Override + public Either<InputDefinition, StorageOperationStatus> declarePropertiesAsListInput(Component component, String propertiesOwnerId, List<ComponentInstancePropInput> propsToDeclare, InputDefinition input) { + log.debug("#declarePropertiesAsListInput - declaring properties as inputs for component {} from properties owner {}", component.getUniqueId(), propertiesOwnerId); + Optional<PROPERTYOWNER> propertyOwner = resolvePropertiesOwner(component, propertiesOwnerId); + if (propertyOwner.isPresent()) { + return declarePropertiesAsListInput(component, propertyOwner.get(), propsToDeclare, input); + } else { + return Either.right(onPropertiesOwnerNotFound(component.getUniqueId(), propertiesOwnerId)); + } } public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policy) { @@ -130,12 +143,12 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties } private void changePropertyValueToGetPolicy(PropertyDataDefinition prop, PolicyDefinition policyDefinition) { - JSONObject jobject = new JSONObject(); + JSONObject jsonObject = new JSONObject(); String origValue = Objects.isNull(prop.getValue()) ? prop.getDefaultValue() : prop.getValue(); - jobject.put(GET_POLICY, null); - prop.setValue(jobject.toJSONString()); - policyDefinition.setValue(jobject.toJSONString()); + jsonObject.put(GET_POLICY, null); + prop.setValue(jsonObject.toJSONString()); + policyDefinition.setValue(jsonObject.toJSONString()); if(CollectionUtils.isEmpty(prop.getGetPolicyValues())){ prop.setGetPolicyValues(new ArrayList<>()); @@ -155,6 +168,39 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties } + private Either<InputDefinition, StorageOperationStatus> declarePropertiesAsListInput(Component component, PROPERTYOWNER propertiesOwner, List<ComponentInstancePropInput> propsToDeclare, InputDefinition input) { + List<PROPERTYTYPE> declaredProperties = new ArrayList<>(); + for (ComponentInstancePropInput propInput : propsToDeclare) { + if (StringUtils.isNotEmpty(propInput.getPropertiesName()) && propInput.getInput() != null) { + // sub-property in complex type is checked on UI. currently not supported. + log.debug("skip propInput (propertiesName={}) currently not supported.", propInput.getPropertiesName()); + continue; + } + PROPERTYTYPE declaredProperty = createDeclaredProperty(propInput); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put(GET_INPUT, Arrays.asList(input.getName(), GET_INPUT_INDEX, propInput.getName())); + declaredProperty.setValue(jsonObject.toJSONString()); + + GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition(); + getInputValueDataDefinition.setInputId(input.getUniqueId()); + getInputValueDataDefinition.setInputName(input.getName()); + List<GetInputValueDataDefinition> getInputValues = declaredProperty.getGetInputValues(); + if (getInputValues == null) { + getInputValues = new ArrayList<>(); + declaredProperty.setGetInputValues(getInputValues); + } + getInputValues.add(getInputValueDataDefinition); + + if (!declaredProperties.contains(declaredProperty)) { + // Add property to the list if not contain in declareProperties. + declaredProperties.add(declaredProperty); + } + } + return updatePropertiesValues(component, propertiesOwner.getUniqueId(), declaredProperties) + .left().map(x -> input); + } + private PropertiesDeclarationData createInputsAndOverridePropertiesValues(String componentId, PROPERTYOWNER propertiesOwner, List<ComponentInstancePropInput> propsToDeclare) { List<PROPERTYTYPE> declaredProperties = new ArrayList<>(); List<InputDefinition> createdInputs = propsToDeclare.stream() @@ -182,6 +228,7 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties generatedInputPrefix = null; } String generatedInputName = generateInputName(generatedInputPrefix, propInput); + log.debug("createInput: propOwner.uniqueId={}, propInput.parentUniqueId={}", propertiesOwner.getUniqueId(), propInput.getParentUniqueId()); return createInputFromProperty(componentId, propertiesOwner, generatedInputName, propInput, prop); } @@ -266,18 +313,18 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties } private void changePropertyValueToGetInputValue(String inputName, String[] parsedPropNames, InputDefinition input, PropertyDataDefinition prop, boolean complexProperty) { - JSONObject jobject = new JSONObject(); + JSONObject jsonObject = new JSONObject(); String value = prop.getValue(); if(value == null || value.isEmpty()){ if(complexProperty){ - jobject = createJSONValueForProperty(parsedPropNames.length -1, parsedPropNames, jobject, inputName); - prop.setValue(jobject.toJSONString()); + jsonObject = createJSONValueForProperty(parsedPropNames.length -1, parsedPropNames, jsonObject, inputName); + prop.setValue(jsonObject.toJSONString()); }else{ - jobject.put(GET_INPUT, input.getName()); - prop.setValue(jobject.toJSONString()); + jsonObject.put(GET_INPUT, input.getName()); + prop.setValue(jsonObject.toJSONString()); } @@ -286,8 +333,8 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties Object objValue = new Yaml().load(value); if( objValue instanceof Map || objValue instanceof List){ if(!complexProperty){ - jobject.put(GET_INPUT, input.getName()); - prop.setValue(jobject.toJSONString()); + jsonObject.put(GET_INPUT, input.getName()); + prop.setValue(jsonObject.toJSONString()); }else{ @@ -300,14 +347,13 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties } }else{ - jobject.put(GET_INPUT, input.getName()); - prop.setValue(jobject.toJSONString()); + jsonObject.put(GET_INPUT, input.getName()); + prop.setValue(jsonObject.toJSONString()); } } - if(CollectionUtils.isEmpty(prop.getGetInputValues())){ prop.setGetInputValues(new ArrayList<>()); } @@ -453,6 +499,9 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties } else if (value instanceof Map) { Map<String, Object> subMap = (Map<String, Object>)value; resetInputName(subMap, inputName); + } else if (value instanceof List && ((List) value).contains(inputName) && key.equals(GET_INPUT)) { + value = ""; + lhm1.remove(key); } else { continue; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclarator.java index 46ca85c585..f9ef479ab0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclarator.java @@ -89,6 +89,13 @@ public class GroupPropertyDeclarator extends DefaultPropertyDeclarator<GroupDefi .orElse(StorageOperationStatus.OK); } + @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputForDelete) { + return getGroupPropertiesDeclaredAsInput(component, inputForDelete.getUniqueId()) + .map(groupProperties -> unDeclareGroupProperties(component, inputForDelete, groupProperties)) + .orElse(StorageOperationStatus.OK); + } + private StorageOperationStatus unDeclareGroupProperties(Component container, InputDefinition input, GroupProperties groupProperties) { String groupId = groupProperties.getGroupId(); List<PropertyDataDefinition> propsDeclaredAsInput = groupProperties.getProperties(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclarator.java index f7f4a75be1..17059104ff 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclarator.java @@ -87,6 +87,13 @@ public class PolicyPropertyDeclarator extends DefaultPropertyDeclarator<PolicyDe .orElse(StorageOperationStatus.OK); } + @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputForDelete) { + return getPolicyPropertiesDeclaredAsInput(component, inputForDelete.getUniqueId()) + .map(policyProperties -> unDeclarePolicyProperties(component, inputForDelete, policyProperties)) + .orElse(StorageOperationStatus.OK); + } + private StorageOperationStatus unDeclarePolicyProperties(Component container, InputDefinition input, PolicyProperties policyProperties) { String policyId = policyProperties.getPolicyId(); List<PropertyDataDefinition> propsDeclaredAsInput = policyProperties.getProperties(); 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 3a32559dda..a6c752d689 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 @@ -58,6 +58,20 @@ public class PropertyDeclarationOrchestrator { return propertyDeclarator.declarePropertiesAsPolicies(component, propsToDeclare.getLeft(), propsToDeclare.getRight()); } + /** + * + * @param component + * @param componentInstInputsMap + * @param input + * @return + */ + public Either<InputDefinition, StorageOperationStatus> declarePropertiesToListInput(Component component, ComponentInstInputsMap componentInstInputsMap, InputDefinition input) { + PropertyDeclarator propertyDeclarator = getPropertyDeclarator(componentInstInputsMap); + Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare(); + log.debug("#declarePropertiesToInputs: componentId={}, propOwnerId={}", component.getUniqueId(), propsToDeclare.getLeft()); + return propertyDeclarator.declarePropertiesAsListInput(component, propsToDeclare.getLeft(), propsToDeclare.getRight(), input); + } + public StorageOperationStatus unDeclarePropertiesAsInputs(Component component, InputDefinition inputToDelete) { log.debug("#unDeclarePropertiesAsInputs - removing input declaration for input {} on component {}", inputToDelete.getName(), component.getUniqueId()); for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToInput) { @@ -70,6 +84,36 @@ public class PropertyDeclarationOrchestrator { return StorageOperationStatus.OK; } + /** + * Un declare properties declared as list type input + * + * @param component + * @param inputToDelete + * @return + */ + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputToDelete) { + log.debug("#unDeclarePropertiesAsListInputs - removing input declaration for input {} on component {}", inputToDelete.getName(), component.getUniqueId()); + for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToInput) { + StorageOperationStatus storageOperationStatus = propertyDeclarator.unDeclarePropertiesAsListInputs(component, inputToDelete); + if (StorageOperationStatus.OK != storageOperationStatus) { + log.debug("#unDeclarePropertiesAsListInputs - failed to remove input declaration for input {} on component {}. reason {}", inputToDelete.getName(), component.getUniqueId(), storageOperationStatus); + return storageOperationStatus; + } + } + return StorageOperationStatus.OK; + + } + + /** + * Get properties owner id + * + * @param componentInstInputsMap + * @return + */ + public String getPropOwnerId(ComponentInstInputsMap componentInstInputsMap) { + Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare(); + return propsToDeclare.getLeft(); + } public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policyToDelete) { log.debug("#unDeclarePropertiesAsInputs - removing policy declaration for input {} on component {}", policyToDelete diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarator.java index c0f76288b2..b8b6c6eb62 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarator.java @@ -44,4 +44,21 @@ public interface PropertyDeclarator { */ StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policy); + /** + * Updates given list of properties to get values from the specified "list input" with get_input function. + * This function does NOT create "list input", it needs to be created separately. + * @param component the container + * @param propertiesOwnerId the id of the owner of the properties to declare (e.g ComponentInstance, Policy, Group etc) + * @param propsToDeclare the list of properties that are being declared as inputs + * @param input the input from which properties get values + * @return the input same as passed one at 4th argument + */ + Either<InputDefinition, StorageOperationStatus> declarePropertiesAsListInput(Component component, String propertiesOwnerId, List<ComponentInstancePropInput> propsToDeclare, InputDefinition input); + + /** + * Un declare properties declared as list type input + * @param component the container of the input to be deleted + * @param input the input to be deleted + */ + StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentInstancePropertyToPolicyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentInstancePropertyToPolicyDeclarator.java index bbbdf6f105..2726f67342 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentInstancePropertyToPolicyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentInstancePropertyToPolicyDeclarator.java @@ -65,6 +65,11 @@ public class ComponentInstancePropertyToPolicyDeclarator extends } @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) { + return StorageOperationStatus.OK; + } + + @Override public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policy) { Optional<ComponentInstanceProperty> propertyCandidate = diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentPropertyToPolicyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentPropertyToPolicyDeclarator.java index 1d73786938..6bd09c1622 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentPropertyToPolicyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentPropertyToPolicyDeclarator.java @@ -65,9 +65,14 @@ public class ComponentPropertyToPolicyDeclarator extends DefaultPropertyDeclarat } @Override + public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) { + // no need for implementation since we are in a policy scenario + return StorageOperationStatus.OK; + } + + @Override public void addPropertiesListToInput(PropertyDataDefinition declaredProp, InputDefinition input) { // no need for implementation since we are in a policy scenario - return; } @Override diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java index 7da6533570..9f77c5150a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java @@ -44,10 +44,15 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.openecomp.sdc.be.components.impl.DataTypeBusinessLogic; import org.openecomp.sdc.be.components.impl.InputsBusinessLogic; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.datatypes.enums.DeclarationTypeEnum; import org.openecomp.sdc.be.model.ComponentInstInputsMap; import org.openecomp.sdc.be.model.ComponentInstanceInput; @@ -55,10 +60,13 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.ComponentInstListInput; +import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; 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; @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Api(value = "Input Catalog", description = "Input Servlet") @@ -256,6 +264,14 @@ public class InputsServlet extends AbstractValidationsServlet { } } + private Either<ComponentInstInputsMap, ResponseFormat> parseToComponentInstanceMap(String serviceJson, User user) { + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, ComponentInstInputsMap.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + } + + private Either<ComponentInstListInput, ResponseFormat> parseToComponentInstListInput(String json, User user) { + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(json, user, ComponentInstListInput.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + } + @POST @Path("/{componentType}/{componentId}/create/inputs") @ApiOperation(value = "Create inputs on service", httpMethod = "POST", notes = "Return inputs list", response = Resource.class) @@ -268,6 +284,71 @@ public class InputsServlet extends AbstractValidationsServlet { } + /** + * Creates a "list input" and updates given list of properties to get value from the input. + * also a data type which has same properties is created. + * the data type will be the entry_schema of the list input. + * @param componentType the container type (service, resource, ...) + * @param componentId the container ID + * @param request HttpServletRequest object + * @param userId the User ID + * @param componentInstInputsMapObj the list of properties to be declared and the "list input" to be created. + * the type of the input must be "list". + * schema.type of the input will be the name of new data type. + * @return the created input + */ + @POST + @Path("/{componentType}/{componentId}/create/listInput") + @ApiOperation(value = "Create a list input on service", httpMethod = "POST", notes = "Return input", response = Resource.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "Component found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Component not found") }) + public Response createListInput(@PathParam("componentType") final String componentType, @PathParam("componentId") final String componentId, @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @ApiParam(value = "ComponentIns Inputs Object to be created", required = true) String componentInstInputsMapObj) { + + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("#createListInput: Start handle request of {}", url); + Response response = null; + + try { + InputsBusinessLogic businessLogic = getInputBL(context); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); + + Either<ComponentInstListInput, ResponseFormat> componentInstInputsMapRes = + parseToComponentInstListInput(componentInstInputsMapObj, modifier); + if (componentInstInputsMapRes.isRight()) { + log.debug("failed to parse componentInstInputsMap"); + response = buildErrorResponse(componentInstInputsMapRes.right().value()); + return response; + } + + ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType); + ComponentInstListInput componentInstInputsMap = componentInstInputsMapRes.left().value(); + if (log.isDebugEnabled()) { + // for inspection on debug + log.debug("parsed componentInstInputsMap={}", ReflectionToStringBuilder.toString(componentInstInputsMap)); + } + + Either<List<InputDefinition>, ResponseFormat> inputPropertiesRes = businessLogic.createListInput( + userId, componentId, componentTypeEnum, componentInstInputsMap, true, false); + if (inputPropertiesRes.isRight()) { + log.debug("failed to create list input for service: {}", componentId); + return buildErrorResponse(inputPropertiesRes.right().value()); + } + Object properties = RepresentationUtils.toRepresentation(inputPropertiesRes.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), properties); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create list input for service with id: " + componentId); + log.debug("createListInput failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } + @DELETE @Path("/{componentType}/{componentId}/delete/{inputId}/input") @@ -304,4 +385,142 @@ public class InputsServlet extends AbstractValidationsServlet { } } + /** + * Gets a specific data type associated with a component. + * @param componentType the container type (service, resource, ...) + * @param componentId the container ID + * @param dataTypeName the data type name + * @param request HttpServletRequest object + * @return the data type info + */ + @GET + @Path("/{componentType}/{componentId}/dataType/{dataTypeName}") + @ApiOperation(value = "Get data type in service", httpMethod = "GET", notes = "Get data type in service", + response = DataTypeDefinition.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Data type found"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 404, message = "Data type not found")}) + public Response getDataType( + @PathParam("componentType") final String componentType, + @PathParam("componentId") final String componentId, + @PathParam("dataTypeName") final String dataTypeName, + @Context final HttpServletRequest request + ) { + ServletContext context = request.getSession().getServletContext(); + ComponentsUtils componentsUtils = getComponentsUtils(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("(getDataType) Start handle request of {}", url); + Response response; + + try { + DataTypeBusinessLogic businessLogic = getDataTypeBL(context); + Either<DataTypeDefinition, StorageOperationStatus> getResult = businessLogic.getPrivateDataType(componentId, dataTypeName); + if (getResult.isRight()) { + ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getResult.right().value()); + return buildErrorResponse(componentsUtils.getResponseFormat(actionStatus)); + } + Object json = RepresentationUtils.toRepresentation(getResult.left().value()); + return buildOkResponse(componentsUtils.getResponseFormat(ActionStatus.OK), json); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get data type from service + " + componentId + " + with name: " + dataTypeName); + log.debug("Get data type failed with exception", e); + response = buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } + + /** + * Gets a list of data types which a component has. + * @param componentType the container type (service, resource, ...) + * @param componentId the container ID + * @param request HttpServletRequest object + * @return the list of data types in the component + */ + @GET + @Path("/{componentType}/{componentId}/dataTypes") + @ApiOperation(value = "Get data types that service has", httpMethod = "GET", notes = "Get data types in service", + response = Resource.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Data type found"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 404, message = "Component not found")}) + public Response getDataTypes( + @PathParam("componentType") final String componentType, + @PathParam("componentId") final String componentId, + @Context final HttpServletRequest request + ) { + ServletContext context = request.getSession().getServletContext(); + ComponentsUtils componentsUtils = getComponentsUtils(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("(getDataType) Start handle request of {}", url); + Response response; + + try { + DataTypeBusinessLogic businessLogic = getDataTypeBL(context); + Either<List<DataTypeDefinition>, StorageOperationStatus> getResult = businessLogic.getPrivateDataTypes(componentId); + if (getResult.isRight()) { + ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getResult.right().value()); + return buildErrorResponse(componentsUtils.getResponseFormat(actionStatus)); + } + Object json = RepresentationUtils.toRepresentation(getResult.left().value()); + return buildOkResponse(componentsUtils.getResponseFormat(ActionStatus.OK), json); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get data type from service + " + componentId); + log.debug("Get data type failed with exception", e); + response = buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } + + /** + * Deletes a data type from a component. + * @param componentType the container type (service, resource, ...) + * @param componentId the container ID + * @param dataTypeName the data type name to be deleted + * @param request HttpServletRequest object + * @return operation result + */ + @DELETE + @Path("/{componentType}/{componentId}/dataType/{dataTypeName}") + @ApiOperation(value = "Delete data type from service", httpMethod = "DELETE", notes = "Delete service input", + response = Resource.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Data type deleted"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 404, message = "Data type not found")}) + public Response deleteDataType( + @PathParam("componentType") final String componentType, + @PathParam("componentId") final String componentId, + @PathParam("dataTypeName") final String dataTypeName, + @Context final HttpServletRequest request + ) { + ServletContext context = request.getSession().getServletContext(); + ComponentsUtils componentsUtils = getComponentsUtils(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("(get) Start handle request of {}", url); + Response response; + + try { + DataTypeBusinessLogic businessLogic = getDataTypeBL(context); + Either<DataTypeDefinition, StorageOperationStatus> deleteResult = businessLogic.deletePrivateDataType(componentId, dataTypeName); + if (deleteResult.isRight()) { + ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(deleteResult.right().value()); + return buildErrorResponse(componentsUtils.getResponseFormat(actionStatus)); + } + Object json = RepresentationUtils.toRepresentation(deleteResult.left().value()); + return buildOkResponse(componentsUtils.getResponseFormat(ActionStatus.OK), json); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete data type for service + " + componentId + " + with name: " + dataTypeName); + log.debug("Delete data type failed with exception", e); + response = buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } + + private DataTypeBusinessLogic getDataTypeBL(ServletContext context) { + WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); + WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); + return webApplicationContext.getBean(DataTypeBusinessLogic.class); + } } 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 405db5a465..baf5b30267 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 @@ -22,6 +22,7 @@ package org.openecomp.sdc.be.tosca; import com.google.gson.Gson; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; import fj.data.Either; @@ -32,6 +33,7 @@ import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.tosca.ToscaFunctions; 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; @@ -185,25 +187,31 @@ public class PropertyConvertor { log.trace("It's well defined type. convert it"); ToscaValueConverter converter = type.getValueConverter(); return converter.convertToToscaValue(value, innerType, dataTypes); - } else { - log.trace("It's data type or inputs in primitive type. convert as map"); - Object convertedValue; - if (innerConverter != null && (ToscaPropertyType.MAP.equals(type) || ToscaPropertyType.LIST.equals(type))) { - convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes); - } else { - if (isScalar) { - // complex json for scalar type - convertedValue = mapConverterInst.handleComplexJsonValue(jsonElement); - } else { - if (innerConverter != null) { - convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes); - } else { - convertedValue = mapConverterInst.convertDataTypeToToscaObject(innerType, dataTypes, innerConverter, isScalar, jsonElement, preserveEmptyValue); - } - } + } + log.trace("It's data type or inputs in primitive type. convert as map"); + if (jsonElement.isJsonObject()) { + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // check if value is a get_input function + if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) { + Object obj = mapConverterInst.handleComplexJsonValue(jsonElement); + log.debug("It's get_input function. obj={}", obj); + return obj; } - return convertedValue; } + Object convertedValue; + if (innerConverter != null && (ToscaPropertyType.MAP.equals(type) || ToscaPropertyType.LIST.equals(type))) { + convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes); + } else if (isScalar) { + // complex json for scalar type + convertedValue = mapConverterInst.handleComplexJsonValue(jsonElement); + } else if (innerConverter != null) { + convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes); + } else { + convertedValue = mapConverterInst.convertDataTypeToToscaObject( + innerType, dataTypes, innerConverter, isScalar, jsonElement, preserveEmptyValue); + } + + return convertedValue; } catch (Exception e) { log.debug("convertToToscaValue failed to parse json value :", e); 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 54cf4cf096..65451e9dc5 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 @@ -76,7 +76,6 @@ import java.util.stream.Collectors; 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; @@ -313,6 +312,7 @@ public class ToscaExportHandler { topologyTemplate.setSubstitution_mappings(substitutionMapping); toscaNode.setTopology_template(topologyTemplate); + return Either.left(toscaNode); } @@ -560,6 +560,30 @@ public class ToscaExportHandler { resolveDefaultPropertyValue(inputDef, mergedProperties, dataTypes); toscaNodeType.setProperties(mergedProperties); } + + /* convert private data_types */ + List<DataTypeDefinition> privateDataTypes = component.getDataTypes(); + if (CollectionUtils.isNotEmpty(privateDataTypes) ) { + Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>(); + for (DataTypeDefinition dataType: privateDataTypes) { + log.debug("Emitting private data type: component.name={} dataType.name={}", + component.getNormalizedName(), dataType.getName()); + ToscaDataType toscaDataType = new ToscaDataType(); + toscaDataType.setDerived_from(dataType.getDerivedFromName()); + toscaDataType.setDescription(dataType.getDescription()); + toscaDataType.setVersion(dataType.getVersion()); + if (CollectionUtils.isNotEmpty(dataType.getProperties())) { + toscaDataType.setProperties(dataType.getProperties().stream() + .collect(Collectors.toMap( + s -> s.getName(), + s -> propertyConvertor.convertProperty(dataTypes, s, PropertyConvertor.PropertyType.PROPERTY) + ))); + } + toscaDataTypeMap.put(dataType.getName(), toscaDataType); + } + toscaNode.setData_types(toscaDataTypeMap); + } + // Extracted to method for code reuse return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes); } @@ -570,17 +594,30 @@ public class ToscaExportHandler { for (Map.Entry<String, ToscaProperty> mergedPropertyEntry : mergedProperties.entrySet()) { ToscaProperty value = mergedPropertyEntry.getValue(); if (Objects.nonNull(value) && value.getDefaultp() instanceof Map) { - Map<String, String> valueAsMap = (Map<String, String>) value.getDefaultp(); - String inputName = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName()); - Optional<InputDefinition> matchedInputDefinition = inputDef.stream() - .filter(componentInput -> componentInput.getName().equals(inputName)) - .findFirst(); - if (matchedInputDefinition.isPresent()) { - InputDefinition matchedInput = matchedInputDefinition.get(); - Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(), - matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false); - value.setDefaultp(resolvedDefaultValue); - mergedProperties.put(mergedPropertyEntry.getKey(), value); + Map<String, Object> valueAsMap = (Map<String, Object>) value.getDefaultp(); + Object getInputValue = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName()); + if (getInputValue instanceof String) { + String inputName = (String)getInputValue; + Optional<InputDefinition> matchedInputDefinition = inputDef.stream() + .filter(componentInput -> componentInput.getName().equals(inputName)) + .findFirst(); + if (matchedInputDefinition.isPresent()) { + InputDefinition matchedInput = matchedInputDefinition.get(); + Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(), + matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false); + value.setDefaultp(resolvedDefaultValue); + mergedProperties.put(mergedPropertyEntry.getKey(), value); + } + } else if (getInputValue instanceof List) { + // new get_input syntax to refer to sub-element (introduced from TOSCA v1.3) + // e.g. get_input: [input_name, INDEX, inner_property] + // currently resolving default value for the syntax is not supported + log.debug("#resolveDefaultPropertyValue: ignore get_input list syntax. propname={}, val={}", + mergedPropertyEntry.getKey(), getInputValue); + } else { + // Ignore unknown get_input syntax + log.debug("#resolveDefaultPropertyValue: ignore unknown get_input syntax. propname={}, val={}", + mergedPropertyEntry.getKey(), getInputValue); } } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaDataType.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaDataType.java new file mode 100644 index 0000000000..8a4ec7c301 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaDataType.java @@ -0,0 +1,126 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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.tosca.model; + +import java.util.Map; + +/** + * Represents a data type (in data_types in TOSCA model). + */ +public class ToscaDataType { + + private String derived_from; + private String version; + private Map<String, String> metadata; + private String description; + //private List<ToscaConstraint> constraints; + private Map<String, ToscaProperty> properties; + + /** + * Gets derived_from. + * + * @return Current derived_from value. + */ + public String getDerived_from() { + return derived_from; + } + + /** + * Sets derived_from. + * + * @param derived_from New derived_from value. + */ + public void setDerived_from(String derived_from) { + this.derived_from = derived_from; + } + + /** + * Gets version. + * + * @return Current version value. + */ + public String getVersion() { + return version; + } + + /** + * Sets version. + * + * @param version New version value. + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Gets metadata map. + * + * @return Current metadata map. + */ + public Map<String, String> getMetadata() { + return metadata; + } + + /** + * Sets metadata map. + * + * @param metadata New metadata map. + */ + public void setMetadata(Map<String, String> metadata) { + this.metadata = metadata; + } + + /** + * Gets description. + * + * @return Current description value. + */ + public String getDescription() { + return description; + } + + /** + * Sets description. + * + * @param description New description value. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Gets properties map. + * + * @return Current properties map. + */ + public Map<String, ToscaProperty> getProperties() { + return properties; + } + + /** + * Sets properties map. + * + * @param properties New properties map. + */ + public void setProperties(Map<String, ToscaProperty> properties) { + this.properties = properties; + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java index 65a6dbf282..742e8bb233 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java @@ -32,6 +32,7 @@ public class ToscaTemplate { private ToscaMetadata metadata; private List<Map<String, Map<String, String>>> imports; private Map<String, Object> interface_types; + private Map<String, ToscaDataType> data_types; private Map<String, ToscaNodeType> node_types; private ToscaTopolgyTemplate topology_template; @@ -102,5 +103,21 @@ public class ToscaTemplate { this.interface_types = interface_types; } + + /** + * Gets data_types map. + * @return Current data_types map. + */ + public Map<String, ToscaDataType> getData_types() { + return data_types; + } + + /** + * Sets data_types map. + * @param data_types New data_types map. + */ + public void setData_types(Map<String, ToscaDataType> data_types) { + this.data_types = data_types; + } } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogicTest.java new file mode 100644 index 0000000000..9219de1aac --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogicTest.java @@ -0,0 +1,156 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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.components.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import fj.data.Either; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.validation.UserValidations; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.user.IUserBusinessLogic; + +public class DataTypeBusinessLogicTest { + + private static final String COMPONENT_INSTANCE_ID = "instanceId"; + private static final String COMPONENT_ID = "componentId"; + private static final String USER_ID = "userId"; + private static final String INSTANCE_INPUT_ID = "inputId"; + private static final String DATATYPE_NAME = "org.onap.datatypes.mytype"; + + @Mock + private ComponentsUtils componentsUtilsMock; + + @Mock + private IUserBusinessLogic userAdminMock; + + @Mock + private ToscaOperationFacade toscaOperationFacadeMock; + + @Mock + private UserValidations userValidations; + + @Mock + private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + + @InjectMocks + private DataTypeBusinessLogic testInstance; + + private Service service; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + service = new Service(); + service.setUniqueId(COMPONENT_INSTANCE_ID); + ComponentInstance componentInstance = new ComponentInstance(); + componentInstance.setUniqueId(COMPONENT_INSTANCE_ID); + service.setComponentInstances(Collections.singletonList(componentInstance)); + DataTypeDefinition dataType = new DataTypeDefinition(); + dataType.setName(DATATYPE_NAME); + dataType.setDerivedFromName(ToscaPropertyType.Root.getType()); + List<DataTypeDefinition> dataTypes = Arrays.asList(dataType); + service.setDataTypes(dataTypes); + + Map<String, List<ComponentInstanceInput>> instanceInputMap = new HashMap<>(); + ComponentInstanceInput componentInstanceInput = new ComponentInstanceInput(); + componentInstanceInput.setInputId(INSTANCE_INPUT_ID); + instanceInputMap.put(COMPONENT_INSTANCE_ID, Collections.singletonList(componentInstanceInput)); + instanceInputMap.put("someInputId", Collections.singletonList(new ComponentInstanceInput())); + service.setComponentInstancesInputs(instanceInputMap); + when(userValidations.validateUserExists(eq(USER_ID), anyString(), eq(false))).thenReturn(new User()); + when(userAdminMock.getUser(USER_ID, false)).thenReturn(Either.left(new User())); + } + + @Test + public void test_getPrivateDataTypes() throws Exception { + setMockitoWhenGetToscaElementCalled(); + + Either<List<DataTypeDefinition>, StorageOperationStatus> result = testInstance.getPrivateDataTypes(COMPONENT_ID); + assertTrue(result.isLeft()); + List<DataTypeDefinition> dataTypes = result.left().value(); + assertEquals(service.getDataTypes(), dataTypes); + } + + @Test + public void test_getPrivateDataType() throws Exception { + setMockitoWhenGetToscaElementCalled(); + + Either<DataTypeDefinition, StorageOperationStatus> result = + testInstance.getPrivateDataType(COMPONENT_ID, DATATYPE_NAME); + assertTrue(result.isLeft()); + DataTypeDefinition dataType = result.left().value(); + assertEquals(service.getDataTypes().get(0), dataType); + } + + @Test + public void test_deletePrivateDataType1() throws Exception { + setMockitoWhenGetToscaElementCalled(); + when(toscaOperationFacadeMock.deleteDataTypeOfComponent(service, DATATYPE_NAME)) + .thenReturn(StorageOperationStatus.OK); + + Either<DataTypeDefinition, StorageOperationStatus> result = + testInstance.deletePrivateDataType(COMPONENT_ID, DATATYPE_NAME); + assertTrue(result.isLeft()); + DataTypeDefinition dataType = result.left().value(); + assertEquals(service.getDataTypes().get(0), dataType); + } + + @Test + public void test_deletePrivateDataType2() throws Exception { + when(toscaOperationFacadeMock.deleteDataTypeOfComponent(service, DATATYPE_NAME)) + .thenReturn(StorageOperationStatus.OK); + + Either<DataTypeDefinition, StorageOperationStatus> result = + testInstance.deletePrivateDataType(service, DATATYPE_NAME); + assertTrue(result.isLeft()); + DataTypeDefinition dataType = result.left().value(); + assertEquals(service.getDataTypes().get(0), dataType); + } + + private void setMockitoWhenGetToscaElementCalled() { + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java index 2ef3d463eb..b306b2ad72 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java @@ -21,18 +21,31 @@ package org.openecomp.sdc.be.components.impl; import fj.data.Either; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator; +import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder; import org.openecomp.sdc.be.components.validation.UserValidations; import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; import org.openecomp.sdc.be.user.IUserBusinessLogic; import org.openecomp.sdc.exception.ResponseFormat; @@ -40,9 +53,9 @@ import java.util.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyObject; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class InputsBusinessLogicTest { @@ -50,7 +63,13 @@ public class InputsBusinessLogicTest { private static final String COMPONENT_INSTANCE_ID = "instanceId"; private static final String COMPONENT_ID = "componentId"; private static final String USER_ID = "userId"; - public static final String INSTANCE_INPUT_ID = "inputId"; + private static final String INSTANCE_INPUT_ID = "inputId"; + private static final String LISTINPUT_NAME = "listInput"; + private static final String LISTINPUT_SCHEMA_TYPE = "org.onap.datatypes.listinput"; + private static final String LISTINPUT_PROP1_NAME = "prop1"; + private static final String LISTINPUT_PROP1_TYPE = "string"; + private static final String LISTINPUT_PROP2_NAME = "prop2"; + private static final String LISTINPUT_PROP2_TYPE = "integer"; @Mock private ComponentsUtils componentsUtilsMock; @@ -67,26 +86,54 @@ public class InputsBusinessLogicTest { @Mock private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + @Mock + private IGraphLockOperation graphLockOperation; + + @Mock + private PropertyDeclarationOrchestrator propertyDeclarationOrchestrator; + + @Mock + private ApplicationDataTypeCache applicationDataTypeCache; + + @Mock + private PropertyOperation propertyOperation; + + @Mock + private TitanDao titanDao; + + @Mock + private DataTypeBusinessLogic dataTypeBusinessLogic; + @InjectMocks private InputsBusinessLogic testInstance; private Service service; + @Captor + ArgumentCaptor<Map<String, DataTypeDefinition>> dataTypesMapCaptor; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); service = new Service(); - service.setUniqueId(COMPONENT_INSTANCE_ID); + service.setUniqueId(COMPONENT_ID); + service.setLastUpdaterUserId(USER_ID); + service.setIsDeleted(false); + service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + + // add a ComponentInstance ComponentInstance componentInstance = new ComponentInstance(); componentInstance.setUniqueId(COMPONENT_INSTANCE_ID); service.setComponentInstances(Collections.singletonList(componentInstance)); + // add inputs to the ComponentInstance Map<String, List<ComponentInstanceInput>> instanceInputMap = new HashMap<>(); ComponentInstanceInput componentInstanceInput = new ComponentInstanceInput(); componentInstanceInput.setInputId(INSTANCE_INPUT_ID); instanceInputMap.put(COMPONENT_INSTANCE_ID, Collections.singletonList(componentInstanceInput)); instanceInputMap.put("someInputId", Collections.singletonList(new ComponentInstanceInput())); service.setComponentInstancesInputs(instanceInputMap); + when(userValidations.validateUserExists(eq(USER_ID), anyString(), eq(false))).thenReturn(new User()); when(userAdminMock.getUser(USER_ID, false)).thenReturn(Either.left(new User())); } @@ -96,7 +143,7 @@ public class InputsBusinessLogicTest { when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service)); Either<List<ComponentInstanceInput>, ResponseFormat> componentInstanceInputs = testInstance.getComponentInstanceInputs(USER_ID, COMPONENT_ID, "nonExisting"); assertTrue(componentInstanceInputs.isRight()); - Mockito.verify(componentsUtilsMock).getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND); + verify(componentsUtilsMock).getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND); } @Test @@ -263,4 +310,321 @@ public class InputsBusinessLogicTest { Either<List<ComponentInstanceInput>, ResponseFormat> result = testInstance.getInputsForComponentInput("USR01", COMPONENT_ID,"INPO1"); assertEquals(true,result.isLeft()); } + + + private InputDefinition setUpListInput() { + InputDefinition listInput = new InputDefinition(); + listInput.setName(LISTINPUT_NAME); + listInput.setType("list"); + SchemaDefinition listInputSchema = new SchemaDefinition(); + listInputSchema.setProperty(new PropertyDataDefinitionBuilder() + .setType(LISTINPUT_SCHEMA_TYPE) + .setIsRequired(false) + .build() + ); + listInput.setSchema(listInputSchema); + return listInput; + } + + private ComponentInstListInput setUpCreateListInputParams() { + ComponentInstListInput componentInstListInput = new ComponentInstListInput(); + + // Create a "list input" + InputDefinition listInput = setUpListInput(); + componentInstListInput.setListInput(listInput); + + // Create ComponentInstancePropInputs + // for inputs in the ComponentInstance + Map<String, List<ComponentInstancePropInput>> propInputsListMap = new HashMap<>(); + // Add 2 PropInputs. property owner is COMPONENT_INSTANCE_ID + List<ComponentInstancePropInput> propInputsList = new ArrayList<>(); + ComponentInstancePropInput propInput = new ComponentInstancePropInput(); + propInput.setName(LISTINPUT_PROP1_NAME); + propInput.setType(LISTINPUT_PROP1_TYPE); + propInput.setUniqueId(COMPONENT_INSTANCE_ID+"."+LISTINPUT_PROP1_NAME); + propInputsList.add(propInput); + propInput = new ComponentInstancePropInput(); + propInput.setName(LISTINPUT_PROP2_NAME); + propInput.setType(LISTINPUT_PROP2_TYPE); + propInput.setUniqueId(COMPONENT_INSTANCE_ID+"."+LISTINPUT_PROP2_NAME); + propInputsList.add(propInput); + propInputsListMap.put(COMPONENT_INSTANCE_ID, propInputsList); + ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); + componentInstInputsMap.setComponentInstanceInputsMap(propInputsListMap); + componentInstListInput.setComponentInstInputsMap(componentInstInputsMap); + + return componentInstListInput; + } + + @Test + public void test_createListInput_success() throws Exception { + ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap(); + List<ComponentInstancePropInput> propInputsList = componentInstInputsMap.getComponentInstanceInputsMap().get(COMPONENT_INSTANCE_ID); + InputDefinition listInput = createListInputParams.getListInput(); + + // set up mock returns + // for get component object: + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + // for data type creation (use captor): + when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>())); + when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID); + when(propertyDeclarationOrchestrator.declarePropertiesToListInput(service, componentInstInputsMap, listInput)).thenReturn(Either.left(listInput)); + // for BaseOperation.getAllDataTypes: + when(applicationDataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); // don't use Collections.emptyMap + // for BaseOperation.validatePropertyDefaultValue: + when(propertyOperation.isPropertyTypeValid(any())).thenReturn(true); + when(propertyOperation.isPropertyInnerTypeValid(any(),any())).thenReturn(new ImmutablePair<>(listInput.getSchemaType(), true)); + when(propertyOperation.isPropertyDefaultValueValid(any(), any())).thenReturn(true); + // for createListInputsInGraph: + when(toscaOperationFacadeMock.addInputsToComponent(anyMap(), eq(COMPONENT_ID))).thenReturn(Either.left(Arrays.asList(listInput))); + // for rollback/commit: + when(titanDao.commit()).thenReturn(TitanOperationStatus.OK); + // for unlock resource + when(graphLockOperation.unlockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + + Either<List<InputDefinition>, ResponseFormat> result = + testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false); + // validate result + assertEquals(true, result.isLeft()); + List<InputDefinition> resultInputList = result.left().value(); + assertEquals(1, resultInputList.size()); + //InputDefinition resultInput = resultInputList.get(0); + Map<String, DataTypeDefinition> captoredDataTypeMap = dataTypesMapCaptor.getValue(); + assertEquals(1, captoredDataTypeMap.size()); + assertEquals(true, captoredDataTypeMap.containsKey(LISTINPUT_SCHEMA_TYPE)); + DataTypeDefinition captoredDataType = captoredDataTypeMap.get(LISTINPUT_SCHEMA_TYPE); + assertEquals("tosca.datatypes.Root", captoredDataType.getDerivedFromName()); + assertEquals( propInputsList.size(), captoredDataType.getProperties().size()); + // confirm if corresponding property exists in data type + captoredDataType.getProperties().forEach(dataTypeProp -> { + Optional<ComponentInstancePropInput> find = propInputsList.stream() + .filter(propInput -> propInput.getName().equals(dataTypeProp.getName())).findAny(); + assertEquals(true, find.isPresent()); + }); + } + + @Test + public void test_createListInput_fail_getComponent() throws Exception { + ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either<List<InputDefinition>, ResponseFormat> result = + testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false); + assertEquals(true, result.isRight()); + } + + + @Test + public void test_createListInput_fail_lockComponent() throws Exception { + ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT); + Either<List<InputDefinition>, ResponseFormat> result = + testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false); + assertEquals(true, result.isRight()); + } + + @Test + public void test_createListInput_fail_getAllDataTypes() throws Exception { + ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap(); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>())); + when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID); + when(applicationDataTypeCache.getAll()).thenReturn(Either.right(TitanOperationStatus.NOT_FOUND)); + when(componentsUtilsMock.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY)).thenReturn(new ResponseFormat()); + + Either<List<InputDefinition>, ResponseFormat> result = + testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false); + assertEquals(true, result.isRight()); + verify(applicationDataTypeCache, times(1)).getAll(); + verify(componentsUtilsMock, times(1)).getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY); + } + + @Test + public void test_createListInput_fail_prepareAndValidateInput() throws Exception { + ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap(); + InputDefinition listInput = createListInputParams.getListInput(); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>())); + when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID); + when(applicationDataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); // don't use Collections.emptyMap + // for BaseOperation.validatePropertyDefaultValue: + when(propertyOperation.isPropertyTypeValid(any())).thenReturn(false); + + Either<List<InputDefinition>, ResponseFormat> result = + testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false); + assertEquals(true, result.isRight()); + verify(propertyOperation, times(1)).isPropertyTypeValid(any()); + } + + @Test + public void test_createListInput_fail_addInputsToComponent() throws Exception { + ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap(); + InputDefinition listInput = createListInputParams.getListInput(); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>())); + when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID); + when(applicationDataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); // don't use Collections.emptyMap + // for BaseOperation.validatePropertyDefaultValue: + when(propertyOperation.isPropertyTypeValid(any())).thenReturn(true); + when(propertyOperation.isPropertyInnerTypeValid(any(),any())).thenReturn(new ImmutablePair<>(listInput.getSchemaType(), true)); + when(propertyOperation.isPropertyDefaultValueValid(any(), any())).thenReturn(true); + when(toscaOperationFacadeMock.addInputsToComponent(anyMap(), eq(COMPONENT_ID))).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + + Either<List<InputDefinition>, ResponseFormat> result = + testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false); + assertEquals(true, result.isRight()); + verify(toscaOperationFacadeMock, times(1)).addInputsToComponent(anyMap(), eq(COMPONENT_ID)); + } + + @Test + public void test_deleteInput_listInput_fail_getComponent() throws Exception { + //ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, LISTINPUT_NAME); + assertEquals(true, result.isRight()); + verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)); + } + + + @Test + public void test_deleteInput_listInput_fail_validateInput() throws Exception { + InputDefinition listInput = setUpListInput(); + String inputId = COMPONENT_ID + "." + listInput.getName(); + listInput.setUniqueId(inputId); + service.setInputs(Collections.singletonList(listInput)); + //ComponentInstListInput createListInputParams = setUpCreateListInputParams(); + final String NONEXIST_INPUT_NAME = "myInput"; + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, NONEXIST_INPUT_NAME); + assertEquals(true, result.isRight()); + verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)); + } + + + @Test + public void test_deleteInput_listInput_fail_lockComponent() throws Exception { + InputDefinition listInput = setUpListInput(); + String inputId = COMPONENT_ID + "." + listInput.getName(); + listInput.setUniqueId(inputId); + service.setInputs(Collections.singletonList(listInput)); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.NOT_FOUND); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId); + assertEquals(true, result.isRight()); + verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)); + verify(graphLockOperation, times(1)).lockComponent(COMPONENT_ID, NodeTypeEnum.Service); + } + + + @Test + public void test_deleteInput_listInput_fail_deleteInput() throws Exception { + InputDefinition listInput = setUpListInput(); + String inputId = COMPONENT_ID + "." + listInput.getName(); + listInput.setUniqueId(inputId); + service.setInputs(Collections.singletonList(listInput)); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.BAD_REQUEST); + when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId); + assertEquals(true, result.isRight()); + verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)); + verify(graphLockOperation, times(1)).lockComponent(COMPONENT_ID, NodeTypeEnum.Service); + verify(toscaOperationFacadeMock, times(1)).deleteInputOfResource(service, listInput.getName()); + } + + + @Test + public void test_deleteInput_listInput_success() throws Exception { + InputDefinition listInput = setUpListInput(); + String inputId = COMPONENT_ID + "." + listInput.getName(); + listInput.setUniqueId(inputId); + listInput.setIsDeclaredListInput(true); + service.setInputs(Collections.singletonList(listInput)); + ArgumentCaptor<String> schemaTypeCaptor = ArgumentCaptor.forClass(String.class); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.OK); + //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(service, listInput)).thenReturn(StorageOperationStatus.OK); + when(dataTypeBusinessLogic.deletePrivateDataType(eq(service), schemaTypeCaptor.capture())) + .thenReturn(Either.left(new DataTypeDefinition())); // TODO: replace to return proper datatype + //when(propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(service, listInput)).thenReturn(StorageOperationStatus.OK); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId); + assertEquals(true, result.isLeft()); + verify(propertyDeclarationOrchestrator, times(1)).unDeclarePropertiesAsListInputs(service, listInput); + verify(dataTypeBusinessLogic, times(1)).deletePrivateDataType(service, listInput.getSchemaType()); + assertEquals(listInput.getSchemaType(), schemaTypeCaptor.getValue()); + } + + + @Test + public void test_deleteInput_input_fail_unDeclare() throws Exception { + InputDefinition listInput = setUpListInput(); + String inputId = COMPONENT_ID + "." + listInput.getName(); + listInput.setUniqueId(inputId); + listInput.setIsDeclaredListInput(false); + service.setInputs(Collections.singletonList(listInput)); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.OK); + //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(service, listInput)).thenReturn(StorageOperationStatus.BAD_REQUEST); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId); + assertEquals(true, result.isRight()); + verify(propertyDeclarationOrchestrator, times(1)).unDeclarePropertiesAsInputs(service, listInput); + } + + + @Test + public void test_deleteInput_input_success() throws Exception { + InputDefinition listInput = setUpListInput(); + String inputId = COMPONENT_ID + "." + listInput.getName(); + listInput.setUniqueId(inputId); + listInput.setIsDeclaredListInput(false); + service.setInputs(Collections.singletonList(listInput)); + + when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.OK); + //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(service, listInput)).thenReturn(StorageOperationStatus.OK); + + Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId); + assertEquals(true, result.isLeft()); + verify(propertyDeclarationOrchestrator, times(1)).unDeclarePropertiesAsInputs(service, listInput); + } + } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclaratorTest.java index acfa721e74..f5d4aabd92 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclaratorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclaratorTest.java @@ -1,6 +1,7 @@ package org.openecomp.sdc.be.components.property; import fj.data.Either; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -8,19 +9,25 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; import org.openecomp.sdc.be.components.utils.AnnotationBuilder; import org.openecomp.sdc.be.components.utils.InputsBuilder; +import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder; import org.openecomp.sdc.be.components.utils.ResourceBuilder; import org.openecomp.sdc.be.datatypes.elements.Annotation; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstancePropInput; import org.openecomp.sdc.be.model.ComponentParametersView; 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.StorageException; 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; @@ -41,6 +48,12 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar @Mock private ToscaOperationFacade toscaOperationFacade; + @Mock + private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + + @Mock + private PropertyOperation propertyOperation; + @Captor private ArgumentCaptor<ComponentParametersView> inputsFilterCaptor; @@ -50,8 +63,8 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar @Before public void setUp() throws Exception { super.setUp(); - testInstance = new ComponentInstanceInputPropertyDeclarator(mockComponentUtils(), null, - toscaOperationFacade, null, mockExceptionUtils()); + testInstance = new ComponentInstanceInputPropertyDeclarator(mockComponentUtils(), propertyOperation, + toscaOperationFacade, componentInstanceBusinessLogic, mockExceptionUtils()); annotation1 = AnnotationBuilder.create() .setType("annotationType1") .setName("annotation1") @@ -88,6 +101,55 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar assertThatExceptionOfType(StorageException.class).isThrownBy(() -> testInstance.declarePropertiesAsInputs(resource, "inst1", propsToDeclare)); } + @Test + public void unDeclarePropertiesAsListInputsTest() { + InputDefinition inputToDelete = new InputDefinition(); + inputToDelete.setUniqueId(INPUT_ID); + inputToDelete.setName(INPUT_ID); + inputToDelete.setIsDeclaredListInput(true); + + Component component = createComponentWithListInput(INPUT_ID, "innerPropName"); + PropertyDefinition prop = new PropertyDataDefinitionBuilder() + .setName("propName") + .setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName")) + .setType("list") + .setUniqueId("propName") + .addGetInputValue(INPUT_ID) + .build(); + component.setProperties(Collections.singletonList(prop)); + + List<ComponentInstanceInput> ciPropList = new ArrayList<>(); + ComponentInstanceInput ciProp = new ComponentInstanceInput(); + List<String> pathOfComponentInstances = new ArrayList<>(); + pathOfComponentInstances.add("pathOfComponentInstances"); + ciProp.setPath(pathOfComponentInstances); + ciProp.setUniqueId("componentInstanceId"); + ciProp.setDefaultValue("default value"); + ciProp.setComponentInstanceId("componentInstanceId"); + ciProp.setComponentInstanceName("componentInstanceName"); + ciProp.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName")); + ciPropList.add(ciProp); + + when(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(eq(component), eq(INPUT_ID))).thenReturn(ciPropList); + when(propertyOperation.findDefaultValueFromSecondPosition(eq(pathOfComponentInstances), eq(ciProp.getUniqueId()), eq(ciProp.getDefaultValue()))).thenReturn(Either.left(ciProp.getDefaultValue())); + when(toscaOperationFacade.updateComponentInstanceInputs(eq(component), eq(ciProp.getComponentInstanceId()), eq(ciPropList))).thenReturn(StorageOperationStatus.OK); + StorageOperationStatus storageOperationStatus = testInstance.unDeclarePropertiesAsListInputs(component, inputToDelete); + + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_whenNoListInput_returnOk() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + List<ComponentInstanceInput> resList = new ArrayList<>(); + when(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(eq(resource), eq(INPUT_ID))).thenReturn(resList); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.OK); + } + private void verifyInputAnnotations(InputDefinition inputDefinition) { List<Annotation> annotations = inputDefinition.getAnnotations(); assertThat(annotations) @@ -105,4 +167,19 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar .build(); } -}
\ No newline at end of file + private Component createComponentWithListInput(String inputName, String propName) { + InputDefinition input = InputsBuilder.create() + .setName(inputName) + .build(); + + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setDefaultValue("defaultValue"); + input.setValue(generateGetInputValueAsListInput(inputName, propName)); + + return new ResourceBuilder() + .setUniqueId(RESOURCE_ID) + .addInput(input) + .build(); + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java index 5752ae272e..f59adada9a 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java @@ -1,26 +1,25 @@ package org.openecomp.sdc.be.components.property; import fj.data.Either; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InjectMocks; -import org.mockito.Mock; +import org.mockito.*; import org.mockito.junit.MockitoJUnitRunner; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.utils.InputsBuilder; import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder; +import org.openecomp.sdc.be.components.utils.ResourceBuilder; import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.*; 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 org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -37,6 +36,11 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT private ComponentInstancePropertyDeclarator testInstance; @Mock private ToscaOperationFacade toscaOperationFacade; + @Mock + private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + @Mock + private PropertyOperation propertyOperation; + @Captor private ArgumentCaptor<Map<String, List<ComponentInstanceProperty>>> instancePropertiesCaptor; @@ -98,6 +102,100 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT verifyUpdatedComplexProperty(capturedInstanceProperties, inputs); } + @Test + public void declarePropertiesAsListInput() { + // construct arguments + List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2); + List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties); + InputDefinition input = new InputDefinition(new PropertyDataDefinitionBuilder() + .setName("listinput") + .setType("list") + .setDescription("description") + .setSchemaType("org.onap.datatype.listinput") + .build()); + // mock returns + when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor.capture())).thenReturn(Either.left(Collections.emptyMap())); + Either<InputDefinition, StorageOperationStatus> result = testInstance.declarePropertiesAsListInput(resource, "inst1", propsToDeclare, input); + // validate result + assertThat(result.isLeft()).isTrue(); + List<ComponentInstanceProperty> capturedInstanceProperties = instancePropertiesCaptor.getValue().get(INSTANCE_ID); + assertThat(capturedInstanceProperties.size()).isEqualTo(2); + Map<String, PropertyDataDefinition> propertiesMap = + properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, e->e)); + for(ComponentInstanceProperty instanceProperty: capturedInstanceProperties) { + assertThat(propertiesMap.containsKey(instanceProperty.getName())).isTrue(); + PropertyDataDefinition property = propertiesMap.get(instanceProperty.getName()); + assertThat(instanceProperty.getType()).isEqualTo(property.getType()); + assertThat(instanceProperty.isGetInputProperty()).isTrue(); + } + } + + @Test + public void declarePropertiesAsListInput_propertyOwnerNotFound() { + // construct arguments + List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2); + List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties); + InputDefinition input = new InputDefinition(new PropertyDataDefinitionBuilder() + .setName("listinput") + .setType("list") + .setDescription("description") + .setSchemaType("org.onap.datatype.listinput") + .build()); + Either<InputDefinition, StorageOperationStatus> result = testInstance.declarePropertiesAsListInput(resource, "inst2", propsToDeclare, input); + // validate result + assertThat(result.isRight()).isTrue(); + assertThat(result.right().value()).isEqualTo(StorageOperationStatus.NOT_FOUND); + } + + @Test + public void unDeclarePropertiesAsListInputsTest() { + InputDefinition inputToDelete = new InputDefinition(); + inputToDelete.setUniqueId(INPUT_ID); + inputToDelete.setName(INPUT_ID); + inputToDelete.setIsDeclaredListInput(true); + + Component component = createComponentWithListInput(INPUT_ID, "innerPropName"); + PropertyDefinition prop = new PropertyDataDefinitionBuilder() + .setName("propName") + .setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName")) + .setType("list") + .setUniqueId("propName") + .addGetInputValue(INPUT_ID) + .build(); + component.setProperties(Collections.singletonList(prop)); + + List<ComponentInstanceProperty> ciPropList = new ArrayList<>(); + ComponentInstanceProperty ciProp = new ComponentInstanceProperty(); + List<String> pathOfComponentInstances = new ArrayList<>(); + pathOfComponentInstances.add("pathOfComponentInstances"); + ciProp.setPath(pathOfComponentInstances); + ciProp.setUniqueId("componentInstanceId"); + ciProp.setDefaultValue("default value"); + ciProp.setComponentInstanceId("componentInstanceId"); + ciProp.setComponentInstanceName("componentInstanceName"); + ciProp.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName")); + ciPropList.add(ciProp); + + when(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(eq(component), eq(INPUT_ID))).thenReturn(ciPropList); + when(propertyOperation.findDefaultValueFromSecondPosition(eq(pathOfComponentInstances), eq(ciProp.getUniqueId()), eq(ciProp.getDefaultValue()))).thenReturn(Either.left(ciProp.getDefaultValue())); + when(toscaOperationFacade.updateComponentInstanceProperties(eq(component), eq(ciProp.getComponentInstanceId()), eq(ciPropList))).thenReturn(StorageOperationStatus.OK); + StorageOperationStatus storageOperationStatus = testInstance.unDeclarePropertiesAsListInputs(component, inputToDelete); + + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_whenNoListInput_returnOk() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + List<ComponentInstanceProperty> resList = new ArrayList<>(); + when(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(eq(resource), eq(INPUT_ID))).thenReturn(resList); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.OK); + } + private void verifyUpdatedProperties(List<PropertyDataDefinition> properties, List<ComponentInstanceProperty> capturedInstanceProperties, List<InputDefinition> inputs) { assertThat(capturedInstanceProperties).hasSize(properties.size()); Map<String, ComponentInstanceProperty> updatedPropertiesByName = MapUtil.toMap(capturedInstanceProperties, ComponentInstanceProperty::getName); @@ -204,4 +302,19 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT assertThat(input.getInstanceUniqueId()).isEqualTo(INSTANCE_ID); } -}
\ No newline at end of file + private Component createComponentWithListInput(String inputName, String propName) { + InputDefinition input = InputsBuilder.create() + .setName(inputName) + .build(); + + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setDefaultValue("defaultValue"); + input.setValue(generateGetInputValueAsListInput(inputName, propName)); + + return new ResourceBuilder() + .setUniqueId(RESOURCE_ID) + .addInput(input) + .build(); + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclaratorTest.java new file mode 100644 index 0000000000..7069fe84d7 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclaratorTest.java @@ -0,0 +1,175 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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.components.property; + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; +import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; +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 static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + + +@RunWith(MockitoJUnitRunner.class) +public class ComponentPropertyDeclaratorTest extends PropertyDeclaratorTestBase { + + @InjectMocks + private ComponentPropertyDeclarator testInstance; + @Mock + private PropertyBusinessLogic propertyBusinessLogic; + @Mock + private PropertyOperation propertyOperation; + @Mock + private ToscaOperationFacade toscaOperationFacade; + + @Test + public void unDeclarePropertiesAsListInputsTest_whenPropertyUsedByOperation() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + + PropertyDefinition propertyDefinition = new PropertyDefinition(input); + + when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), eq(propertyDefinition))).thenReturn(true); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.DECLARED_INPUT_USED_BY_OPERATION); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_whenNotPresentPropertyToUpdateCandidate() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + resource.setProperties(Collections.singletonList(propertyDefinition)); + + when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any(PropertyDefinition.class))).thenReturn(false); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.OK); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_whenPropertiesEmpty() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + + resource.setProperties(new ArrayList<>()); + + when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any(PropertyDefinition.class))).thenReturn(false); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.OK); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_whenPropertiesToUpdateIsEmpty() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + + PropertyDefinition propertyDefinition = new PropertyDefinition(input); + resource.setProperties(Collections.singletonList(propertyDefinition)); + + when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), eq(propertyDefinition))).thenReturn(false); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.OK); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_singleProperty() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + input.setDefaultValue("default value"); + + PropertyDefinition propertyDefinition = new PropertyDefinition(input); + List<GetInputValueDataDefinition> getInputValueList = new ArrayList<>(); + getInputValueList.add(buildGetInputValue(INPUT_ID)); + getInputValueList.add(buildGetInputValue("otherInputId")); + propertyDefinition.setGetInputValues(getInputValueList); + propertyDefinition.setUniqueId("propertyId"); + propertyDefinition.setDefaultValue("default value"); + propertyDefinition.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName")); + resource.setProperties(Collections.singletonList(propertyDefinition)); + + when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any())).thenReturn(false); + when(propertyOperation.findDefaultValueFromSecondPosition(eq(Collections.emptyList()), eq(propertyDefinition.getUniqueId()), eq(propertyDefinition.getDefaultValue()))).thenReturn(Either.left(propertyDefinition.getDefaultValue())); + when(toscaOperationFacade.updatePropertyOfComponent(eq(resource), any())).thenReturn(Either.left(propertyDefinition)); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.OK); + } + + @Test + public void unDeclarePropertiesAsListInputsTest_UnDeclareInputFail() { + InputDefinition input = new InputDefinition(); + input.setUniqueId(INPUT_ID); + input.setName(INPUT_ID); + input.setValue("value"); + input.setDefaultValue("default value"); + + PropertyDefinition propertyDefinition = new PropertyDefinition(input); + List<GetInputValueDataDefinition> getInputValueList = new ArrayList<>(); + getInputValueList.add(buildGetInputValue(INPUT_ID)); + getInputValueList.add(buildGetInputValue("otherInputId")); + propertyDefinition.setGetInputValues(getInputValueList); + propertyDefinition.setUniqueId("propertyId"); + propertyDefinition.setDefaultValue("default value"); + propertyDefinition.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName")); + resource.setProperties(Collections.singletonList(propertyDefinition)); + + when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any())).thenReturn(false); + when(propertyOperation.findDefaultValueFromSecondPosition(eq(Collections.emptyList()), eq(propertyDefinition.getUniqueId()), eq(propertyDefinition.getDefaultValue()))).thenReturn(Either.left(propertyDefinition.getDefaultValue())); + when(toscaOperationFacade.updatePropertyOfComponent(eq(resource), any())).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input); + Assert.assertEquals(status, StorageOperationStatus.NOT_FOUND); + } + + private GetInputValueDataDefinition buildGetInputValue(String InputId) { + GetInputValueDataDefinition getInputValue = new GetInputValueDataDefinition(); + getInputValue.setInputId(InputId); + getInputValue.setInputName(InputId); + + return getInputValue; + } + +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclaratorTest.java index 63e39b5e61..72706db606 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclaratorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclaratorTest.java @@ -136,6 +136,56 @@ public class GroupPropertyDeclaratorTest extends PropertyDeclaratorTestBase { assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId()); } + @Test + public void testUnDeclarePropertiesAsListInputs_whenComponentHasNoGroups_returnOk() { + Resource resource = new Resource(); + StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input); + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + verifyZeroInteractions(groupOperation); + } + + @Test + public void testUnDeclarePropertiesAsListInputs_whenNoPropertiesFromGroupMatchInputId_returnOk() { + StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(createResourceWithGroup(), input); + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + verifyZeroInteractions(groupOperation); + } + + @Test + public void whenFailingToUpdateDeclaredPropertiesAsListInputs_returnErrorStatus() { + Resource resource = createResourceWithGroups(GROUP_ID); + Optional<GroupDefinition> groupDefinition = resource.getGroupById(GROUP_ID); + assertThat(groupDefinition.isPresent()).isTrue(); + PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID); + groupDefinition.get().setProperties(Collections.singletonList(getInputPropForInput)); + when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue())); + when(groupOperation.updateGroupProperties(eq(resource), eq(GROUP_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.GENERAL_ERROR); + StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input); + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.GENERAL_ERROR); + } + + @Test + public void testUnDeclarePropertiesAsListInputs_propertiesUpdatedCorrectly() { + Resource resource = createResourceWithGroups(GROUP_ID, "groupId3"); + Optional<GroupDefinition> groupDefinition = resource.getGroupById(GROUP_ID); + PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID); + PropertyDataDefinition someOtherProperty = new PropertyDataDefinitionBuilder().build(); + groupDefinition.get().setProperties(Arrays.asList(getInputPropForInput, someOtherProperty)); + + when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue())); + when(groupOperation.updateGroupProperties(eq(resource), eq(GROUP_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.OK); + StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input); + + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + List<PropertyDataDefinition> updatedProperties = updatedPropsCapture.getValue(); + assertThat(updatedProperties).hasSize(1); + PropertyDataDefinition updatedProperty = updatedProperties.get(0); + assertThat(updatedProperty.isGetInputProperty()).isFalse(); + assertThat(updatedProperty.getValue()).isEmpty(); + assertThat(updatedProperty.getDefaultValue()).isEqualTo(getInputPropForInput.getDefaultValue()); + assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId()); + } + private Resource createResourceWithGroup() { return createResourceWithGroups(GROUP_ID); } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclaratorTest.java index 72c26541f1..f85388a06b 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclaratorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclaratorTest.java @@ -134,6 +134,55 @@ public class PolicyPropertyDeclaratorTest extends PropertyDeclaratorTestBase { assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId()); } + @Test + public void testUnDeclarePropertiesAsListInputs_whenComponentHasNoPolicies_returnOk() { + Resource resource = new Resource(); + StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input); + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + verifyZeroInteractions(policyOperation); + } + + @Test + public void testUnDeclarePropertiesAsListInputs_whenNoPropertiesFromPolicyMatchInputId_returnOk() { + StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(createResourceWithPolicy(), input); + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + verifyZeroInteractions(policyOperation); + } + + @Test + public void whenFailingToUpdateDeclaredPropertiesAsListInputs_returnErrorStatus() { + Resource resource = createResourceWithPolicies(POLICY_ID); + PolicyDefinition policyDefinition = resource.getPolicies().get(POLICY_ID); + PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID); + policyDefinition.setProperties(Collections.singletonList(getInputPropForInput)); + when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue())); + when(policyOperation.updatePolicyProperties(eq(resource), eq(POLICY_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.GENERAL_ERROR); + StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input); + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.GENERAL_ERROR); + } + + @Test + public void testUnDeclarePropertiesAsListInputs_propertiesUpdatedCorrectly() { + Resource resource = createResourceWithPolicies(POLICY_ID, "policyId3"); + PolicyDefinition policyDefinition = resource.getPolicies().get(POLICY_ID); + PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID); + PropertyDataDefinition someOtherProperty = new PropertyDataDefinitionBuilder().build(); + policyDefinition.setProperties(Arrays.asList(getInputPropForInput, someOtherProperty)); + + when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue())); + when(policyOperation.updatePolicyProperties(eq(resource), eq(POLICY_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.OK); + StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input); + + assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK); + List<PropertyDataDefinition> updatedProperties = updatedPropsCapture.getValue(); + assertThat(updatedProperties).hasSize(1); + PropertyDataDefinition updatedProperty = updatedProperties.get(0); + assertThat(updatedProperty.isGetInputProperty()).isFalse(); + assertThat(updatedProperty.getValue()).isEmpty(); + assertThat(updatedProperty.getDefaultValue()).isEqualTo(getInputPropForInput.getDefaultValue()); + assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId()); + } + private Resource createResourceWithPolicy() { return createResourceWithPolicies(POLICY_ID); } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDecelerationOrchestratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDecelerationOrchestratorTest.java index 1a2a76e433..ef1d45dbaa 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDecelerationOrchestratorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDecelerationOrchestratorTest.java @@ -4,23 +4,32 @@ import fj.data.Either; import mockit.Deencapsulation; import org.junit.Before; import org.junit.Test; +import org.mockito.Answers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstInputsMap; +import org.openecomp.sdc.be.model.ComponentInstancePropInput; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import java.util.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; public class PropertyDecelerationOrchestratorTest { @InjectMocks PropertyDeclarationOrchestrator testSubject; - @Mock + @Mock(answer = Answers.CALLS_REAL_METHODS) List<PropertyDeclarator> propertyDeceleratorsMock; - + @Mock private ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDecelerator; @Mock @@ -45,6 +54,21 @@ public class PropertyDecelerationOrchestratorTest { } @Test + public void testDeclarePropertiesToListInputs() throws Exception { + Component component = new Resource(); + ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); + Map<String, List<ComponentInstancePropInput>> componentInstanceInputsMap = new HashMap<>(); + List<ComponentInstancePropInput> value = new LinkedList<>(); + componentInstanceInputsMap.put("mock", value); + componentInstInputsMap.setComponentInstanceInputsMap(componentInstanceInputsMap); + InputDefinition input = new InputDefinition(); + Either<InputDefinition, StorageOperationStatus> result; + + // default test + result = testSubject.declarePropertiesToListInput(component, componentInstInputsMap, input); + } + + @Test public void testUnDeclarePropertiesAsInputs() throws Exception { Component component = new Resource(); InputDefinition inputToDelete = new InputDefinition(); @@ -58,6 +82,33 @@ public class PropertyDecelerationOrchestratorTest { result = testSubject.unDeclarePropertiesAsInputs(component, inputToDelete); } + @Test + public void testUnDeclarePropertiesAsListInputs() throws Exception { + Component component = new Resource(); + InputDefinition inputToDelete = new InputDefinition(); + StorageOperationStatus result; + + Iterator<PropertyDeclarator> mockIter = Mockito.mock(Iterator.class); + Mockito.when(propertyDeceleratorsMock.iterator()).thenReturn(mockIter); + Mockito.when(mockIter.hasNext()).thenReturn(false); + + // default test + result = testSubject.unDeclarePropertiesAsListInputs(component, inputToDelete); + } + + @Test + public void testGetPropOwnerId() throws Exception { + ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); + Map<String, List<ComponentInstancePropInput>> componentInstanceInputsMap = new HashMap<>(); + List<ComponentInstancePropInput> value = new LinkedList<>(); + componentInstanceInputsMap.put("mock", value); + componentInstInputsMap.setComponentInstanceInputsMap(componentInstanceInputsMap); + String result; + + // default test + result = Deencapsulation.invoke(testSubject, "getPropOwnerId", componentInstInputsMap); + } + @Test(expected = IllegalStateException.class) public void testGetPropertyDecelerator() throws Exception { ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDeclaratorTestBase.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDeclaratorTestBase.java index bd21f683ad..f1f4d0aac7 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDeclaratorTestBase.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDeclaratorTestBase.java @@ -77,6 +77,10 @@ public class PropertyDeclaratorTestBase { return String.format("{\"%s\":\"%s\"}", GET_INPUT, value); } + String generateGetInputValueAsListInput(String inputName, String inputProperty) { + return String.format("{\"%s\":[\"%s\",\"INDEX\",\"%s\"]}", GET_INPUT, inputName, inputProperty); + } + private void verifyInputPropertiesList(PropertyDataDefinition updatedProperty, InputDefinition input) { assertThat(input.getProperties()).hasSize(1); assertThat(new ComponentInstanceProperty(updatedProperty)).isEqualTo(input.getProperties().get(0)); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/UiComponentDataConverterTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/UiComponentDataConverterTest.java index eb123771a9..3922dd8de7 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/UiComponentDataConverterTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/UiComponentDataConverterTest.java @@ -218,14 +218,16 @@ public class UiComponentDataConverterTest { public void getUiDataTransferFromResourceByParams_policies() { Resource resourceWithPolicies = buildResourceWithPolicies(); UiComponentDataTransfer componentDTO = uiComponentDataConverter.getUiDataTransferFromResourceByParams(resourceWithPolicies, Collections.singletonList("policies")); - assertThat(componentDTO.getPolicies()).isEqualTo(resourceWithPolicies.resolvePoliciesList()); + List<PolicyDefinition> expectedPolicies = resourceWithPolicies.resolvePoliciesList(); + assertThat(componentDTO.getPolicies()).containsExactlyInAnyOrder((PolicyDefinition[]) expectedPolicies.toArray(new PolicyDefinition[expectedPolicies.size()])); } @Test public void getUiDataTransferFromServiceByParams_policies() { Service resourceWithPolicies = buildServiceWithPolicies(); UiComponentDataTransfer componentDTO = uiComponentDataConverter.getUiDataTransferFromServiceByParams(resourceWithPolicies, Collections.singletonList("policies")); - assertThat(componentDTO.getPolicies()).isEqualTo(resourceWithPolicies.resolvePoliciesList()); + List<PolicyDefinition> expectedPolicies = resourceWithPolicies.resolvePoliciesList(); + assertThat(componentDTO.getPolicies()).containsExactlyInAnyOrder((PolicyDefinition[]) expectedPolicies.toArray(new PolicyDefinition[expectedPolicies.size()])); } @Test diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/InputsServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/InputsServletTest.java index 9ff55c22f0..07184704d4 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/InputsServletTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/InputsServletTest.java @@ -1,166 +1,437 @@ -package org.openecomp.sdc.be.servlets; +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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========================================================= + */ -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response; +package org.openecomp.sdc.be.servlets; +import fj.data.Either; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.openecomp.sdc.be.components.impl.DataTypeBusinessLogic; import org.openecomp.sdc.be.components.impl.InputsBusinessLogic; +import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.ComponentInstInputsMap; +import org.openecomp.sdc.be.model.ComponentInstListInput; +import org.openecomp.sdc.be.model.ComponentInstancePropInput; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.web.context.WebApplicationContext; -import fj.data.Either; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSession; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +public class InputsServletTest extends JerseySpringBaseTest { + + /* Constants */ + private static final String RESOURCE_ID = "serviceId"; + private static final String USER_ID = "userId"; + private static final String COMPONENT_INSTANCE_ID = "instanceId"; + private static final String COMPONENT_ID = "componentId"; + private static final String INSTANCE_INPUT_ID = "inputId"; + private static final String LISTINPUT_NAME = "listInput"; + private static final String LISTINPUT_SCHEMA_TYPE = "org.onap.datatypes.listinput"; + private static final String LISTINPUT_PROP1_NAME = "prop1"; + private static final String LISTINPUT_PROP1_TYPE = "string"; + private static final String LISTINPUT_PROP2_NAME = "prop2"; + private static final String LISTINPUT_PROP2_TYPE = "integer"; + + /* Test subject */ + private InputsServletForTest testSubject; + + /* Mocks */ + private InputsBusinessLogic inputsBusinessLogic; + private DataTypeBusinessLogic dataTypeBusinessLogic; + private HttpSession httpSession; + private ServletContext servletContext; + private WebApplicationContext webApplicationContext; + private ComponentsUtils componentsUtils; + private ServletUtils servletUtils; + + /** + * This class extends the original InputsServlet + * and provides methods to inject mocks + */ + class InputsServletForTest extends InputsServlet { + public void setComponentsUtils(ComponentsUtils componentsUtils) { + this.componentsUtils = componentsUtils; + } + + public void setServletUtils(ServletUtils servletUtils) { + this.servletUtils = servletUtils; + } + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + inputsBusinessLogic = mock(InputsBusinessLogic.class); + dataTypeBusinessLogic = mock(DataTypeBusinessLogic.class); + servletContext = mock(ServletContext.class); + httpSession = mock(HttpSession.class); + webApplicationContext = mock(WebApplicationContext.class); + componentsUtils = mock(ComponentsUtils.class); + servletUtils = mock(ServletUtils.class); + when(request.getSession()).thenReturn(httpSession); + when(httpSession.getServletContext()).thenReturn(servletContext); + when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR)).thenReturn(new WebAppContextWrapper()); + when(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)).thenReturn(webApplicationContext); + when(webApplicationContext.getBean(InputsBusinessLogic.class)).thenReturn(inputsBusinessLogic); + when(webApplicationContext.getBean(DataTypeBusinessLogic.class)).thenReturn(dataTypeBusinessLogic); + testSubject.setComponentsUtils(componentsUtils); + testSubject.setServletUtils(servletUtils); + when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils); + } + + + @Override + protected ResourceConfig configure() { + testSubject = new InputsServletForTest(); + return super.configure().register(testSubject); + } + + + private InputDefinition setUpListInput() { + InputDefinition listInput = new InputDefinition(); + listInput.setName(LISTINPUT_NAME); + listInput.setType("list"); + SchemaDefinition listInputSchema = new SchemaDefinition(); + listInputSchema.setProperty(new PropertyDataDefinitionBuilder() + .setType(LISTINPUT_SCHEMA_TYPE) + .setIsRequired(false) + .build() + ); + listInput.setSchema(listInputSchema); + return listInput; + } + + private ComponentInstListInput setUpCreateListInputParams() { + ComponentInstListInput componentInstListInput = new ComponentInstListInput(); + + // Create a "list input" + InputDefinition listInput = setUpListInput(); + componentInstListInput.setListInput(listInput); + + // Create ComponentInstancePropInputs + // for inputs in the ComponentInstance + Map<String, List<ComponentInstancePropInput>> propInputsListMap = new HashMap<>(); + // Add 2 PropInputs. property owner is COMPONENT_INSTANCE_ID + List<ComponentInstancePropInput> propInputsList = new ArrayList<>(); + ComponentInstancePropInput propInput = new ComponentInstancePropInput(); + propInput.setName(LISTINPUT_PROP1_NAME); + propInput.setType(LISTINPUT_PROP1_TYPE); + propInput.setUniqueId(COMPONENT_INSTANCE_ID + "." + LISTINPUT_PROP1_NAME); + propInputsList.add(propInput); + propInput = new ComponentInstancePropInput(); + propInput.setName(LISTINPUT_PROP2_NAME); + propInput.setType(LISTINPUT_PROP2_TYPE); + propInput.setUniqueId(COMPONENT_INSTANCE_ID + "." + LISTINPUT_PROP2_NAME); + propInputsList.add(propInput); + propInputsListMap.put(COMPONENT_INSTANCE_ID, propInputsList); + ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); + componentInstInputsMap.setComponentInstanceInputsMap(propInputsListMap); + componentInstListInput.setComponentInstInputsMap(componentInstInputsMap); + + return componentInstListInput; + } + + @Test + public void test_createListInput_success() throws Exception { + ComponentInstListInput requestBodyObj = setUpCreateListInputParams(); + Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON); + + // for parseToComponentInstListInput + when(componentsUtils.convertJsonToObjectUsingObjectMapper(any(), any(), eq(ComponentInstListInput.class), + eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE))) + .thenReturn(Either.left(requestBodyObj)); + + when(inputsBusinessLogic.createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE), + any(), eq(true), eq(false))) + .thenReturn(Either.left(Collections.emptyList())); + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + + Response response = buildCreateListInputCall().post(entity); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode()); + verify(inputsBusinessLogic, times(1)).createListInput(USER_ID, RESOURCE_ID, + ComponentTypeEnum.SERVICE, requestBodyObj, true, false); + } + + @Test + public void test_createListInput_fail_parse() throws Exception { + ComponentInstListInput requestBodyObj = setUpCreateListInputParams(); + Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON); + + // for parseToComponentInstListInput + ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class); + when(componentsUtils.convertJsonToObjectUsingObjectMapper(any(), userCaptor.capture(), eq(ComponentInstListInput.class), + eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE))) + .thenReturn(Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()))); + + when(inputsBusinessLogic.createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE), + any(), eq(true), eq(false))) + .thenReturn(Either.left(Collections.emptyList())); + + Response response = buildCreateListInputCall().post(entity); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + verify(componentsUtils, times(1)) + .convertJsonToObjectUsingObjectMapper(any(), any(), eq(ComponentInstListInput.class), + eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE)); + assertThat(userCaptor.getValue().getUserId()).isEqualTo(USER_ID); + verify(inputsBusinessLogic, never()).createListInput(USER_ID, RESOURCE_ID, + ComponentTypeEnum.SERVICE, requestBodyObj, true, false); + } + + + @Test + public void test_createListInput_fail_createInput() throws Exception { + ComponentInstListInput requestBodyObj = setUpCreateListInputParams(); + Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON); + + // for parseToComponentInstListInput + ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class); + when(componentsUtils.convertJsonToObjectUsingObjectMapper(any(), userCaptor.capture(), eq(ComponentInstListInput.class), + eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE))) + .thenReturn(Either.left(requestBodyObj)); + + when(inputsBusinessLogic.createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE), + any(), eq(true), eq(false))) + .thenReturn(Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()))); + + Response response = buildCreateListInputCall().post(entity); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + verify(inputsBusinessLogic, times(1)) + .createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE), + any(), eq(true), eq(false)); + } + + + @Test + public void test_createListInput_fail_exception() throws Exception { + ComponentInstListInput requestBodyObj = setUpCreateListInputParams(); + Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON); + + when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())); + + Response response = buildCreateListInputCall().post(entity); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + } + + @Test + public void test_getDataType_success() throws Exception { + when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.left(new DataTypeDefinition())); + + ResponseFormat responseFormat = new ResponseFormat(); + responseFormat.setStatus(HttpStatus.OK_200.getStatusCode()); + when(componentsUtils.getResponseFormat(eq(ActionStatus.OK))).thenReturn(responseFormat); + + Response response = buildGetDataTypeCall().get(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode()); + } + + @Test + public void test_getDataType_fail() throws Exception { + when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST)); + + ResponseFormat responseFormat = new ResponseFormat(); + responseFormat.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode()); + when(componentsUtils.convertFromStorageResponse(eq(StorageOperationStatus.BAD_REQUEST))).thenReturn(ActionStatus.GENERAL_ERROR); + when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(responseFormat); + + Response response = buildGetDataTypeCall().get(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode()); + } + + @Test + public void test_getDataType_fail_exception() throws Exception { + when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST)); + when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())); + + Response response = buildGetDataTypeCall().get(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + } + + @Test + public void test_getDataTypes_success() throws Exception { + when(dataTypeBusinessLogic.getPrivateDataTypes(eq(RESOURCE_ID))).thenReturn(Either.left(Collections.emptyList())); + + ResponseFormat responseFormat = new ResponseFormat(); + responseFormat.setStatus(HttpStatus.OK_200.getStatusCode()); + when(componentsUtils.getResponseFormat(eq(ActionStatus.OK))).thenReturn(responseFormat); + + Response response = buildGetDataTypesCall().get(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode()); + } + + @Test + public void test_getDataTypes_fail() throws Exception { + when(dataTypeBusinessLogic.getPrivateDataTypes(eq(RESOURCE_ID))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST)); + + ResponseFormat responseFormat = new ResponseFormat(); + responseFormat.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode()); + when(componentsUtils.convertFromStorageResponse(eq(StorageOperationStatus.BAD_REQUEST))).thenReturn(ActionStatus.GENERAL_ERROR); + when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(responseFormat); + + Response response = buildGetDataTypesCall().get(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode()); + } + + @Test + public void test_getDataTypes_fail_exception() throws Exception { + when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST)); + when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())); + + Response response = buildGetDataTypesCall().get(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + } + + + @Test + public void test_deleteDataType_success() throws Exception { + when(dataTypeBusinessLogic.deletePrivateDataType(RESOURCE_ID, LISTINPUT_SCHEMA_TYPE)).thenReturn(Either.left(new DataTypeDefinition())); + + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + + Response response = buildGetDataTypeCall().delete(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode()); + } + + @Test + public void test_deleteDataType_failure_exception() throws Exception { + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(new ResponseFormat(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode())); + Response response = buildGetDataTypeCall().delete(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode()); + verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK); + } + + @Test + public void test_deleteDataType_failure_notFound() throws Exception { + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + when(dataTypeBusinessLogic.deletePrivateDataType(RESOURCE_ID, LISTINPUT_SCHEMA_TYPE)).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND)).thenReturn(ActionStatus.ARTIFACT_NOT_FOUND); + when(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND)).thenReturn(new ResponseFormat(HttpStatus.NOT_FOUND_404.getStatusCode())); + Response response = buildGetDataTypeCall().delete(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND_404.getStatusCode()); + verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK); + } + + @Test + public void test_deleteInput_success() throws Exception { + when(inputsBusinessLogic.deleteInput(RESOURCE_ID, USER_ID, LISTINPUT_NAME)) + .thenReturn(Either.left(new InputDefinition())); + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + + // invoke delete call + Response response = target("/v1/catalog/services/{id}/delete/{inputId}/input") + .resolveTemplate("id", RESOURCE_ID) + .resolveTemplate("inputId", LISTINPUT_NAME) + .request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .delete(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode()); + verify(inputsBusinessLogic, times(1)).deleteInput(RESOURCE_ID, USER_ID, LISTINPUT_NAME); + } + + + @Test + public void test_deleteInput_failure_deleteInput() throws Exception { + when(inputsBusinessLogic.deleteInput(RESOURCE_ID, USER_ID, LISTINPUT_NAME)) + .thenReturn(Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()))); + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + + // invoke delete call + Response response = target("/v1/catalog/services/{id}/delete/{inputId}/input") + .resolveTemplate("id", RESOURCE_ID) + .resolveTemplate("inputId", LISTINPUT_NAME) + .request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .delete(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK); + } + + + @Test + public void test_deleteInput_failure_exception() throws Exception { + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode())); + when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())); + + // invoke delete call + Response response = target("/v1/catalog/services/{id}/delete/{inputId}/input") + .resolveTemplate("id", RESOURCE_ID) + .resolveTemplate("inputId", LISTINPUT_NAME) + .request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID) + .delete(); + assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode()); + verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK); + } + + + private Invocation.Builder buildCreateListInputCall() { + return target("/v1/catalog/services/{id}/create/listInput") + .resolveTemplate("id", RESOURCE_ID) + .request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID); + } + + private Invocation.Builder buildGetDataTypeCall() { + return target("/v1/catalog/services/{id}/dataType/{dataTypeName}") + .resolveTemplate("id", RESOURCE_ID) + .resolveTemplate("dataTypeName", LISTINPUT_SCHEMA_TYPE) + .request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID); + } + + private Invocation.Builder buildGetDataTypesCall() { + return target("/v1/catalog/services/{id}/dataTypes") + .resolveTemplate("id", RESOURCE_ID) + .request(MediaType.APPLICATION_JSON) + .header(Constants.USER_ID_HEADER, USER_ID); + } -public class InputsServletTest { - - private InputsServlet createTestSubject() { - return new InputsServlet(); - } - - - @Test - public void testGetComponentInputs() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - HttpServletRequest request = null; - String fromName = ""; - int amount = 0; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testUpdateComponentInputs() throws Exception { - InputsServlet testSubject; - String containerComponentType = ""; - String componentId = ""; - String data = ""; - HttpServletRequest request = null; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetComponentInstanceInputs() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - String instanceId = ""; - String originComonentUid = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetInputPropertiesForComponentInstance() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - String instanceId = ""; - String inputId = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetInputsForComponentInput() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - String inputId = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetInputsAndPropertiesForComponentInput() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - String inputId = ""; - HttpServletRequest request = null; - String userId = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testParseToComponentInstanceMap() throws Exception { - InputsServlet testSubject; - String serviceJson = ""; - User user = null; - Either<ComponentInstInputsMap, ResponseFormat> result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testCreateMultipleInputs() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - HttpServletRequest request = null; - String userId = ""; - String componentInstInputsMapObj = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testDeleteInput() throws Exception { - InputsServlet testSubject; - String componentType = ""; - String componentId = ""; - String inputId = ""; - HttpServletRequest request = null; - String userId = ""; - String componentInstInputsMapObj = ""; - Response result; - - // default test - testSubject = createTestSubject(); - } - - - @Test - public void testGetInputBL() throws Exception { - InputsServlet testSubject; - ServletContext context = null; - InputsBusinessLogic result; - - // default test - testSubject = createTestSubject(); - } -}
\ No newline at end of file +} 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 d46d234595..78ed40a9e6 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 @@ -1,12 +1,14 @@ package org.openecomp.sdc.be.tosca; +import fj.data.Either; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Supplier; - +import java.util.stream.Collectors; +import mockit.Deencapsulation; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Triple; import org.junit.Before; @@ -17,10 +19,12 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.openecomp.sdc.be.components.BeConfDependentTest; +import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathElementDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; @@ -56,9 +60,6 @@ import org.openecomp.sdc.be.tosca.model.ToscaNodeType; 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 fj.data.Either; -import mockit.Deencapsulation; import org.openecomp.sdc.be.tosca.utils.InputConverter; public class ToscaExportHandlerTest extends BeConfDependentTest { @@ -98,6 +99,20 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { CategoryDefinition category = new CategoryDefinition(); List<SubCategoryDefinition> subcategories = new ArrayList<>(); SubCategoryDefinition subcategory = new SubCategoryDefinition(); + List<DataTypeDefinition> dataTypes = new ArrayList<>(); + DataTypeDefinition dataType = new DataTypeDefinition(); + dataType.setName("dataTypeName"); + dataType.setDerivedFromName("tosca.datatypes.Root"); + PropertyDataDefinition propData = new PropertyDataDefinitionBuilder() + .setName("property") + .setType("type") + .build(); + List<PropertyDataDefinition> propDataList = Arrays.asList(propData); + dataType.setPropertiesData(propDataList); + List<PropertyDefinition> propList = propDataList.stream().map(PropertyDefinition::new) + .collect(Collectors.toList()); + dataType.setProperties(propList); + dataTypes.add(dataType); subcategory.setName("name"); subcategories.add(subcategory); @@ -110,6 +125,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { resource.setVendorName("vendorName"); resource.setVendorRelease("vendorRelease"); resource.setResourceVendorModelNumber("resourceVendorModelNumber"); + resource.setDataTypes(dataTypes); return resource; } @@ -1193,4 +1209,4 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { // default test result = Deencapsulation.invoke(testSubject, "convertCapabilities", component, nodeType, dataTypes); } -}
\ No newline at end of file +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaDataTypeTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaDataTypeTest.java new file mode 100644 index 0000000000..94a7d055b7 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaDataTypeTest.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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.tosca.model; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class ToscaDataTypeTest { + private static final String DERIVED_FROM = "tosca.datatypes.Root"; + private static final String VERSION = "1.1"; + private static final String DESCRIPTION = "data type description"; + private static final String PROPERTY_NAME = "prop1"; + private static final String METADATA_KEY = "foo"; + private static final String METADATA_VALUE = "bar"; + + private ToscaDataType testSubject; + + @Test + public void testToscaDataType() throws Exception { + testSubject = new ToscaDataType(); + testSubject.setDerived_from(DERIVED_FROM); + testSubject.setVersion(VERSION); + testSubject.setDescription(DESCRIPTION); + Map<String, String> metadata = new HashMap<>(); + metadata.put(METADATA_KEY, METADATA_VALUE); + testSubject.setMetadata(metadata); + Map<String, ToscaProperty> properties = new HashMap<>(); + properties.put(PROPERTY_NAME, new ToscaProperty()); + testSubject.setProperties(properties); + + assertThat(testSubject.getDerived_from(), is(DERIVED_FROM)); + assertThat(testSubject.getVersion(), is(VERSION)); + assertThat(testSubject.getDescription(), is(DESCRIPTION)); + assertThat(testSubject.getMetadata(), is(metadata)); + assertThat(testSubject.getProperties(), is(properties)); + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateTest.java index 613c7ed457..c250b4eec9 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateTest.java @@ -1,10 +1,12 @@ package org.openecomp.sdc.be.tosca.model; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; +import static org.junit.Assert.*; public class ToscaTemplateTest { @@ -122,9 +124,24 @@ public class ToscaTemplateTest { testSubject.setTopology_template(topology_template); } - + @Test + public void testGetSetData_types() throws Exception { + ToscaTemplate testSubject = createTestSubject(); + Map<String, ToscaDataType> dataTypes = new HashMap<>(); + dataTypes.put("datatype", new ToscaDataType()); + testSubject.setData_types(dataTypes); + assertEquals(dataTypes, testSubject.getData_types()); + } - + + @Test + public void testGetSetInterface_types() throws Exception { + ToscaTemplate testSubject = createTestSubject(); + Map<String, Object> interfaceTypes = new HashMap<>(); + interfaceTypes.put("id", new Object()); + testSubject.setInterface_types(interfaceTypes); + assertEquals(interfaceTypes, testSubject.getInterface_types()); + } }
\ No newline at end of file diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java index 2c84f5afbd..9dc9c84466 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java @@ -65,7 +65,8 @@ public enum EdgeLabelEnum { INTERFACE, INTERFACE_OPERATION, INST_INTERFACES, - NODE_FILTER_TEMPLATE; + NODE_FILTER_TEMPLATE, + DATA_TYPES; /** * Returns EdgeLabelEnum according received name diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java index 288b1ba491..053a690858 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.dao.jsongraph.types; import org.openecomp.sdc.be.datatypes.elements.*; +import org.openecomp.sdc.be.resources.data.DataTypeData; public enum VertexTypeEnum { @@ -62,7 +63,8 @@ public enum VertexTypeEnum { INTERFACE ("interface", InterfaceDataDefinition.class), INTERFACE_OPERATION ("interfaceOperation", OperationDataDefinition.class), NODE_FILTER_TEMPLATE ("NodeTemplateFilter", CINodeFilterDataDefinition.class), - INST_INTERFACES ("InstInterfaces", MapInterfaceDataDefinition.class); + INST_INTERFACES ("InstInterfaces", MapInterfaceDataDefinition.class), + DATA_TYPES ("data_types", DataTypeDataDefinition.class); private String name; private Class classOfJson; 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 65ad149a89..b65997cb35 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 @@ -51,6 +51,8 @@ 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.stream.Collectors.toMap; + public abstract class Component implements PropertiesOwner { private ComponentMetadataDefinition componentMetadataDefinition; @@ -78,8 +80,17 @@ public abstract class Component implements PropertiesOwner { private Map<String, List<UploadNodeFilterInfo>> serviceFilters; protected List<PropertyDefinition> properties; private Map<String, InterfaceDefinition> interfaces; + private List<DataTypeDefinition> dataTypes; + + public List<DataTypeDefinition> getDataTypes() { + return dataTypes; + } + + public void setDataTypes(List<DataTypeDefinition> dataTypes) { + this.dataTypes = dataTypes; + } - public Map<String, InterfaceDefinition> getInterfaces() { + public Map<String, InterfaceDefinition> getInterfaces() { return interfaces; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstListInput.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstListInput.java new file mode 100644 index 0000000000..ee4bef2236 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstListInput.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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.model; + +/** + * Represents a pair of a list of properties to be declared and a "list input" to be created. + * This class is used for passing parameters on creating a list input. + */ +public class ComponentInstListInput { + private ComponentInstInputsMap componentInstInputsMap; + private InputDefinition listInput; + + /** + * Gets componentInstInputsMap which includes properties to be declared. + * + * @return componentInstInputsMap + */ + public ComponentInstInputsMap getComponentInstInputsMap() { + return componentInstInputsMap; + } + + /** + * Sets componentInstInputsMap. + * + * @param componentInstInputsMap + */ + public void setComponentInstInputsMap(ComponentInstInputsMap componentInstInputsMap) { + this.componentInstInputsMap = componentInstInputsMap; + } + + /** + * Gets the input to be created. + * + * @return the list input + */ + public InputDefinition getListInput() { + return listInput; + } + + /** + * Sets the input to be created. + * + * @param listInput + */ + public void setListInput(InputDefinition listInput) { + this.listInput = listInput; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java index 05d9a572a3..3edb8ded6c 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java @@ -51,6 +51,7 @@ public class ComponentParametersView { private boolean ignorePolicies = false; private boolean ignoreNodeFilterRequirements = false; private boolean ignoreNodeFilter = false; + private boolean ignoreDataType = false; public ComponentParametersView() { } @@ -154,6 +155,9 @@ public class ComponentParametersView { this.setIgnoreComponentInstances(false); this.setIgnoreComponentInstancesInterfaces(false); break; + case DATA_TYPES: + this.setIgnoreDataType(false); + break; default: break; } @@ -167,120 +171,114 @@ public class ComponentParametersView { public Component filter(Component component, ComponentTypeEnum componentType) { - if (ignoreUsers) { - component.setCreatorUserId(null); - component.setCreatorFullName(null); - component.setLastUpdaterUserId(null); - component.setLastUpdaterFullName(null); - } - - if (ignoreGroups) { - component.setGroups(null); - } - - if (ignoreComponentInstances) { - component.setComponentInstances(null); - component.setComponentInstancesRelations(null); - } - - if (ignoreComponentInstancesProperties) { - component.setComponentInstancesProperties(null); - } - - if (ignoreProperties && componentType == ComponentTypeEnum.RESOURCE) { - ((Resource) component).setProperties(null); - } - - if (ignoreCapabilities) { - component.setCapabilities(null); - } - - if (ignoreRequirements) { - component.setRequirements(null); - } - - if (ignoreCategories) { - component.setCategories(null); - } - - if (ignoreAllVersions) { - component.setAllVersions(null); - } - if (ignoreAdditionalInformation && componentType == ComponentTypeEnum.RESOURCE) { - ((Resource) component).setAdditionalInformation(null); - } - - if (ignoreArtifacts) { - component.setArtifacts(null); - component.setSpecificComponetTypeArtifacts(null); - component.setDeploymentArtifacts(null); - component.setToscaArtifacts(null); - } - if (ignoreNodeFilterRequirements){ - component.setNodeFilterComponents(null); - } - if (ignoreInterfaces && ignoreInterfaceInstances && - componentType == ComponentTypeEnum.RESOURCE) { - component.setInterfaces(null); - } - if (ignoreDerivedFrom && componentType == ComponentTypeEnum.RESOURCE) { - ((Resource) component).setDerivedFrom(null); - } - if (ignoreAttributesFrom && componentType == ComponentTypeEnum.RESOURCE) { - ((Resource) component).setAttributes(null); - } - if (ignoreComponentInstancesAttributesFrom) { - component.setComponentInstancesAttributes(null); - } - if (ignoreInputs) { - component.setInputs(null); - } - if (ignoreComponentInstancesInputs) { - component.setComponentInstancesInputs(null); - } - if (ignoreServicePath && componentType == ComponentTypeEnum.SERVICE) { - ((Service) component).setForwardingPaths(null); - } - if (ignoreNodeFilter){ - component.setNodeFilterComponents(null); - } - return component; - - } - - public boolean isIgnoreNodeFilterRequirements() { - return ignoreNodeFilterRequirements; - } - - public void setIgnoreNodeFilterRequirements(boolean ignoreNodeFilter) { - this.ignoreNodeFilterRequirements = ignoreNodeFilter; - } - - public void disableAll() { - ignoreUsers = true; - ignoreGroups = true; - ignorePolicies = true; - ignoreComponentInstances = true; - ignoreComponentInstancesProperties = true; - ignoreProperties = true; - ignoreCapabilities = true; - ignoreRequirements = true; - ignoreCategories = true; - ignoreAllVersions = true; - ignoreAdditionalInformation = true; - ignoreArtifacts = true; - ignoreInterfaces = true; - ignoreInterfaceInstances = true; - ignoreDerivedFrom = true; - ignoreAttributesFrom = true; - ignoreInputs = true; - ignoreComponentInstancesAttributesFrom = true; - ignoreComponentInstancesInputs = true; - ignoreCapabiltyProperties = true; - ignoreServicePath = true; - ignoreNodeFilterRequirements = true; + if (ignoreUsers) { + component.setCreatorUserId(null); + component.setCreatorFullName(null); + component.setLastUpdaterUserId(null); + component.setLastUpdaterFullName(null); + } + if (ignoreGroups) { + component.setGroups(null); + } + if (ignoreComponentInstances) { + component.setComponentInstances(null); + component.setComponentInstancesRelations(null); + } + if (ignoreComponentInstancesProperties) { + component.setComponentInstancesProperties(null); + } + if (ignoreProperties && componentType == ComponentTypeEnum.RESOURCE) { + ((Resource) component).setProperties(null); + } + if (ignoreCapabilities) { + component.setCapabilities(null); + } + if (ignoreRequirements) { + component.setRequirements(null); + } + if (ignoreCategories) { + component.setCategories(null); + } + if (ignoreAllVersions) { + component.setAllVersions(null); + } + if (ignoreAdditionalInformation && componentType == ComponentTypeEnum.RESOURCE) { + ((Resource) component).setAdditionalInformation(null); + } + if (ignoreArtifacts) { + component.setArtifacts(null); + component.setSpecificComponetTypeArtifacts(null); + component.setDeploymentArtifacts(null); + component.setToscaArtifacts(null); + } + if (ignoreNodeFilterRequirements){ + component.setNodeFilterComponents(null); + } + if (ignoreInterfaces && ignoreInterfaceInstances && + componentType == ComponentTypeEnum.RESOURCE) { + component.setInterfaces(null); + } + if (ignoreDerivedFrom && componentType == ComponentTypeEnum.RESOURCE) { + ((Resource) component).setDerivedFrom(null); + } + if (ignoreAttributesFrom && componentType == ComponentTypeEnum.RESOURCE) { + ((Resource) component).setAttributes(null); + } + if (ignoreComponentInstancesAttributesFrom) { + component.setComponentInstancesAttributes(null); + } + if (ignoreInputs) { + component.setInputs(null); + } + if (ignoreComponentInstancesInputs) { + component.setComponentInstancesInputs(null); + } + if (ignoreServicePath && componentType == ComponentTypeEnum.SERVICE) { + ((Service) component).setForwardingPaths(null); + } + if (ignoreNodeFilter){ + component.setNodeFilterComponents(null); + } + if (ignoreDataType) { + component.setDataTypes(null); + } + return component; + } + + public boolean isIgnoreNodeFilterRequirements() { + return ignoreNodeFilterRequirements; + } + + public void setIgnoreNodeFilterRequirements(boolean ignoreNodeFilter) { + this.ignoreNodeFilterRequirements = ignoreNodeFilter; + } + + public void disableAll() { + ignoreUsers = true; + ignoreGroups = true; + ignorePolicies = true; + ignoreComponentInstances = true; + ignoreComponentInstancesProperties = true; + ignoreProperties = true; + ignoreCapabilities = true; + ignoreRequirements = true; + ignoreCategories = true; + ignoreAllVersions = true; + ignoreAdditionalInformation = true; + ignoreArtifacts = true; + ignoreInterfaces = true; + ignoreInterfaceInstances = true; + ignoreDerivedFrom = true; + ignoreAttributesFrom = true; + ignoreInputs = true; + ignoreComponentInstancesAttributesFrom = true; + ignoreComponentInstancesInputs = true; + ignoreCapabiltyProperties = true; + ignoreServicePath = true; + ignoreNodeFilterRequirements = true; ignoreNodeFilter = true; - } + ignoreDataType = true; + } public boolean isIgnoreGroups() { return ignoreGroups; @@ -462,6 +460,14 @@ public class ComponentParametersView { this.ignoreNodeFilter = ignoreNodeFilter; } + public boolean isIgnoreDataType() { + return ignoreDataType; + } + + public void setIgnoreDataType(boolean ignoreDataType) { + this.ignoreDataType = ignoreDataType; + } + public JsonParseFlagEnum detectParseFlag() { JsonParseFlagEnum parseFlag; if (isIgnoreComponentInstances()) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/DataTypeDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/DataTypeDefinition.java index 44c6b7b82e..4dc952d59b 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/DataTypeDefinition.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/DataTypeDefinition.java @@ -21,8 +21,10 @@ package org.openecomp.sdc.be.model; import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import java.util.List; +import java.util.stream.Collectors; public class DataTypeDefinition extends DataTypeDataDefinition { 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 14b7a2f786..8c0253a148 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,7 @@ 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.DataTypeDefinition; import org.openecomp.sdc.be.model.MapInterfaceInstanceDataDefinition; import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; @@ -57,6 +58,7 @@ public class TopologyTemplate extends ToscaElement{ private Map<String, InterfaceDataDefinition> interfaces; private Map<String, MapInterfaceInstanceDataDefinition> instInterfaces; private Map<String, MapInterfaceDataDefinition> componentInstInterfaces; + private Map<String, DataTypeDataDefinition> dataTypes; private Map<String, CINodeFilterDataDefinition> nodeFilterComponents; //Component Instances External References (instanceId -> ExternalRefsMap) @@ -239,6 +241,22 @@ public class TopologyTemplate extends ToscaElement{ this.nodeFilterComponents = nodeFilters; } + /** + * Gets data types. + * @return Current data types. + */ + public Map<String, DataTypeDataDefinition> getDataTypes() { + return dataTypes; + } + + /** + * Sets data types. + * @param dataTypes New data types. + */ + public void setDataTypes(Map<String, DataTypeDataDefinition> dataTypes) { + this.dataTypes = dataTypes; + } + /** * Adds component instance to composition of topology template * Note that component instance will be overrided in case if the topology template already contains a component instance with the same name diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java index 417577320c..b0bfc153f4 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java @@ -22,19 +22,8 @@ package org.openecomp.sdc.be.model.jsontitan.operations; import com.google.gson.reflect.TypeToken; import fj.data.Either; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; @@ -47,6 +36,7 @@ import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; @@ -72,7 +62,6 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DistributionStatusEnum; import org.openecomp.sdc.be.model.GroupDefinition; - import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.category.CategoryDefinition; @@ -92,6 +81,19 @@ import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.ValidationUtils; import org.springframework.beans.factory.annotation.Autowired; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + @org.springframework.stereotype.Component("topology-template-operation") public class TopologyTemplateOperation extends ToscaElementOperation { @@ -777,9 +779,29 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(storageStatus)); } } + + if (!componentParametersView.isIgnoreDataType()) { + TitanOperationStatus storageStatus = setDataTypesFromGraph(componentV, toscaElement); + if (storageStatus != TitanOperationStatus.OK) { + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(storageStatus)); + } + } + return Either.left(toscaElement); } + private TitanOperationStatus setDataTypesFromGraph(GraphVertex componentV, TopologyTemplate toscaElement) { + Either<Map<String, DataTypeDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.DATA_TYPES); + if (result.isLeft()) { + toscaElement.setDataTypes(result.left().value()); + } else { + if (result.right().value() != TitanOperationStatus.NOT_FOUND) { + return result.right().value(); + } + } + return TitanOperationStatus.OK; + } + private TitanOperationStatus setPoliciesFromGraph(GraphVertex componentV, TopologyTemplate toscaElement) { Either<Map<String, PolicyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.POLICIES); if (result.isLeft()) { 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 10dd919fc7..8456486bef 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 @@ -20,6 +20,7 @@ package org.openecomp.sdc.be.model.jsontitan.operations; +import com.datastax.driver.core.DataType; import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -46,6 +47,7 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.resources.data.ComponentMetadataData; +import org.openecomp.sdc.be.resources.data.DataTypeData; import org.openecomp.sdc.common.jsongraph.util.CommonUtility; import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum; import org.openecomp.sdc.common.log.wrappers.Logger; @@ -171,6 +173,7 @@ public class ToscaOperationFacade { VertexTypeEnum label = componentV.getLabel(); ToscaElementOperation toscaOperation = getToscaElementOperation(componentV); + log.debug("getToscaElementByOperation: toscaOperation={}", toscaOperation.getClass()); Either<ToscaElement, StorageOperationStatus> toscaElement; String componentId = componentV.getUniqueId(); if (toscaOperation != null) { @@ -971,7 +974,74 @@ public class ToscaOperationFacade { } - public Either<List<InputDefinition>, StorageOperationStatus> getComponentInputs(String componentId) { + /** + * Add data types into a Component. + * + * @param dataTypes datatypes to be added. the key should be each name of data type. + * @param componentId unique ID of Component. + * @return list of data types. + */ + public Either<List<DataTypeDefinition>, StorageOperationStatus> addDataTypesToComponent(Map<String, DataTypeDefinition> dataTypes, String componentId) { + + log.trace("#addDataTypesToComponent - enter, componentId={}", componentId); + + /* get component vertex */ + Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); + if (getVertexEither.isRight()) { + /* not found / error */ + log.debug(COULDNT_FETCH_COMPONENT_WITH_AND_UNIQUE_ID_ERROR, componentId, getVertexEither.right().value()); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value())); + } + GraphVertex vertex = getVertexEither.left().value(); + log.trace("#addDataTypesToComponent - get vertex ok"); + + // convert DataTypeDefinition to DataTypeDataDefinition + Map<String, DataTypeDataDefinition> dataTypeDataMap = dataTypes.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> convertDataTypeToDataTypeData(e.getValue()))); + + // add datatype(s) to the Component. + // if child vertex does not exist, it will be created. + StorageOperationStatus status = topologyTemplateOperation.addToscaDataToToscaElement(vertex, + EdgeLabelEnum.DATA_TYPES, VertexTypeEnum.DATA_TYPES, dataTypeDataMap, JsonPresentationFields.NAME); + + if (StorageOperationStatus.OK == status) { + log.debug(COMPONENT_CREATED_SUCCESSFULLY); + List<DataTypeDefinition> inputsResList = null; + if (!dataTypes.isEmpty()) { + inputsResList = new ArrayList<>(dataTypes.values()); + } + return Either.left(inputsResList); + } + + log.trace("#addDataTypesToComponent - leave"); + return Either.right(status); + } + + private DataTypeDataDefinition convertDataTypeToDataTypeData(DataTypeDefinition dataType) { + DataTypeDataDefinition dataTypeData = new DataTypeDataDefinition(dataType); + if (CollectionUtils.isNotEmpty(dataType.getProperties())) { + List<PropertyDataDefinition> propertyDataList = dataType.getProperties().stream() + .map(PropertyDataDefinition::new).collect(Collectors.toList()); + dataTypeData.setPropertiesData(propertyDataList); + } + + // if "derivedFrom" data_type exists, copy the name to "derivedFromName" + if (dataType.getDerivedFrom() != null && StringUtils.isNotEmpty(dataType.getDerivedFrom().getName())) { + // if names are different, log it + if (!StringUtils.equals(dataTypeData.getDerivedFromName(), dataType.getDerivedFrom().getName())) { + log.debug("#convertDataTypeToDataTypeData - derivedFromName(={}) overwritten by derivedFrom.name(={})", + dataType.getDerivedFromName(), dataType.getDerivedFrom().getName()); + } + dataTypeData.setDerivedFromName(dataType.getDerivedFrom().getName()); + } + + // supply "name" field to toscaPresentationValue in each datatype object for DAO operations + dataTypeData.setToscaPresentationValue(JsonPresentationFields.NAME, dataType.getName()); + return dataTypeData; + } + + + public Either<List<InputDefinition>, StorageOperationStatus> getComponentInputs(String componentId) { Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); if (getVertexEither.isRight()) { @@ -2068,6 +2138,16 @@ public class ToscaOperationFacade { return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputName, JsonPresentationFields.NAME); } + /** + * Deletes a data type from a component. + * @param component the container which has the data type + * @param dataTypeName the data type name to be deleted + * @return Operation result. + */ + public StorageOperationStatus deleteDataTypeOfComponent(Component component, String dataTypeName) { + return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.DATA_TYPES, VertexTypeEnum.DATA_TYPES, dataTypeName, JsonPresentationFields.NAME); + } + public Either<PropertyDefinition, StorageOperationStatus> updatePropertyOfComponent(Component component, PropertyDefinition newPropertyDefinition) { 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 808fdbd4f6..cfd00a5313 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 @@ -23,9 +23,11 @@ package org.openecomp.sdc.be.model.jsontitan.utils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.ListUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; import org.openecomp.sdc.be.datatypes.elements.*; @@ -152,6 +154,8 @@ public class ModelConverter { convertServiceInterfaces(topologyTemplate, service); + convertDataTypes(topologyTemplate, service); + convertNodeFiltersComponents(topologyTemplate, service); setCapabilitiesToComponent(topologyTemplate, service); setRequirementsToComponent(topologyTemplate, service); @@ -205,6 +209,7 @@ public class ModelConverter { convertProperties(topologyTemplate, resource); setCapabilitiesToComponent(topologyTemplate, resource); setRequirementsToComponent(topologyTemplate, resource); + convertDataTypes(topologyTemplate, resource); } convertArtifacts(toscaElement, resource); convertAdditionalInformation(toscaElement, resource); @@ -1106,6 +1111,26 @@ public class ModelConverter { } } + private static void convertDataTypes(TopologyTemplate topologyTemplate, Component component) { + Map<String, DataTypeDataDefinition> dataTypeDataMap = topologyTemplate.getDataTypes(); + if (MapUtils.isNotEmpty(dataTypeDataMap)) { + List<DataTypeDefinition> dataTypeMap = dataTypeDataMap.values().stream().map(e -> { + DataTypeDefinition dataType = new DataTypeDefinition(e); + + if(CollectionUtils.isNotEmpty(e.getPropertiesData())) { + log.debug("#convertDataTypes - propertiesData is not null. {}", + ReflectionToStringBuilder.toString(e.getPropertiesData())); + dataType.setProperties(e.getPropertiesData().stream() + .map(PropertyDefinition::new).collect(Collectors.toList())); + } else { + log.debug("#convertDataTypes - propertiesData is null. ignore."); + } + return dataType; + }).collect(Collectors.toList()); + component.setDataTypes(dataTypeMap); + } + } + private static void convertCommonToscaData(Component component, ToscaElement toscaElement) { toscaElement.setUUID(component.getUUID()); @@ -1168,6 +1193,7 @@ public class ModelConverter { + private static void setComponentInstancesToComponent(TopologyTemplate topologyTemplate, Component component) { List<ComponentInstance> componentInstances = new ArrayList<>(); diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/ComponentParametersViewTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/ComponentParametersViewTest.java index d84b821950..7f8ea5184c 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/ComponentParametersViewTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/ComponentParametersViewTest.java @@ -7,6 +7,8 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import java.util.LinkedList; +import static org.junit.Assert.assertSame; + public class ComponentParametersViewTest { private ComponentParametersView createTestSubject() { @@ -449,6 +451,26 @@ public class ComponentParametersViewTest { @Test + public void testIsIgnoreNodeFilterWithTrue() throws Exception { + ComponentParametersView testSubject; + + testSubject = createTestSubject(); + testSubject.setIgnoreNodeFilter(true); + assertSame(testSubject.isIgnoreNodeFilter(), true); + } + + + @Test + public void testIsIgnoreNodeFilterWithFalse() throws Exception { + ComponentParametersView testSubject; + + testSubject = createTestSubject(); + testSubject.setIgnoreNodeFilter(false); + assertSame(testSubject.isIgnoreNodeFilter(), false); + } + + + @Test public void testDetectParseFlag() throws Exception { ComponentParametersView testSubject; JsonParseFlagEnum result; @@ -457,4 +479,4 @@ public class ComponentParametersViewTest { testSubject = createTestSubject(); result = testSubject.detectParseFlag(); } -}
\ No newline at end of file +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplateTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplateTest.java index 72ca0c0cab..c13ddd3970 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplateTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplateTest.java @@ -5,6 +5,7 @@ import java.util.Map; import org.junit.Test; import org.openecomp.sdc.be.datatypes.elements.*; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.DataTypeDefinition; public class TopologyTemplateTest { @@ -366,10 +367,29 @@ public class TopologyTemplateTest { } + @Test + public void testGetDataTypes() throws Exception { + TopologyTemplate testSubject; + Map<String, DataTypeDataDefinition> result; + // default test + testSubject = createTestSubject(); + result = testSubject.getDataTypes(); + } @Test + public void testSetDataTypes() throws Exception { + TopologyTemplate testSubject; + Map<String, DataTypeDataDefinition> dataTypes = null; + + // default test + testSubject = createTestSubject(); + testSubject.setDataTypes(dataTypes); + } + + + @Test public void testGetComponentInstances() throws Exception { TopologyTemplate testSubject; Map<String, ComponentInstanceDataDefinition> result; diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperationTest.java index 8bb252ea12..4ace70b34f 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperationTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperationTest.java @@ -26,11 +26,10 @@ import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; @@ -107,6 +106,23 @@ public class TopologyTemplateOperationTest { } @Test + public void testSetDataTypesFromGraph() { + GraphVertex containerVertex = new GraphVertex(); + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstancesInterfaces(true); + filter.setIgnoreDataType(false); + String componentName = "componentName"; + String componentId = UniqueIdBuilder.buildResourceUniqueId(); + containerVertex.setVertex(Mockito.mock(TitanVertex.class)); + containerVertex.setJsonMetadataField(JsonPresentationFields.NAME, componentName); + containerVertex.setUniqueId(componentId); + containerVertex.setLabel(VertexTypeEnum.TOPOLOGY_TEMPLATE); + when(titanDao.getChildVertex(any(GraphVertex.class), any(EdgeLabelEnum.class), any(JsonParseFlagEnum.class))).thenReturn(Either.right(TitanOperationStatus.GENERAL_ERROR)); + Either<ToscaElement, StorageOperationStatus> storageOperationStatus = topologyTemplateOperation.getToscaElement(containerVertex, filter); + assertThat(storageOperationStatus).isEqualTo(Either.right(StorageOperationStatus.GENERAL_ERROR)); + } + + @Test public void testUpdateDistributionStatus() { Either<GraphVertex, StorageOperationStatus> result; String uniqueId = "uniqueId"; diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacadeTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacadeTest.java index 63856e6515..0eb0b3c6d2 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacadeTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacadeTest.java @@ -61,6 +61,9 @@ import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition; import static org.assertj.core.api.Assertions.assertThat; @@ -73,6 +76,8 @@ import java.util.Set; import java.util.HashSet; import java.util.stream.Collectors; import java.util.stream.IntStream; +import java.util.Collections; +import java.util.Arrays; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; @@ -81,11 +86,11 @@ import static org.mockito.Mockito.when; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @RunWith(MockitoJUnitRunner.class) public class ToscaOperationFacadeTest { - @InjectMocks private ToscaOperationFacade testInstance; @@ -482,6 +487,103 @@ public class ToscaOperationFacadeTest { return toscaElement; } + @Test + public void addDataTypesToComponentSuccessTest(){ + Either<List<DataTypeDefinition>, StorageOperationStatus> result = addDataTypesToComponentWithStatus(StorageOperationStatus.OK); + assertTrue(result.isLeft()); + } + + @Test + public void addDataTypesToComponentFailureTest_BadRequest(){ + Either<List<DataTypeDefinition>, StorageOperationStatus> result = addDataTypesToComponentWithStatus(StorageOperationStatus.BAD_REQUEST); + assertTrue(result.isRight() && result.right().value() == StorageOperationStatus.BAD_REQUEST); + } + + private Either<List<DataTypeDefinition>, StorageOperationStatus> addDataTypesToComponentWithStatus(StorageOperationStatus status) { + Map<String, DataTypeDefinition> dataTypes = new HashMap<>(); + String componentId = "componentid"; + String Id = "id"; + + PropertyDefinition noDefaultProp = new PropertyDefinition(); + noDefaultProp.setName("noDefaultProp"); + PropertyDefinition prop1 = new PropertyDefinition(); + prop1.setDefaultValue("def1"); + prop1.setName("prop1"); + PropertyDefinition prop2 = new PropertyDefinition(); + prop2.setType("dataType1"); + prop2.setName("prop2"); + PropertyDefinition prop3 = new PropertyDefinition(); + prop3.setDefaultValue("def3"); + prop3.setName("prop3"); + + DataTypeDefinition noDefaultValue = new DataTypeDefinition(); + noDefaultValue.setProperties(Collections.singletonList(noDefaultProp)); + noDefaultValue.setDerivedFromName("name0"); + + DataTypeDefinition dataType1 = new DataTypeDefinition(); + dataType1.setProperties(Arrays.asList(prop1, prop3)); + dataType1.setName("name1"); + dataType1.setDerivedFromName("derivedfromname1"); + + DataTypeDefinition dataType2 = new DataTypeDefinition(); + dataType2.setDerivedFrom(dataType1); + dataType2.setName("name2"); + dataType2.setDerivedFromName("derivedfromname2"); + + DataTypeDefinition dataType3 = new DataTypeDefinition(); + dataType3.setProperties(Collections.singletonList(prop2)); + dataType3.setDerivedFrom(noDefaultValue); + dataType3.setName("name3"); + dataType3.setDerivedFromName("derivedfromname3"); + + dataTypes.put("noDefault", noDefaultValue); + dataTypes.put("dataType1", dataType1); + dataTypes.put("dataType2", dataType2); + dataTypes.put("dataType3", dataType3); + + GraphVertex vertex; + if(status == StorageOperationStatus.OK){ + vertex = getTopologyTemplateVertex(); + } else { + vertex = getNodeTypeVertex(); + } + Either<GraphVertex, TitanOperationStatus> getVertexEither = Either.left(vertex); + when(titanDaoMock.getVertexById(componentId, JsonParseFlagEnum.NoParse)).thenReturn(getVertexEither); + when(topologyTemplateOperationMock.addToscaDataToToscaElement(eq(vertex), + eq(EdgeLabelEnum.DATA_TYPES), eq(VertexTypeEnum.DATA_TYPES), anyMap(), eq(JsonPresentationFields.NAME))).thenReturn(status); + return testInstance.addDataTypesToComponent(dataTypes, componentId); + } + + @Test + public void testDataTypesToComponentFailureTest_NotFound() { + Either<List<DataTypeDefinition>, StorageOperationStatus> result; + String componentId = "componentId"; + GraphVertex vertex = getNodeTypeVertex(); + Map<String, DataTypeDefinition> dataTypes = new HashMap<>(); + when(titanDaoMock.getVertexById(componentId, JsonParseFlagEnum.NoParse)).thenReturn(Either.right(TitanOperationStatus.NOT_FOUND)); + result = testInstance.addDataTypesToComponent(dataTypes, componentId); + assertTrue(result.isRight() && result.right().value() == StorageOperationStatus.NOT_FOUND); + } + + @Test + public void testDeleteDataTypeOfComponent() { + StorageOperationStatus result; + Component component = new Resource(); + String id = "id"; + component.setUniqueId(id); + String datatype = null; + + DataTypeDefinition dataType1 = new DataTypeDefinition(); + dataType1.setName("name1"); + Map<String, DataTypeDataDefinition> dataTypeDataMap = new HashMap<>(); + dataTypeDataMap.put("datatype1", dataType1); + List<DataTypeDefinition> dataTypeMap = dataTypeDataMap.values().stream().map(e -> { DataTypeDefinition dataType = new DataTypeDefinition(e);return dataType; }).collect(Collectors.toList()); + component.setDataTypes(dataTypeMap); + GraphVertex graphVertex = getTopologyTemplateVertex(); + result = testInstance.deleteDataTypeOfComponent(component, "datatype1"); + assertEquals(datatype, result); + } + private Either<PolicyDefinition, StorageOperationStatus> associatePolicyToComponentWithStatus(StorageOperationStatus status) { PolicyDefinition policy = new PolicyDefinition(); String componentId = "componentId"; diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index cd488d9cd1..b541beb3d7 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -81,6 +81,7 @@ import {RequirementsEditorModule} from "./pages/req-and-capabilities-editor/requ import {CapabilitiesEditorModule} from "./pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module" import {GenericArtifactBrowserModule} from "./components/logic/generic-artifact-browser/generic-artifact-browser.module"; import {GabService} from "./services/gab.service"; +import {DeclareListModule} from "./pages/properties-assignment/declare-list/declare-list.module" export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule)); @@ -114,6 +115,7 @@ export function configServiceFactory(config: ConfigService) { ConnectionWizardModule, PropertiesAssignmentModule, PropertyCreatorModule, + DeclareListModule, PluginFrameModule, InterfaceOperationModule, OperationCreatorModule, 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 167509b1e6..0cc188134f 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 @@ -45,7 +45,8 @@ export class PropertiesTableComponent { @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() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption and hasDeclareListOption + @Output() updateCheckedChildPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareListOption @Output() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>(); private selectedPropertyToDelete: PropertyFEModel; @@ -94,6 +95,11 @@ export class PropertiesTableComponent { this.propertiesService.disableRelatedProperties(prop, childPropName); } this.updateCheckedPropertyCount.emit(isChecked); + + if (childPropName) { + let isCount: boolean = (isChecked)? true : false ; + this.updateCheckedChildPropertyCount.emit(isCount); + } } onDeleteProperty = () => { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.html new file mode 100644 index 0000000000..c0bcc7885e --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.html @@ -0,0 +1,83 @@ +<!-- +* ============LICENSE_START======================================================= +* SDC +* ================================================================================ +* Copyright (C) 2019 Fujitsu Limited. 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========================================================= +*/ +--> + +<div class="declare-list"> + <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">Type</label> + <input class="i-sdc-form-input" + type="text" + data-tests-id="property-type" + value="list" + disabled + autofocus/> + </div> + </div> + + <!-- Schema Type --> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label required">New Schema Type for List</label> + <input class="i-sdc-form-input" + type="text" + name="typeName" + [(ngModel)]="propertyModel.simpleType" + [ngModelOptions]="{ debounce: 200 }"> + </div> + + <!-- Properties --> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label">Properties</label> + <input class="i-sdc-form-input" + type="text" + name="properties" + data-tests-id="properties" + value="{{propertiesListString}}" + disabled> + </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/declare-list/declare-list.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.less new file mode 100644 index 0000000000..8d6638901f --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.less @@ -0,0 +1,35 @@ +@import '../../../../../assets/styles/variables.less'; + +.declare-list { + 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/declare-list/declare-list.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts new file mode 100644 index 0000000000..20e04f84b6 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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========================================================= + */ + +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"; +import { ModalService } from "app/ng2/services/modal.service"; +import { InstancePropertiesAPIMap } from "app/models/properties-inputs/property-fe-map"; +import { ModalModel } from "app/models/modal"; +import { DataTypeModel } from "app/models/data-types"; + + + +@Component({ + selector: 'declare-list', + templateUrl: './declare-list.component.html', + styleUrls:['./declare-list.component.less'], +}) + +export class DeclareListComponent { + + 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; + inputsToCreate:InstancePropertiesAPIMap; + propertiesListString:string; + privateDataType: DataTypeModel; + + constructor(protected dataTypeService:DataTypeService, private modalService:ModalService) {} + + ngOnInit() { + console.log('DeclareListComponent.ngOnInit() - enter'); + 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...')); + + this.inputsToCreate = this.modalService.currentModal.instance.dynamicContent.instance.input.properties; + + this.propertiesListString = this.modalService.currentModal.instance.dynamicContent.instance.input.propertyNameList.join(", "); + + this.privateDataType = new DataTypeModel(null); + this.privateDataType.name = "datatype"; + + console.log('DeclareListComponent.ngOnInit() - leave'); + } + + 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/declare-list/declare-list.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts new file mode 100644 index 0000000000..54af76a9f5 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2019 Fujitsu Limited. 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========================================================= + */ + +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {DeclareListComponent} from "./declare-list.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: [ + DeclareListComponent, + ], + imports: [ + CommonModule, + FormsModule, + FormElementsModule, + UiElementsModule, + TranslateModule + ], + exports: [], + entryComponents: [ + DeclareListComponent + ], + providers: [] +}) + +export class DeclareListModule {} 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 1ec6df9bc1..580c36284b 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 @@ -35,6 +35,7 @@ (selectPropertyRow)="selectPropertyRow($event)" (selectChildProperty)="selectChildProperty($event)" (updateCheckedPropertyCount)="updateCheckedPropertyCount($event)" + (updateCheckedChildPropertyCount)="updateCheckedChildPropertyCount($event)" (selectInstanceRow)="selectInstanceRow($event)" (deleteProperty)="deleteProperty($event)"> </properties-table> @@ -73,6 +74,7 @@ </div> <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button declare-input">Declare Input</button> <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData || isSelf()" (click)="declarePropertiesToPolicies()" data-tests-id="declare-button declare-policy">Declare Policy</button> + <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || checkedChildPropertiesCount || isReadonly || hasChangedData" (click)="declareListProperties()" data-tests-id="declare-button declare-list-input">Create List Input</button> </div> </div> <div class="right-column"> 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 523eda2e9f..14015525f7 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 @@ -109,7 +109,7 @@ } .declare-button{ - &:first-of-type { + &:not(:last-of-type) { margin-right: 10px; } } 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 38278c9d4f..9f406f8c76 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 @@ -39,11 +39,16 @@ 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 {DeclareListComponent} from "./declare-list/declare-list.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"; +import { DataTypeService } from "app/ng2/services/data-type.service"; +import { DataTypeModel } from "app/models"; +import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils"; +import { PropertyDeclareAPIModel} from "app/models"; const SERVICE_SELF_TITLE = "SELF"; @Component({ @@ -69,6 +74,7 @@ export class PropertiesAssignmentComponent { selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty(); selectedInstanceData: ComponentInstance|GroupInstance|PolicyInstance = null; checkedPropertiesCount: number = 0; + checkedChildPropertiesCount: number = 0; hierarchyPropertiesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens'); hierarchyInstancesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass'); @@ -296,6 +302,7 @@ export class PropertiesAssignmentComponent { processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => { this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values this.checkedPropertiesCount = 0; + this.checkedChildPropertiesCount = 0; }; @@ -418,6 +425,7 @@ export class PropertiesAssignmentComponent { let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId); if (selectedInstanceData instanceof ComponentInstance) { if (!this.isInput(selectedInstanceData.originType)) { + // convert Property FE model -> Property BE model, extract only checked selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); } else { selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); @@ -436,6 +444,7 @@ export class PropertiesAssignmentComponent { .subscribe(response => { this.setInputTabIndication(response.length); this.checkedPropertiesCount = 0; + this.checkedChildPropertiesCount = 0; _.forEach(response, (input: InputBEModel) => { let newInput: InputFEModel = new InputFEModel(input); this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue); @@ -445,6 +454,123 @@ export class PropertiesAssignmentComponent { }, error => {}); //ignore error }; + declareListProperties = (): void => { + console.log('declareListProperties() - enter'); + + // get selected properties + let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []); + let propertyNameList: Array<string> = []; + let insId :string; + + angular.forEach(instancesIds, (instanceId: string): void => { + console.log("instanceId="+instanceId); + insId = instanceId; + let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId); + let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); + + if (selectedInstanceData instanceof ComponentInstance) { + if (!this.isInput(selectedInstanceData.originType)) { + // convert Property FE model -> Property BE model, extract only checked + selectedComponentInstancesProperties[instanceId] = checkedProperties; + } else { + selectedComponentInstancesInputs[instanceId] = checkedProperties; + } + } else if (selectedInstanceData instanceof GroupInstance) { + selectedGroupInstancesProperties[instanceId] = checkedProperties; + } else if (selectedInstanceData instanceof PolicyInstance) { + selectedPolicyInstancesProperties[instanceId] = checkedProperties; + } + + angular.forEach(checkedProperties, (property: PropertyBEModel) => { + propertyNameList.push(property.name); + }); + }); + + let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties); + + let modalTitle = 'Declare Properties as List Input'; + const modal = this.ModalService.createCustomModal(new ModalModel( + 'sm', /* size */ + modalTitle, /* title */ + null, /* content */ + [ /* buttons */ + new ButtonModel( + 'Save', /* text */ + 'blue', /* css class */ + () => { /* callback */ + let content:any = modal.instance.dynamicContent.instance; + + /* listInput */ + let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + let typelist: any = PROPERTY_TYPES.LIST; + let uniID: any = insId; + let boolfalse: any = false; + let schem :any = { + "empty": boolfalse, + "property": { + "type": content.propertyModel.simpleType, + "required": boolfalse + } + } + let schemaProp :any = { + "type": content.propertyModel.simpleType, + "required": boolfalse + } + + reglistInput.description = content.propertyModel.description; + reglistInput.name = content.propertyModel.name; + reglistInput.type = typelist; + reglistInput.schemaType = content.propertyModel.simpleType; + reglistInput.instanceUniqueId = uniID; + reglistInput.uniqueId = uniID; + reglistInput.required =boolfalse; + reglistInput.schema = schem; + reglistInput.schemaProperty = schemaProp; + + let input = { + componentInstInputsMap: content.inputsToCreate, + listInput: reglistInput + }; + console.log("save button clicked. input=", input); + + this.componentServiceNg2 + .createListInput(this.component, input, this.isSelf()) + .subscribe(response => { + this.setInputTabIndication(response.length); + this.checkedPropertiesCount = 0; + this.checkedChildPropertiesCount = 0; + _.forEach(response, (input: InputBEModel) => { + let newInput: InputFEModel = new InputFEModel(input); + this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue); + this.inputs.push(newInput); + // create list input does not return updated properties info, so need to reload + //this.updatePropertyValueAfterDeclare(newInput); + // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead! + this.changeSelectedInstance(this.selectedInstanceData); + + modal.instance.close(); + }); + }, error => {}); //ignore error + + } + /*, getDisabled: function */ + ), + new ButtonModel('Cancel', 'outline grey', () => { + modal.instance.close(); + }), + ], + null /* type */ + )); + // 3rd arg is passed to DeclareListComponent instance + this.ModalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList}); + modal.instance.open(); + console.log('declareListProperties() - leave'); + }; + /*** DECLARE PROPERTIES/POLICIES ***/ declarePropertiesToPolicies = (): void => { let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); @@ -609,6 +735,8 @@ export class PropertiesAssignmentComponent { handleReverseItem = (changedItem) => { changedItem = <PropertyFEModel>changedItem; this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value); + this.checkedPropertiesCount = 0; + this.checkedChildPropertiesCount = 0; }; } else if (this.isInputsTabSelected) { handleReverseItem = (changedItem) => { @@ -643,6 +771,10 @@ export class PropertiesAssignmentComponent { title: 'Saved' }); if(onSuccessFunction) onSuccessFunction(); + if(this.isPropertiesTabSelected){ + this.checkedPropertiesCount = 0; + this.checkedChildPropertiesCount = 0; + } }, () => { this.Notification.error({ @@ -698,6 +830,10 @@ export class PropertiesAssignmentComponent { console.log("CheckedProperties count is now.... " + this.checkedPropertiesCount); }; + updateCheckedChildPropertyCount = (increment: boolean): void => { + this.checkedChildPropertiesCount += (increment) ? 1 : -1; + }; + setInputTabIndication = (numInputs: number): void => { this.propertyInputTabs.setTabIndication('Inputs', numInputs); }; 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 e0884d714f..c313a3fc2f 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 @@ -307,6 +307,25 @@ export class ComponentServiceNg2 { }) } + createListInput(component:Component, input:any, isSelf:boolean):Observable<any> { + let inputs: any; + if(isSelf) { + // change componentInstanceProperties -> serviceProperties + inputs = { + componentInstInputsMap: { + serviceProperties: input.componentInstInputsMap.componentInstanceProperties + }, + listInput: input.listInput + }; + } else { + inputs = input; + } + return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/listInput', inputs) + .map(res => { + return res.json(); + }) + } + createPolicy(component:Component, policiesToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> { const policiesList = isSelf ? diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/DataTypeDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/DataTypeDataDefinition.java index 358f8ef614..a4042d9917 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/DataTypeDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/DataTypeDataDefinition.java @@ -22,6 +22,8 @@ package org.openecomp.sdc.be.datatypes.elements; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import java.util.List; + public class DataTypeDataDefinition extends ToscaDataDefinition { private String name; @@ -43,6 +45,8 @@ public class DataTypeDataDefinition extends ToscaDataDefinition { */ private Long modificationTime; + private List<PropertyDataDefinition> propertiesData; + public DataTypeDataDefinition() { } @@ -104,11 +108,19 @@ public class DataTypeDataDefinition extends ToscaDataDefinition { this.modificationTime = modificationTime; } + public List<PropertyDataDefinition> getPropertiesData() { + return propertiesData; + } + + public void setPropertiesData(List<PropertyDataDefinition> propertiesData) { + this.propertiesData = propertiesData; + } + @Override public String toString() { return "DataTypeDataDefinition [name=" + name + ", uniqueId=" + uniqueId + ", derivedFromName=" + derivedFromName + ", description=" + description + ", creationTime=" + creationTime - + ", modificationTime=" + modificationTime + "]"; + + ", modificationTime=" + modificationTime + ", propertiesData=" + propertiesData + "]"; } } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java index fed728dade..218b648742 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java @@ -75,6 +75,8 @@ public class PropertyDataDefinition extends ToscaDataDefinition { private List<GetInputValueDataDefinition> getInputValues; + private Boolean isDeclaredListInput = Boolean.FALSE; + private List<GetPolicyValueDataDefinition> getPolicyValues; public PropertyDataDefinition() { @@ -86,35 +88,36 @@ public class PropertyDataDefinition extends ToscaDataDefinition { } - public PropertyDataDefinition(PropertyDataDefinition p) { + public PropertyDataDefinition(PropertyDataDefinition propertyDataDefinition) { super(); - this.setUniqueId(p.getUniqueId()); - this.setRequired(p.isRequired()); - this.setDefaultValue(p.getDefaultValue()); - this.setDescription(p.getDescription()); - this.setSchema(p.getSchema()); - this.setPassword(p.isPassword()); - this.setType(p.getType()); - this.setName(p.getName()); - this.setValue(p.getValue()); - this.setRequired(p.isRequired()); - this.setHidden(p.isHidden()); - this.setLabel(p.getLabel()); - this.setImmutable(p.isImmutable()); - this.setParentUniqueId(p.getParentUniqueId()); - this.setOwnerId(p.getOwnerId()); - this.setGetInputValues(p.getGetInputValues()); - this.setGetPolicyValues(p.getGetPolicyValues()); - this.setInputPath(p.getInputPath()); - this.setStatus(p.getStatus()); - this.setInputId(p.getInputId()); - this.setInstanceUniqueId(p.getInstanceUniqueId()); - this.setPropertyId(p.getPropertyId()); - this.parentPropertyType = p.getParentPropertyType(); - this.subPropertyInputPath = p.getSubPropertyInputPath(); - if(isNotEmpty(p.annotations)){ - this.setAnnotations(p.annotations); + this.setUniqueId(propertyDataDefinition.getUniqueId()); + this.setRequired(propertyDataDefinition.isRequired()); + this.setDefaultValue(propertyDataDefinition.getDefaultValue()); + this.setDescription(propertyDataDefinition.getDescription()); + this.setSchema(propertyDataDefinition.getSchema()); + this.setPassword(propertyDataDefinition.isPassword()); + this.setType(propertyDataDefinition.getType()); + this.setName(propertyDataDefinition.getName()); + this.setValue(propertyDataDefinition.getValue()); + this.setRequired(propertyDataDefinition.isRequired()); + this.setHidden(propertyDataDefinition.isHidden()); + this.setLabel(propertyDataDefinition.getLabel()); + this.setImmutable(propertyDataDefinition.isImmutable()); + this.setParentUniqueId(propertyDataDefinition.getParentUniqueId()); + this.setOwnerId(propertyDataDefinition.getOwnerId()); + this.setGetInputValues(propertyDataDefinition.getGetInputValues()); + this.setGetPolicyValues(propertyDataDefinition.getGetPolicyValues()); + this.setInputPath(propertyDataDefinition.getInputPath()); + this.setStatus(propertyDataDefinition.getStatus()); + this.setInputId(propertyDataDefinition.getInputId()); + this.setInstanceUniqueId(propertyDataDefinition.getInstanceUniqueId()); + this.setPropertyId(propertyDataDefinition.getPropertyId()); + this.parentPropertyType = propertyDataDefinition.getParentPropertyType(); + this.subPropertyInputPath = propertyDataDefinition.getSubPropertyInputPath(); + if(isNotEmpty(propertyDataDefinition.annotations)){ + this.setAnnotations(propertyDataDefinition.annotations); } + this.setIsDeclaredListInput(propertyDataDefinition.getIsDeclaredListInput()); } public String getParentPropertyType() { @@ -321,13 +324,21 @@ public class PropertyDataDefinition extends ToscaDataDefinition { this.propertyId = propertyId; } + public Boolean getIsDeclaredListInput() { + return isDeclaredListInput; + } + + public void setIsDeclaredListInput(Boolean isDeclaredListInput) { + this.isDeclaredListInput = isDeclaredListInput; + } + @Override public String toString() { return "PropertyDataDefinition [uniqueId=" + uniqueId + ", type=" + type + ", required=" + required + ", definition=" + definition + ", defaultValue=" + defaultValue + ", description=" + description + ", schema=" + schema + ", password=" + password + ", name=" + name + ", value=" + value + ", label=" + label + ", hidden=" + hidden + ", immutable=" + immutable + ", inputPath=" + inputPath + ", status=" + status + ", inputId=" + inputId + ", instanceUniqueId=" - + instanceUniqueId + ", propertyId=" + propertyId + ", parentUniqueId=" + parentUniqueId + ", getInputValues=" + getInputValues - + "parentPropertyType" + parentPropertyType - + "subPropertyInputPath" + subPropertyInputPath +"]"; + + instanceUniqueId + ", propertyId=" + propertyId + ", parentUniqueId=" + parentUniqueId + ", getInputValues=" + getInputValues + ", isDeclaredListInput=" + isDeclaredListInput + + ", parentPropertyType=" + parentPropertyType + + ", subPropertyInputPath=" + subPropertyInputPath +"]"; } @Override @@ -344,6 +355,7 @@ public class PropertyDataDefinition extends ToscaDataDefinition { result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode()); result = prime * result + ((parentUniqueId == null) ? 0 : parentUniqueId.hashCode()); result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((isDeclaredListInput == null) ? 0 : isDeclaredListInput.hashCode()); return result; } @@ -446,6 +458,13 @@ public class PropertyDataDefinition extends ToscaDataDefinition { } else if (!status.equals(other.status)) { return false; } + if (isDeclaredListInput == null) { + if (other.isDeclaredListInput != null) { + return false; + } + } else if (!isDeclaredListInput.equals(other.isDeclaredListInput)) { + return false; + } return true; } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java index a0843eb81f..8d83be461f 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java @@ -45,7 +45,8 @@ public enum ComponentFieldsEnum { POLICIES("policies"), NON_EXCLUDED_POLICIES("nonExcludedPolicies"), NODE_FILTER("nodeFilter"), - COMPONENT_INSTANCES_INTERFACES("componentInstancesInterfaces") + COMPONENT_INSTANCES_INTERFACES("componentInstancesInterfaces"), + DATA_TYPES("dataTypes") ; |