2 * ============LICENSE_START=======================================================
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
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=========================================================
21 package org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.relations;
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;
45 import javax.annotation.Resource;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.List;
50 import java.util.stream.Collectors;
52 import static org.openecomp.sdc.asdctool.impl.migration.MigrationMsg.*;
53 import static org.openecomp.sdc.asdctool.impl.migration.v1707.MigrationUtils.willThrowException;
55 public abstract class FulfilledCapabilityRequirementMigrationService<T extends ToscaDataDefinition, S extends GraphNode> {
57 private static Logger LOGGER = LoggerFactory.getLogger(FulfilledCapabilityRequirementMigrationService.class);
59 @Resource(name = "topology-template-operation")
60 TopologyTemplateOperation topologyTemplateOperation;
62 @Resource(name = "tosca-path-calculator")
63 private ToscaDefinitionPathCalculator toscaDefinitionPathCalculator;
65 @Resource(name = "titan-dao")
68 public boolean associateToscaDefinitions(Component component, NodeTypeEnum componentType) {
70 return isDefinitionsAlreadyAssociated(component) || doAssociateToscaDefinitions(component, componentType);
71 } catch (MigrationException e) {
72 LOGGER.error(e.getMessage(), e);
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));
85 private boolean notFoundStatusOrFail(Component component, TitanOperationStatus error) {
86 if (error.equals(TitanOperationStatus.NOT_FOUND)) {
89 throw new MigrationException(FAILED_TO_RETRIEVE_CAP_REQ_VERTEX.getMessage(component.getName(), error.name()));
92 private boolean doAssociateToscaDefinitions(Component component, NodeTypeEnum componentType) {
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);
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()) {
109 toscaDefByInstance.put(componentInstance.getUniqueId(), getReqCapToscaDefs(fulfilledCapReq, componentInstance));
111 return toscaDefByInstance;
114 private MapDataDefinition getReqCapToscaDefs(List<ImmutablePair<S, GraphEdge>> capReqsData, ComponentInstance componentInstance) {
115 Map<String, List<T>> capReqDefinitions = getCapReqDefinitions(componentInstance, capReqsData);
116 return convertToMapDefinition(capReqDefinitions);
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()));
125 private List<ImmutablePair<S, GraphEdge>> emptyListOrFail(TitanOperationStatus error, String instanceName) {
126 if (error.equals(TitanOperationStatus.NOT_FOUND)) {
127 return Collections.emptyList();
129 String errorMsg = FAILED_TO_RETRIEVE_REQ_CAP.getMessage(instanceName, error.name());
130 throw new MigrationException(errorMsg);
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));
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);
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())));
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())));
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())));
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);
168 abstract Either<T, ?> getToscaDefinition(S data);
170 abstract void setPath(T def, List<String> path);
172 abstract String getType(T def);
174 abstract Either<List<ImmutablePair<S, GraphEdge>>, TitanOperationStatus> getFulfilledCapReqs(ComponentInstance instance, NodeTypeEnum nodeTypeEnum);
176 abstract ListDataDefinition convertToDefinitionListObject(List<T> capReqDefList);
178 abstract MapDataDefinition convertToDefinitionMapObject(Map<String, ListDataDefinition> reqCapForInstance);
180 abstract Either<GraphVertex, TitanOperationStatus> getAssociatedDefinitions(GraphVertex component);
182 abstract Either<GraphVertex, StorageOperationStatus> associateToGraph(GraphVertex graphVertex, Map<String, MapDataDefinition> defsByInstance);