VFC operation not clearing artifact details when unchecked
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / merge / instance / ComponentInstanceInterfacesMerge.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20 package org.openecomp.sdc.be.components.merge.instance;
21
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
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;
41
42 @org.springframework.stereotype.Component("ComponentInstanceInterfacesMerge")
43 public class ComponentInstanceInterfacesMerge implements ComponentInstanceMergeInterface {
44
45     @Autowired
46     private ComponentsUtils componentsUtils;
47     @Autowired
48     private ToscaOperationFacade toscaOperationFacade;
49
50     @Override
51     public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance,
52                                     Component originComponent) {
53         dataHolder.setOrigInstanceNode(originComponent);
54         dataHolder.setOrigComponentInstanceInterfaces(containerComponent.safeGetComponentInstanceInterfaces(currentResourceInstance.getUniqueId()));
55     }
56
57     @Override
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));
64         } else {
65             return updatedContainerComponent;
66         }
67     }
68
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;
74         }
75         if (CollectionUtils.isEmpty(currentComponent.getComponentInstancesInterfaces().get(instanceId))) {
76             return ActionStatus.OK;
77         }
78         currentComponent.getComponentInstancesInterfaces().get(instanceId).forEach(
79             newInterfaceDef -> {
80                 Map<String, Operation> newInterfaceDefOperationMap = newInterfaceDef.getOperationsMap();
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<>());
92                                     }
93                                     mergeOperationInputDefinitions(oldOperationDef.getInputs(), newOperationDefKeyValue.getInputs(),
94                                         originalOperationDef.getInputs());
95                                 }
96                                 if (originalValueOverwritten(originalOperationDef.getImplementation(), oldOperationDef.getImplementation()) ) {
97                                     newOperationDefKeyValue.setImplementation(oldOperationDef.getImplementation());
98                                 }
99                                 if (originalValueOverwritten(originalOperationDef.getDescription(), oldOperationDef.getDescription())) {
100                                     newOperationDefKeyValue.setDescription(oldOperationDef.getDescription());
101                                 }
102                                 newInterfaceDefOperationMap.put(newOperationDefKey, newOperationDefKeyValue);
103                             })));
104                 newInterfaceDef.setOperationsMap(newInterfaceDefOperationMap);
105             });
106         StorageOperationStatus updateStatus = toscaOperationFacade.updateComponentInstanceInterfaces(currentComponent, instanceId);
107         return componentsUtils.convertFromStorageResponse(updateStatus);
108     }
109     
110     private <T> boolean originalValueOverwritten(final T originalValue, final T oldValue) {
111         if (originalValue == null) {
112             return oldValue != null;
113         }
114         return !originalValue.equals(oldValue);
115     }
116
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()))
125                             .findFirst();
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());
130                     }
131                 }));
132         oldInputs.getListToscaDataDefinition().stream()
133         .filter(oldInput -> newInputs.getListToscaDataDefinition().stream().noneMatch(newInput -> newInput.getName().equals(oldInput.getName())))
134         .forEach(oldInput -> newInputs.getListToscaDataDefinition().add(oldInput));
135     }
136 }