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