Sync Integ to Master
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / merge / utils / MergeInstanceUtils.java
1 package org.openecomp.sdc.be.components.merge.utils;
2
3 import fj.data.Either;
4 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
5 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
6 import org.openecomp.sdc.be.model.Component;
7 import org.openecomp.sdc.be.model.ComponentInstance;
8 import org.openecomp.sdc.be.model.Resource;
9 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
10 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
11 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired;
15
16 import com.google.common.annotations.VisibleForTesting;
17 import java.util.*;
18 import java.util.stream.Collectors;
19
20 import static java.util.function.Function.identity;
21
22 /**
23  * This class is Utils class but it should be bean
24  * @author dr2032
25  *
26  */
27 @org.springframework.stereotype.Component("MergeInstanceUtils")
28 public class MergeInstanceUtils {
29     private Logger log = LoggerFactory.getLogger(MergeInstanceUtils.class);
30     
31     @Autowired
32     private ToscaOperationFacade toscaOperationFacade;
33
34     /**
35      * Maps capability owner IDs of old component instance to capability owner IDs of the new component instance
36      * @param container containing new component instance
37      * @param origInstanceNode old component (in case of PROXY it should be actual service)
38      * @param newInstanceId - ID of new instance of the component
39      * @param oldCapabilitiesOwnerIds
40      * @return
41      */
42     public Map<String, String> mapOldToNewCapabilitiesOwnerIds(Component container,
43                                                                Component origInstanceNode,
44                                                                String newInstanceId,
45                                                                List<String> oldCapabilitiesOwnerIds) {
46
47         Map<String, String> resultMap;
48
49         if (ModelConverter.isAtomicComponent(origInstanceNode) || isCVFC(origInstanceNode)) {
50             resultMap = prepareMapForAtomicComponent(newInstanceId, oldCapabilitiesOwnerIds);
51         }
52         else {
53             resultMap = prepareMapForNonAtomicComponent(container, origInstanceNode, newInstanceId, oldCapabilitiesOwnerIds);
54         }
55
56         return resultMap;
57     }
58
59
60     private static boolean isCVFC(Component component) {
61         ComponentTypeEnum componentType = component.getComponentType();
62         if (!componentType.equals(ComponentTypeEnum.RESOURCE)) {
63             return false;
64         }
65
66         Resource resource = (Resource) component;
67         ResourceTypeEnum resourceType = resource.getResourceType();
68         return resourceType == ResourceTypeEnum.CVFC;
69     }
70
71
72     /**
73      * Maps capability owner IDs of old component instance to capability owner IDs of the new component instance
74      * @param oldInstance
75      * @param newInstance
76      * @return
77      */
78     public Map<String, String> mapOldToNewCapabilitiesOwnerIds(ComponentInstance oldInstance, ComponentInstance newInstance) {
79         List<ComponentInstance> oldVfcInstances  = getVfcInstances(oldInstance);
80         List<ComponentInstance> newVfcInstances  = getVfcInstances(newInstance);
81
82         Map<String, ComponentInstance> newVfciNameMap = convertToVfciNameMap(newVfcInstances);
83
84         return oldVfcInstances.stream()
85                             .filter(oldVfci -> newVfciNameMap.containsKey(oldVfci.getName()))
86                             .collect(Collectors.toMap(ComponentInstance::getUniqueId, oldVfci -> newVfciNameMap.get(oldVfci.getName()).getUniqueId()));
87     }
88
89
90     /**
91      * Method converts list of Component Instances to map of the instances where the key is their name
92      * @param componentInstances
93      * @return
94      */
95     public Map<String, ComponentInstance> convertToVfciNameMap(List<ComponentInstance> componentInstances) {
96         return componentInstances != null ?
97                 componentInstances.stream()
98                             .collect(Collectors.toMap(ComponentInstance::getName, identity())): Collections.emptyMap();
99     }
100
101
102     
103     /**
104      * Returns List of componentInstances by specified componentInstance
105      * If componentInstance is for atomic component the returned list will contain the specified componentInstance only.
106      * @param componentInstance
107      * @return
108      */
109     public List<ComponentInstance> getVfcInstances(ComponentInstance componentInstance) {
110         if (componentInstance == null) {
111             return Collections.emptyList();
112         }
113
114
115         List<ComponentInstance> vfcInstances;
116
117         String componentId = componentInstance.getActualComponentUid();
118         Either<Component, StorageOperationStatus> eitherComponent = toscaOperationFacade.getToscaElement(componentId);
119
120         if(eitherComponent.isLeft()) {
121             Component component = eitherComponent.left().value();
122             vfcInstances = getVfcInstances(componentInstance, component);
123         }
124         else {
125             log.debug("Unexpected error: resource was not loaded for VF ID: {}", componentId);
126             vfcInstances =  Collections.emptyList();
127         }
128
129         return vfcInstances;
130     }
131
132
133     /**
134      * Returns List of componentInstances by specified componentInstance and component
135      * If componentInstance is for atomic component the returned list will contain the specified componentInstance only.
136      * @param componentInstance
137      * @param eitherComponent
138      * @return
139      */
140     public List<ComponentInstance> getVfcInstances(ComponentInstance componentInstance, Component component) {
141         if (componentInstance == null || component == null) {
142             return Collections.emptyList();
143         }
144
145
146         List<ComponentInstance> vfcInstances;
147
148         if (ModelConverter.isAtomicComponent(component) || isCVFC(component)) {
149             if (componentInstance.getIsProxy()) {
150                 // Component is proxy and it doesn't contain required data
151                 vfcInstances = getVfcInstances(componentInstance);
152             }
153             else {
154                 vfcInstances = Arrays.asList(componentInstance);
155             }
156         }
157         else {
158             vfcInstances = recursiveScanForAtomicComponentInstances(component);
159         }
160
161         return vfcInstances;
162     }
163
164
165     @VisibleForTesting
166     public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
167         this.toscaOperationFacade = toscaOperationFacade;
168     }
169
170
171
172     /**
173      * @param component
174      * @return
175      */
176     private List<ComponentInstance> recursiveScanForAtomicComponentInstances(Component component) {
177         List<ComponentInstance> vfcInstances;
178
179         List<ComponentInstance> componentInstances = component.getComponentInstances();
180         if (componentInstances != null) {
181             // Go recursively to collect atomic components only
182             vfcInstances = componentInstances.stream()
183                                              .map(this::getVfcInstances)
184                                              .flatMap(List::stream)
185                                              .collect(Collectors.toList());
186         }
187         else {
188             vfcInstances = Collections.emptyList();
189         }
190
191         return vfcInstances;
192     }
193
194
195
196     /**
197      * @param newInstanceId
198      * @param oldCapabilitiesOwnerIds
199      * @return
200      */
201     private Map<String, String> prepareMapForAtomicComponent(String newInstanceId, List<String> oldCapabilitiesOwnerIds) {
202         Map<String, String> resultMap;
203
204         int oldCapabilityOwnerIdsSize = oldCapabilitiesOwnerIds.size();
205         if (oldCapabilityOwnerIdsSize == 1) {
206             resultMap = new HashMap<>();
207             resultMap.put(oldCapabilitiesOwnerIds.get(0), newInstanceId);
208         }
209         else {
210             log.debug("For automic component the list of old capabilities owner Ids should contains one element while actual size is {},", oldCapabilityOwnerIdsSize);
211             resultMap = Collections.emptyMap();
212         }
213
214         return resultMap;
215     }
216
217     /**
218      * @param container
219      * @param origInstanceNode
220      * @param newInstanceId
221      * @param oldCapabilitiesOwnerIds
222      * @return
223      */
224     private Map<String, String> prepareMapForNonAtomicComponent(Component container, Component origInstanceNode,
225                                                                     String newInstanceId, List<String> oldCapabilitiesOwnerIds) {
226         Map<String, String> resultMap;
227         List<ComponentInstance> oldVfcInstances = recursiveScanForAtomicComponentInstances(origInstanceNode);
228
229         ComponentInstance newInstance = container.getComponentInstanceById(newInstanceId).orElse(null);
230         if (newInstance == null) {
231             log.debug("Failed to get component instance by newInstanceId: {}.", newInstanceId);
232             resultMap = Collections.emptyMap();
233         }
234         else {
235             resultMap = mapOldVfcIdsToNewOnes(oldCapabilitiesOwnerIds, oldVfcInstances, newInstance);
236         }
237         return resultMap;
238     }
239
240     /**
241      * @param oldCapabilitiesOwnerIds
242      * @param oldVfcInstances
243      * @param newInstance
244      * @return
245      */
246     private Map<String, String> mapOldVfcIdsToNewOnes(List<String> oldCapabilitiesOwnerIds,
247                                                                 List<ComponentInstance> oldVfcInstances, ComponentInstance newInstance) {
248         List<ComponentInstance> newVfcInstances = getVfcInstances(newInstance);
249         Map<String, ComponentInstance> newVfciNameMap = convertToVfciNameMap(newVfcInstances);
250
251         return oldVfcInstances.stream()
252                         .filter(oldVfc -> oldCapabilitiesOwnerIds.contains(oldVfc.getUniqueId()))
253                         .filter(oldVfci -> newVfciNameMap.containsKey(oldVfci.getName()))
254                         .collect(Collectors.toMap(ComponentInstance::getUniqueId, oldVfci -> newVfciNameMap.get(oldVfci.getName()).getUniqueId()));
255     }
256
257 }