aad2eb4412c6d8bbac2a7ad0f842842a846d3b78
[sdc.git] /
1 package org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.relations;
2
3 import fj.Function;
4 import fj.data.Either;
5 import org.apache.commons.lang3.tuple.ImmutablePair;
6 import org.openecomp.sdc.asdctool.impl.migration.MigrationException;
7 import org.openecomp.sdc.asdctool.impl.migration.v1707.MigrationUtils;
8 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
9 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
10 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
11 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
12 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
13 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
14 import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition;
15 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
16 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
17 import org.openecomp.sdc.be.model.Component;
18 import org.openecomp.sdc.be.model.ComponentInstance;
19 import org.openecomp.sdc.be.model.jsontitan.operations.TopologyTemplateOperation;
20 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
21 import org.openecomp.sdc.be.model.operations.api.ToscaDefinitionPathCalculator;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import javax.annotation.Resource;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.stream.Collectors;
31
32 import static org.openecomp.sdc.asdctool.impl.migration.MigrationMsg.*;
33 import static org.openecomp.sdc.asdctool.impl.migration.v1707.MigrationUtils.willThrowException;
34
35 public abstract class FulfilledCapabilityRequirementMigrationService<T extends ToscaDataDefinition, S extends GraphNode> {
36
37     private static Logger LOGGER = LoggerFactory.getLogger(FulfilledCapabilityRequirementMigrationService.class);
38
39     @Resource(name = "topology-template-operation")
40     TopologyTemplateOperation topologyTemplateOperation;
41
42     @Resource(name = "tosca-path-calculator")
43     private ToscaDefinitionPathCalculator toscaDefinitionPathCalculator;
44
45     @Resource(name = "titan-dao")
46     TitanDao titanDao;
47
48     public boolean associateToscaDefinitions(Component component, NodeTypeEnum componentType) {
49         try {
50             return isDefinitionsAlreadyAssociated(component) || doAssociateToscaDefinitions(component, componentType);
51         } catch (MigrationException e) {
52             LOGGER.error(e.getMessage(), e);
53             return false;
54         }
55     }
56
57     private boolean isDefinitionsAlreadyAssociated(Component component) {
58         GraphVertex componentVertex =  titanDao.getVertexById(component.getUniqueId()).left().on((err) -> willThrowException(FAILED_TO_RETRIEVE_VERTEX.getMessage(component.getName(), err.name())));
59         return this.getAssociatedDefinitions(componentVertex)
60                    .either(vertex -> true,
61                            errorStatus -> notFoundStatusOrFail(component, errorStatus));
62
63     }
64
65     private boolean notFoundStatusOrFail(Component component, TitanOperationStatus error) {
66         if (error.equals(TitanOperationStatus.NOT_FOUND)) {
67             return false;
68         }
69         throw new MigrationException(FAILED_TO_RETRIEVE_CAP_REQ_VERTEX.getMessage(component.getName(), error.name()));
70     }
71
72     private boolean doAssociateToscaDefinitions(Component component, NodeTypeEnum componentType) {
73         try {
74             Map<String, MapDataDefinition> toscaDefByInstance = groupToscaDefinitionByInstance(component, componentType);
75             return toscaDefByInstance.isEmpty() || updateOnGraph(component, toscaDefByInstance);
76         } catch (MigrationException e) {
77             LOGGER.error(e.getMessage(), e);
78             return false;
79         }
80     }
81
82     private  Map<String, MapDataDefinition> groupToscaDefinitionByInstance(Component component, NodeTypeEnum componentType) {
83         Map<String, MapDataDefinition> toscaDefByInstance = new HashMap<>();
84         for (ComponentInstance componentInstance : component.getComponentInstances()) {
85                 List<ImmutablePair<S, GraphEdge>> fulfilledCapReq = getFulfilledCapReqs(componentType, componentInstance);
86                 if (fulfilledCapReq.isEmpty()) {
87                     continue;
88                 }
89                 toscaDefByInstance.put(componentInstance.getUniqueId(), getReqCapToscaDefs(fulfilledCapReq, componentInstance));
90         }
91         return toscaDefByInstance;
92     }
93
94     private MapDataDefinition getReqCapToscaDefs(List<ImmutablePair<S, GraphEdge>> capReqsData, ComponentInstance componentInstance) {
95         Map<String, List<T>> capReqDefinitions = getCapReqDefinitions(componentInstance, capReqsData);
96         return convertToMapDefinition(capReqDefinitions);
97     }
98
99     private List<ImmutablePair<S, GraphEdge>> getFulfilledCapReqs(NodeTypeEnum componentType, ComponentInstance componentInstance) {
100         return getFulfilledCapReqs(componentInstance, componentType)
101                 .either(Function.identity(),
102                         error ->  emptyListOrFail(error, componentInstance.getName()));
103     }
104
105     private List<ImmutablePair<S, GraphEdge>> emptyListOrFail(TitanOperationStatus error, String instanceName) {
106         if (error.equals(TitanOperationStatus.NOT_FOUND)) {
107             return Collections.emptyList();
108         }
109         String errorMsg = FAILED_TO_RETRIEVE_REQ_CAP.getMessage(instanceName, error.name());
110         throw new MigrationException(errorMsg);
111     }
112
113     private Map<String, List<T>> getCapReqDefinitions(ComponentInstance componentInstance, List<ImmutablePair<S, GraphEdge>> capReqDataList) {
114         return capReqDataList.stream()
115                 .map(capReqData -> convertToToscaDef(componentInstance, capReqData))
116                 .collect(Collectors.groupingBy(this::getType));
117     }
118
119     private T convertToToscaDef(ComponentInstance componentInstance, ImmutablePair<S, GraphEdge> data) {
120         T def = getReqCapDataDefinition(data);
121         List<String> definitionPath = toscaDefinitionPathCalculator.calculateToscaDefinitionPath(componentInstance, data.getRight());
122         setPath(def, definitionPath);
123         return def;
124     }
125
126     private T getReqCapDataDefinition(ImmutablePair<S, GraphEdge> data) {
127         S capReqData = data.getLeft();
128         return getToscaDefinition(capReqData).left().on(err -> willThrowException(FAILED_TO_RETRIEVE_TOSCA_DEF.getMessage(capReqData.getUniqueId().toString(), err.toString())));
129     }
130
131     private boolean updateOnGraph(Component component, Map<String, MapDataDefinition> defsByInstance) {
132         GraphVertex graphVertex = getComponentGraphVertex(component);
133         Either<GraphVertex, StorageOperationStatus> associatedVertex = associateToGraph(graphVertex, defsByInstance);
134         return associatedVertex.either(vertex -> true, err -> MigrationUtils.handleError(FAILED_TO_ASSOCIATE_CAP_REQ.getMessage(component.getName(), err.name())));
135     }
136
137     private GraphVertex getComponentGraphVertex(Component component) {
138         return titanDao.getVertexById(component.getUniqueId())
139                        .left().on(error -> willThrowException(FAILED_TO_RETRIEVE_VERTEX.getMessage(component.getUniqueId(), error.name())));
140     }
141
142     private MapDataDefinition convertToMapDefinition(Map<String, List<T>> toscaDefs) {
143         Map<String, ListDataDefinition> defsListByType = toscaDefs.entrySet().stream()
144                 .collect(Collectors.toMap(Map.Entry::getKey, entry -> convertToDefinitionListObject(entry.getValue())));
145         return convertToDefinitionMapObject(defsListByType);
146     }
147
148     abstract Either<T, ?> getToscaDefinition(S data);
149
150     abstract void setPath(T def, List<String> path);
151
152     abstract String getType(T def);
153
154     abstract Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> getFulfilledCapReqs(ComponentInstance instance, NodeTypeEnum nodeTypeEnum);
155
156     abstract ListDataDefinition convertToDefinitionListObject(List<T> capReqDefList);
157
158     abstract MapDataDefinition convertToDefinitionMapObject(Map<String, ListDataDefinition> reqCapForInstance);
159
160     abstract Either<GraphVertex, TitanOperationStatus> getAssociatedDefinitions(GraphVertex component);
161
162     abstract Either<GraphVertex, StorageOperationStatus> associateToGraph(GraphVertex graphVertex, Map<String, MapDataDefinition> defsByInstance);
163
164 }