+ private void addPropertiesToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) {
+ ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> {
+ Either<PropertyDefinition, StorageOperationStatus> addPropertyEither =
+ toscaOperationFacade.addPropertyToComponent(prop, currentService);
+ if (addPropertyEither.isRight()) {
+ throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+ }
+ });
+ }
+
+ private void addInputsToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) {
+ ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> {
+ InputDefinition inputDef = new InputDefinition(prop);
+ Either<InputDefinition, StorageOperationStatus> status =
+ toscaOperationFacade.addInputToComponent(prop.getName(), inputDef, currentService);
+ if (status.isRight()) {
+ throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+ }
+ });
+ }
+
+ private void removePropertiesFromService(Service currentService, List<String> subNodePropsToBeRemoved) {
+ List<PropertyDefinition> props = currentService.getProperties();
+ List<String> propsUniqueIdsToBeRemoved =
+ props.stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName())).map(PropertyDefinition::getUniqueId)
+ .collect(Collectors.toList());
+ ListUtils.emptyIfNull(props).stream().filter(prop -> propsUniqueIdsToBeRemoved.contains(prop.getUniqueId())).forEach(prop -> {
+ StorageOperationStatus status = toscaOperationFacade.deletePropertyOfComponent(currentService, prop.getName());
+ if (status != StorageOperationStatus.OK) {
+ throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+ }
+ });
+ }
+
+ private void removeInputsFromService(Service currentService, List<String> subNodePropsToBeRemoved) {
+ List<PropertyDefinition> props = currentService.getProperties();
+ List<InputDefinition> inputs = currentService.getInputs();
+ List<String> propsUniqueIdsToBeRemoved =
+ props.stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName())).map(PropertyDefinition::getUniqueId)
+ .collect(Collectors.toList());
+ ListUtils.emptyIfNull(inputs).stream().filter(input -> input.isMappedToComponentProperty() &&
+ (propsUniqueIdsToBeRemoved.contains(input.getPropertyId()) || subNodePropsToBeRemoved.contains(input.getName()))).forEach(input -> {
+ StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(currentService, input.getName());
+ if (status != StorageOperationStatus.OK) {
+ throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+ }
+ });
+ }
+
+ private void areSubstitutionNodePropertiesInUse(Service service, List<String> subNodePropsToBeRemoved) {
+ Map<String, List<ComponentInstanceProperty>> componentInstancesProps = service.getComponentInstancesProperties();
+ List<String> propsUniqueIdsToBeRemoved =
+ ListUtils.emptyIfNull(service.getProperties()).stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName()))
+ .map(PropertyDefinition::getUniqueId)
+ .collect(Collectors.toList());
+ List<String> inputsUniqueIdsToBeRemoved = ListUtils.emptyIfNull(service.getInputs()).stream()
+ .filter(input -> propsUniqueIdsToBeRemoved.contains(input.getPropertyId()) || subNodePropsToBeRemoved.contains(input.getName()))
+ .map(PropertyDefinition::getUniqueId)
+ .collect(Collectors.toList());
+ Map<String, List<String>> inUse = new HashMap<>();
+ if (componentInstancesProps != null && !componentInstancesProps.isEmpty()) {
+ componentInstancesProps.forEach((compInstanceId, listOfProps) -> {
+ List<String> propsInUse = new ArrayList<>();
+ listOfProps.stream()
+ .filter(PropertyDataDefinition::isToscaFunction)
+ .filter(compProp -> ToscaFunctionType.isGetFunction(compProp.getToscaFunction().getType()))
+ .forEach(compProp -> {
+ ToscaFunction toscaFunction = compProp.getToscaFunction();
+ ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction;
+ String propName = toscaGetFunction.getPropertyName();
+ String propUniqueId = toscaGetFunction.getPropertyUniqueId();
+ if (inputsUniqueIdsToBeRemoved.contains(propUniqueId) || propsUniqueIdsToBeRemoved.contains(propUniqueId) ||
+ subNodePropsToBeRemoved.contains(propName)) {
+ propsInUse.add(compProp.getName());
+ }
+ });
+ if (!propsInUse.isEmpty()) {
+ Optional<ComponentInstance> componentInstance = service.getComponentInstanceById(compInstanceId);
+ componentInstance.ifPresent(instance -> inUse.put(instance.getName(), propsInUse));
+ }
+
+ });
+ }
+ if (!inUse.isEmpty()) {
+ String propsInUse = inUse.entrySet().stream().map(entry -> {
+ String properties = entry.getValue().stream().map(Object::toString).collect(Collectors.joining(", "));
+ return properties + " on " + entry.getKey();
+ }).collect(Collectors.joining(", properties "));
+ throw new ByActionStatusComponentException(ActionStatus.SUBSTITUTION_NODE_TYPE_PROPERTY_IN_USE, propsInUse);
+ }
+ }
+
+
+ private boolean isSubstitutionNodeChanged(Service currentService, Service updatedService) {
+ String currentServiceType = currentService.getDerivedFromGenericType();
+ String updatedServiceType = updatedService.getDerivedFromGenericType();
+ String currentServiceVersion = currentService.getDerivedFromGenericVersion();
+ String updatedServiceVersion = updatedService.getDerivedFromGenericVersion();
+ return !(StringUtils.equals(currentServiceType, updatedServiceType) && StringUtils.equals(currentServiceVersion, updatedServiceVersion));
+ }
+
+ private List<String> getSubstitutionNodePropertiesToBeRemoved(Service currentService, Service serviceUpdate) {
+ List<PropertyDefinition> currentProps = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties());
+ List<PropertyDefinition> updatedProps = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties());
+ if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) {
+ return currentProps.stream().map(PropertyDefinition::getName).collect(Collectors.toList());
+ }
+
+ Map<String, PropertyDefinition> currentPropsMap = currentProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+ Map<String, PropertyDefinition> updatedPropsMap = updatedProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+
+ List<String> propNamesToBeRemoved = new ArrayList<>();
+ for (String currentPropertyName : currentPropsMap.keySet()) {
+ if (updatedPropsMap.containsKey(currentPropertyName)) {
+ if (!haveSameType(currentPropsMap.get(currentPropertyName), updatedPropsMap.get(currentPropertyName))) {
+ propNamesToBeRemoved.add(currentPropertyName);
+ }
+ } else {
+ propNamesToBeRemoved.add(currentPropertyName);
+ }
+ }
+
+ return propNamesToBeRemoved;
+ }
+
+ private boolean haveSameType(final PropertyDefinition property1, final PropertyDefinition property2) {
+ if (property1.getType().equals("list")) {
+ return property2.getType().equals("list") && property1.getSchema().equals(property2.getSchema());
+ }
+ if (property1.getType().equals("map")) {
+ return property2.getType().equals("map") && property1.getSchema().equals(property2.getSchema());
+ }
+ return property1.getType().equals(property2.getType());
+ }
+
+ private List<PropertyDefinition> getSubstitutionNodePropertiesToBeAdded(Service currentService, Service serviceUpdate) {
+ List<PropertyDefinition> propsInCurrentVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties());
+ List<PropertyDefinition> propsInUpdatedVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties());
+ if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) {
+ return propsInUpdatedVersion;
+ }
+
+ Map<String, PropertyDefinition> mapOfPropsInCurrentVersion = propsInCurrentVersion.stream()
+ .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+ Map<String, PropertyDefinition> mapOfPropsInUpdatedVersion = propsInUpdatedVersion.stream()
+ .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+
+ List<PropertyDefinition> propsToBeAdded = new ArrayList<>();
+ for (Entry<String, PropertyDefinition> propertyInUpdatedVersion : mapOfPropsInUpdatedVersion.entrySet()) {
+ if (mapOfPropsInCurrentVersion.containsKey(propertyInUpdatedVersion.getKey())) {
+ if (!haveSameType(mapOfPropsInCurrentVersion.get(propertyInUpdatedVersion.getKey()), propertyInUpdatedVersion.getValue())) {
+ propsToBeAdded.add(propertyInUpdatedVersion.getValue());
+ }
+ } else {
+ propsToBeAdded.add(propertyInUpdatedVersion.getValue());
+ }
+ }
+
+ return propsToBeAdded;
+ }
+
+