2 * ============LICENSE_START=======================================================
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
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.be.components.merge.instance;
23 import fj.data.Either;
24 import org.apache.commons.lang3.StringUtils;
25 import org.openecomp.sdc.be.components.merge.utils.CapabilityOwner;
26 import org.openecomp.sdc.be.components.merge.utils.ComponentInstanceBuildingBlocks;
27 import org.openecomp.sdc.be.components.merge.utils.MergeInstanceUtils;
28 import org.openecomp.sdc.be.dao.utils.MapUtil;
29 import org.openecomp.sdc.be.impl.ComponentsUtils;
30 import org.openecomp.sdc.be.model.Component;
31 import org.openecomp.sdc.be.model.ComponentInstance;
32 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
33 import org.openecomp.sdc.be.model.User;
34 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
35 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
36 import org.openecomp.sdc.common.datastructure.Wrapper;
37 import org.openecomp.sdc.common.log.wrappers.Logger;
38 import org.openecomp.sdc.exception.ResponseFormat;
40 import java.util.Collections;
41 import java.util.List;
43 import java.util.Objects;
44 import java.util.function.Function;
45 import java.util.stream.Collectors;
46 import java.util.stream.Stream;
49 @org.springframework.stereotype.Component("ComponentInstanceRelashionMerge")
50 public class ComponentInstanceRelationMerge implements ComponentInstanceMergeInterface {
51 private static final Logger log = Logger.getLogger(ComponentInstanceRelationMerge.class);
53 private final ComponentsUtils componentsUtils;
54 private final MergeInstanceUtils mergeInstanceUtils;
55 private final ToscaOperationFacade toscaOperationFacade;
57 public ComponentInstanceRelationMerge(ComponentsUtils componentsUtils, MergeInstanceUtils mergeInstanceUtils, ToscaOperationFacade toscaOperationFacade) {
58 this.componentsUtils = componentsUtils;
59 this.mergeInstanceUtils = mergeInstanceUtils;
60 this.toscaOperationFacade = toscaOperationFacade;
65 public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance, Component originComponent) {
66 //All Relationships - container (service) holds info about all relations
67 //Filter by UniqueId in from/to
68 List<RequirementCapabilityRelDef> relationsFrom = getRelations(RequirementCapabilityRelDef::getFromNode,
70 currentResourceInstance);
72 List<RequirementCapabilityRelDef> relationsTo = getRelations(RequirementCapabilityRelDef::getToNode,
74 currentResourceInstance);
76 if (!relationsFrom.isEmpty() || !relationsTo.isEmpty()) {
77 ComponentInstanceBuildingBlocks instBuildingBlocks = mergeInstanceUtils.getInstanceAtomicBuildingBlocks(currentResourceInstance, originComponent);
79 if (instBuildingBlocks != null) {
80 List<RelationMergeInfo> fromRelInfoList = convert(relationsFrom, rel -> mergeInstanceUtils.mapRelationRequirement(rel, instBuildingBlocks.getVfcInstances()));
81 List<RelationMergeInfo> toRelInfoList = convert(relationsTo, rel -> mergeInstanceUtils.mapRelationCapability(rel, instBuildingBlocks.getCapabilitiesOwners()));
83 // Encapsulate all needed info in one container
84 ContainerRelationsMergeInfo containerRelationsMergeInfo = new ContainerRelationsMergeInfo(fromRelInfoList, toRelInfoList);
86 dataHolder.setVfRelationsInfo(containerRelationsMergeInfo);
90 log.debug("No relations relevant to currentResourceInstance {} found in container component", currentResourceInstance);
97 public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
98 Wrapper<Either<Component, ResponseFormat>> resultWrapper = new Wrapper<>();
100 ContainerRelationsMergeInfo containerRelationsMergeInfo = getRelationsMergeInfo(dataHolder, updatedContainerComponent, resultWrapper);
102 ComponentInstance newComponentInstance = null;
103 if(resultWrapper.isEmpty()) {
105 newComponentInstance = loadComponentInstance(updatedContainerComponent, newInstanceId, resultWrapper);
108 if(resultWrapper.isEmpty() && containerRelationsMergeInfo != null) {
109 // Load VFCI and filter them by name
110 ComponentInstanceBuildingBlocks instanceBuildBlocks = mergeInstanceUtils.getInstanceAtomicBuildingBlocks(newComponentInstance);
111 if(instanceBuildBlocks != null) {
112 // Process Relationships
113 Stream<RequirementCapabilityRelDef> toRelationsInfoStream = getCapabilitiesRelationInfoStream(updatedContainerComponent, newInstanceId, containerRelationsMergeInfo, instanceBuildBlocks);
114 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream = getRequirementRelationsInfoStream(updatedContainerComponent, newInstanceId, containerRelationsMergeInfo, instanceBuildBlocks);
115 List<RequirementCapabilityRelDef> updatedRelations = getUpdatedRelations(toRelationsInfoStream, fromRelationsInfoStream);
116 StorageOperationStatus saveResult = toscaOperationFacade.associateResourceInstances(updatedContainerComponent.getUniqueId(), updatedRelations);
117 if (saveResult == StorageOperationStatus.OK) {
118 resultWrapper.setInnerElement(Either.left(updatedContainerComponent));
121 log.debug("Failed to associate instances of resource {} status is {}", updatedContainerComponent.getUniqueId(), saveResult);
122 ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(saveResult), updatedContainerComponent.getUniqueId());
123 resultWrapper.setInnerElement(Either.right(responseFormat));
127 return resultWrapper.getInnerElement();
130 private Stream<RequirementCapabilityRelDef> getRequirementRelationsInfoStream(Component updatedContainerComponent, String newInstanceId, ContainerRelationsMergeInfo containerRelationsMergeInfo, ComponentInstanceBuildingBlocks instanceBuildBlocks) {
131 Map<String, ComponentInstance> vfciMap = MapUtil.toMap(instanceBuildBlocks.getVfcInstances(), ComponentInstance::getName, (p1, p2) -> p1);
132 List<RelationMergeInfo> fromRelationsInfo = containerRelationsMergeInfo.getFromRelationsInfo();
133 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream = null;
134 if( fromRelationsInfo != null) {
135 fromRelationsInfoStream = fromRelationsInfo.stream()
136 .map(oldReqInfo -> mergeInstanceUtils.restoreRequirementRelation(oldReqInfo, newInstanceId, vfciMap, updatedContainerComponent))
137 .filter(Objects::nonNull);
139 return fromRelationsInfoStream;
142 private Stream<RequirementCapabilityRelDef> getCapabilitiesRelationInfoStream(Component updatedContainerComponent, String newInstanceId, ContainerRelationsMergeInfo containerRelationsMergeInfo, ComponentInstanceBuildingBlocks instanceBuildBlocks) {
143 Map<String, CapabilityOwner> capOwnersByName = MapUtil.toMap(instanceBuildBlocks.getCapabilitiesOwners(), CapabilityOwner::getName, (p1, p2) -> p1);
144 List<RelationMergeInfo> toRelationsInfo = containerRelationsMergeInfo.getToRelationsInfo();
145 Stream<RequirementCapabilityRelDef> toRelationsInfoStream = null;
146 if (toRelationsInfo != null) {
147 toRelationsInfoStream = toRelationsInfo.stream()
148 .map(oldCapInfo -> mergeInstanceUtils.restoreCapabilityRelation(oldCapInfo, newInstanceId, capOwnersByName, updatedContainerComponent))
149 .filter(Objects::nonNull);
151 return toRelationsInfoStream;
155 * @param containerComponent
157 * @param resultWrapper
160 private ComponentInstance loadComponentInstance(Component containerComponent, String instanceId,
161 Wrapper<Either<Component, ResponseFormat>> resultWrapper) {
162 ComponentInstance componentInstance = containerComponent.getComponentInstanceById(instanceId).orElse(null);
163 if (componentInstance == null) {
164 log.debug("Failed to get VF instance by new VF instance ID: {}", instanceId);
165 resultWrapper.setInnerElement(Either.left(containerComponent));
168 return componentInstance;
172 private List<RequirementCapabilityRelDef> getUpdatedRelations(Stream<RequirementCapabilityRelDef> toRelationsInfoStream,
173 Stream<RequirementCapabilityRelDef> fromRelationsInfoStream) {
174 Stream<RequirementCapabilityRelDef> updatedRelationsStream = Stream.empty();
176 if (toRelationsInfoStream != null) {
177 updatedRelationsStream = Stream.concat(updatedRelationsStream, toRelationsInfoStream);
180 if (fromRelationsInfoStream != null) {
181 updatedRelationsStream = Stream.concat(updatedRelationsStream, fromRelationsInfoStream);
184 return updatedRelationsStream.collect(Collectors.toList());
187 private List<RequirementCapabilityRelDef> getRelations(Function<RequirementCapabilityRelDef, String> getNodeFunc,
188 Component containerComponent,
189 ComponentInstance currentResourceInstance) {
191 final List<RequirementCapabilityRelDef> componentInstancesRelations = containerComponent.getComponentInstancesRelations();
192 if (componentInstancesRelations == null) {
193 return Collections.emptyList();
196 final String vfInstanceId = currentResourceInstance.getUniqueId();
198 return componentInstancesRelations.stream()
199 .filter(rel -> StringUtils.equals(getNodeFunc.apply(rel), vfInstanceId))
200 .collect(Collectors.toList());
203 private List<RelationMergeInfo> convert(List<RequirementCapabilityRelDef> relationsDef,
204 Function<RequirementCapabilityRelDef, RelationMergeInfo> mapFunc) {
205 return relationsDef.stream()
207 .filter(Objects::nonNull)
208 .collect(Collectors.toList());
211 private ContainerRelationsMergeInfo getRelationsMergeInfo(DataForMergeHolder dataHolder,
212 Component updatedContainerComponent,
213 Wrapper<Either<Component, ResponseFormat>> resultWrapper) {
214 ContainerRelationsMergeInfo containerRelationsMergeInfo = dataHolder.getContainerRelationsMergeInfo();
215 if (containerRelationsMergeInfo == null) {
216 log.debug("There is no info about relations should be restored.");
217 resultWrapper.setInnerElement(Either.left(updatedContainerComponent));
220 return containerRelationsMergeInfo;