2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.openecomp.sdc.be.components.merge.instance;
22 import java.util.HashMap;
23 import java.util.List;
25 import java.util.Optional;
26 import org.apache.commons.collections.CollectionUtils;
27 import org.apache.commons.collections.MapUtils;
28 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
31 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
32 import org.openecomp.sdc.be.impl.ComponentsUtils;
33 import org.openecomp.sdc.be.model.Component;
34 import org.openecomp.sdc.be.model.ComponentInstance;
35 import org.openecomp.sdc.be.model.ComponentInstanceInterface;
36 import org.openecomp.sdc.be.model.Operation;
37 import org.openecomp.sdc.be.model.User;
38 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
39 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
40 import org.springframework.beans.factory.annotation.Autowired;
42 @org.springframework.stereotype.Component("ComponentInstanceInterfacesMerge")
43 public class ComponentInstanceInterfacesMerge implements ComponentInstanceMergeInterface {
46 private ComponentsUtils componentsUtils;
48 private ToscaOperationFacade toscaOperationFacade;
51 public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance,
52 Component originComponent) {
53 dataHolder.setOrigInstanceNode(originComponent);
54 dataHolder.setOrigComponentInstanceInterfaces(containerComponent.safeGetComponentInstanceInterfaces(currentResourceInstance.getUniqueId()));
58 public Component mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
59 List<ComponentInstanceInterface> origInstanceInterfaces = dataHolder.getOrigComponentInstanceInterfaces();
60 ActionStatus mergeStatus = mergeComponentInstanceInterfaces(updatedContainerComponent, newInstanceId, origInstanceInterfaces,
61 dataHolder.getOrigInstanceNode());
62 if (!ActionStatus.OK.equals(mergeStatus)) {
63 throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(mergeStatus));
65 return updatedContainerComponent;
69 private ActionStatus mergeComponentInstanceInterfaces(Component currentComponent, String instanceId,
70 List<ComponentInstanceInterface> prevInstanceInterfaces,
71 Component prevInstanceOrigComponent) {
72 if (CollectionUtils.isEmpty(prevInstanceInterfaces) || MapUtils.isEmpty(currentComponent.getComponentInstancesInterfaces())) {
73 return ActionStatus.OK;
75 if (CollectionUtils.isEmpty(currentComponent.getComponentInstancesInterfaces().get(instanceId))) {
76 return ActionStatus.OK;
78 currentComponent.getComponentInstancesInterfaces().get(instanceId).forEach(
80 Map<String, Operation> newInterfaceDefOperationMap = new HashMap<>();
81 newInterfaceDef.getOperationsMap().forEach(
82 (newOperationDefKey, newOperationDefKeyValue) -> prevInstanceInterfaces.stream()
83 .filter(in -> in.getUniqueId().equals(newInterfaceDef.getUniqueId())).forEach(
84 prevInterfaceDef -> prevInterfaceDef.getOperationsMap().values().stream()
85 .filter(in1 -> in1.getUniqueId().equals(newOperationDefKeyValue.getUniqueId()))
86 .forEach(oldOperationDef -> {
87 Operation originalOperationDef = prevInstanceOrigComponent.getInterfaces().get(newInterfaceDef.getInterfaceId())
88 .getOperationsMap().get(newOperationDefKey);
89 if (oldOperationDef.getInputs() != null) {
90 if (newOperationDefKeyValue.getInputs() == null) {
91 newOperationDefKeyValue.setInputs(new ListDataDefinition<>());
93 mergeOperationInputDefinitions(oldOperationDef.getInputs(), newOperationDefKeyValue.getInputs(),
94 originalOperationDef.getInputs());
96 if (originalValueOverwritten(originalOperationDef.getImplementation(), oldOperationDef.getImplementation()) ) {
97 newOperationDefKeyValue.setImplementation(oldOperationDef.getImplementation());
99 if (originalValueOverwritten(originalOperationDef.getDescription(), oldOperationDef.getDescription())) {
100 newOperationDefKeyValue.setDescription(oldOperationDef.getDescription());
102 newInterfaceDefOperationMap.put(newOperationDefKey, newOperationDefKeyValue);
104 newInterfaceDef.setOperationsMap(newInterfaceDefOperationMap);
106 StorageOperationStatus updateStatus = toscaOperationFacade.updateComponentInstanceInterfaces(currentComponent, instanceId);
107 return componentsUtils.convertFromStorageResponse(updateStatus);
110 private <T> boolean originalValueOverwritten(final T originalValue, final T oldValue) {
111 if (originalValue == null) {
112 return oldValue != null;
114 return !originalValue.equals(oldValue);
117 private void mergeOperationInputDefinitions(ListDataDefinition<OperationInputDefinition> oldInputs,
118 ListDataDefinition<OperationInputDefinition> newInputs,
119 ListDataDefinition<OperationInputDefinition> origInputs) {
120 newInputs.getListToscaDataDefinition()
121 .forEach(newInput -> oldInputs.getListToscaDataDefinition().stream().filter(oldInput -> oldInput.getName().equals(newInput.getName()))
122 .forEach(oldInput -> {
123 Optional<OperationInputDefinition> origInput =
124 origInputs.getListToscaDataDefinition().stream().filter(input -> input.getName().equals(oldInput.getName()))
126 newInput.setSourceProperty(oldInput.getSourceProperty());
127 newInput.setSource(oldInput.getSource());
128 if (origInput.isPresent() && !origInput.get().getValue().equals(oldInput.getValue())) {
129 newInput.setValue(oldInput.getValue());
132 oldInputs.getListToscaDataDefinition().stream()
133 .filter(oldInput -> newInputs.getListToscaDataDefinition().stream().noneMatch(newInput -> newInput.getName().equals(oldInput.getName())))
134 .forEach(oldInput -> newInputs.getListToscaDataDefinition().add(oldInput));