Implement 'Update Service by importing Tosca Model'-story
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsonjanusgraph / operations / NodeFilterOperation.java
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 package org.openecomp.sdc.be.model.jsonjanusgraph.operations;
21
22 import fj.data.Either;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.Set;
27 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
28 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
29 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
30 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
31 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
32 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
33 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
34 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition;
36 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
37 import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType;
38 import org.openecomp.sdc.be.model.Component;
39 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
40 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
41 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43
44 @org.springframework.stereotype.Component("node-filter-operations")
45 public class NodeFilterOperation extends BaseOperation {
46
47     private static Logger logger = Logger.getLogger(NodeFilterOperation.class);
48
49     public Either<Set<String>, StorageOperationStatus> deleteNodeFilters(final Component component, final Set<String> componentInstanceIds) {
50         final Either<GraphVertex, JanusGraphOperationStatus> getComponentVertex;
51         final Either<GraphVertex, JanusGraphOperationStatus> getNodeFilterVertex;
52         StorageOperationStatus status;
53         getComponentVertex = janusGraphDao.getVertexById(component.getUniqueId(), JsonParseFlagEnum.NoParse);
54         if (getComponentVertex.isRight()) {
55             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getComponentVertex.right().value()));
56         }
57         getNodeFilterVertex = janusGraphDao
58             .getChildVertex(getComponentVertex.left().value(), EdgeLabelEnum.NODE_FILTER_TEMPLATE, JsonParseFlagEnum.NoParse);
59         if (getNodeFilterVertex.isLeft()) {
60             status = deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.NODE_FILTER_TEMPLATE, new ArrayList<>(componentInstanceIds));
61             if (status != StorageOperationStatus.OK) {
62                 return Either.right(status);
63             }
64         }
65         return Either.left(componentInstanceIds);
66     }
67
68     public Either<String, StorageOperationStatus> deleteNodeFilter(final Component component, final String componentInstanceId) {
69         final Either<Set<String>, StorageOperationStatus> listStorageOperationStatusEither = deleteNodeFilters(component,
70             Set.of(componentInstanceId));
71         if (listStorageOperationStatusEither.isRight()) {
72             return Either.right(listStorageOperationStatusEither.right().value());
73         }
74         return Either.left(componentInstanceId);
75     }
76
77     public Either<CINodeFilterDataDefinition, StorageOperationStatus> createNodeFilter(final String componentId, final String componentInstanceId) {
78         CINodeFilterDataDefinition nodeFilterDataDefinition = new CINodeFilterDataDefinition();
79         return addOrUpdateNodeFilter(false, componentId, componentInstanceId, nodeFilterDataDefinition);
80     }
81
82     public Either<CINodeFilterDataDefinition, StorageOperationStatus> deleteConstraint(final String serviceId, final String componentInstanceId,
83                                                                                        final CINodeFilterDataDefinition nodeFilterDataDefinition,
84                                                                                        final int propertyIndex,
85                                                                                        final NodeFilterConstraintType nodeFilterConstraintType) {
86         if (NodeFilterConstraintType.PROPERTIES.equals(nodeFilterConstraintType)) {
87             nodeFilterDataDefinition.getProperties().getListToscaDataDefinition().remove(propertyIndex);
88         } else if (NodeFilterConstraintType.CAPABILITIES.equals(nodeFilterConstraintType)) {
89             removeCapabilityNodeFilterByIndex(nodeFilterDataDefinition, propertyIndex);
90         }
91         return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, nodeFilterDataDefinition);
92     }
93
94     public Either<CINodeFilterDataDefinition, StorageOperationStatus> addPropertyFilter(final String componentId, final String componentInstanceId,
95                                                                                         final CINodeFilterDataDefinition nodeFilterDataDefinition,
96                                                                                         final PropertyFilterDataDefinition propertyFilterDataDefinition) {
97         ListDataDefinition<PropertyFilterDataDefinition> properties = nodeFilterDataDefinition.getProperties();
98         if (properties == null) {
99             properties = new ListDataDefinition<>();
100             nodeFilterDataDefinition.setProperties(properties);
101         }
102         properties.getListToscaDataDefinition().add(propertyFilterDataDefinition);
103         nodeFilterDataDefinition.setProperties(properties);
104         return addOrUpdateNodeFilter(true, componentId, componentInstanceId, nodeFilterDataDefinition);
105     }
106
107     public Either<CINodeFilterDataDefinition, StorageOperationStatus> addCapabilities(final String componentId, final String componentInstanceId,
108                                                                                       final CINodeFilterDataDefinition nodeFilterDataDefinition,
109                                                                                       final RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition) {
110         ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> capabilities = nodeFilterDataDefinition.getCapabilities();
111         if (capabilities == null) {
112             capabilities = new ListDataDefinition<>();
113             nodeFilterDataDefinition.setCapabilities(capabilities);
114         }
115
116         final Optional<RequirementNodeFilterCapabilityDataDefinition> existingCap = capabilities
117                 .getListToscaDataDefinition().stream()
118                 .filter(def -> def.getName().equals(requirementNodeFilterCapabilityDataDefinition.getName())).findAny();
119
120         if (existingCap.isPresent()) {
121             final ListDataDefinition<PropertyFilterDataDefinition> newProperties  = requirementNodeFilterCapabilityDataDefinition.getProperties();
122             final ListDataDefinition<PropertyFilterDataDefinition> existingProperties = existingCap.get().getProperties();
123             newProperties.getListToscaDataDefinition().forEach((existingProperties::add)) ;
124         } else {
125             capabilities.getListToscaDataDefinition().add(requirementNodeFilterCapabilityDataDefinition);
126         }
127         nodeFilterDataDefinition.setCapabilities(capabilities);
128         return addOrUpdateNodeFilter(true, componentId, componentInstanceId, nodeFilterDataDefinition);
129     }
130
131     public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateNodeFilter(final String serviceId, final String componentInstanceId,
132                                                                                        final CINodeFilterDataDefinition ciNodeFilterDataDefinition) {
133         return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, ciNodeFilterDataDefinition);
134     }
135
136     public Either<CINodeFilterDataDefinition, StorageOperationStatus> addNodeFilterData(
137             final String componentId,
138             final String componentInstanceId,
139             final CINodeFilterDataDefinition nodeFilterDataDefinition) {
140         return addOrUpdateNodeFilter(false, componentId, componentInstanceId, nodeFilterDataDefinition);
141     }
142
143     private void removeCapabilityNodeFilterByIndex(final CINodeFilterDataDefinition nodeFilterDataDefinition, final int filterToRemoveIndex) {
144         int currentFilterCountdown = filterToRemoveIndex;
145         final List<RequirementNodeFilterCapabilityDataDefinition> filtersByCapability =
146             nodeFilterDataDefinition.getCapabilities().getListToscaDataDefinition();
147         for (final RequirementNodeFilterCapabilityDataDefinition capabilityFilterGroup : filtersByCapability) {
148             final List<PropertyFilterDataDefinition> capabilityFilters = capabilityFilterGroup.getProperties().getListToscaDataDefinition();
149             if (isFilterInCapabilityGroup(currentFilterCountdown, capabilityFilters)) {
150                 capabilityFilters.remove(currentFilterCountdown);
151                 break;
152             } else {
153                 currentFilterCountdown = getRemainingFilterCount(currentFilterCountdown, capabilityFilters);
154             }
155         }
156     }
157
158     private boolean isFilterInCapabilityGroup(int currentFilterCount, List<PropertyFilterDataDefinition> capabilityFilters) {
159         return capabilityFilters.size() > currentFilterCount;
160     }
161
162     private int getRemainingFilterCount(int currentFilterCount, final List<PropertyFilterDataDefinition> capabilityFilters) {
163         return currentFilterCount - capabilityFilters.size();
164     }
165
166     private Either<CINodeFilterDataDefinition, StorageOperationStatus> addOrUpdateNodeFilter(final boolean isUpdateAction, final String componentId,
167                                                                                              final String componentInstanceId,
168                                                                                              final CINodeFilterDataDefinition ciNodeFilterDataDefinition) {
169
170         final Either<GraphVertex, JanusGraphOperationStatus> serviceVertexEither =
171             janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
172         if (serviceVertexEither.isRight()) {
173             JanusGraphOperationStatus status = serviceVertexEither.right().value();
174             CommonUtility
175                 .addRecordToLog(logger, CommonUtility.LogLevelEnum.DEBUG, "Failed to get tosca element {} upon adding the properties. Status is {}. ",
176                     componentId, status);
177             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
178         }
179         final GraphVertex serviceVertex = serviceVertexEither.left().value();
180         ciNodeFilterDataDefinition.setID(componentInstanceId);
181         final StorageOperationStatus statusRes = performUpdateToscaAction(isUpdateAction, serviceVertex, List.of(ciNodeFilterDataDefinition));
182         if (!statusRes.equals(StorageOperationStatus.OK)) {
183             janusGraphDao.rollback();
184             logger.error(" Failed to perform tosca update for node filter in service {} , component instance {}. status is {}", componentId,
185                 componentInstanceId, statusRes);
186             return Either.right(statusRes);
187         }
188         janusGraphDao.commit();
189         return Either.left(ciNodeFilterDataDefinition);
190     }
191
192     private StorageOperationStatus performUpdateToscaAction(final boolean isUpdate, final GraphVertex graphVertex,
193                                                             final List<CINodeFilterDataDefinition> toscaDataList) {
194         if (isUpdate) {
195             return updateToscaDataOfToscaElement(graphVertex, EdgeLabelEnum.NODE_FILTER_TEMPLATE, VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList,
196                 JsonPresentationFields.UNIQUE_ID);
197         } else {
198             return addToscaDataToToscaElement(graphVertex, EdgeLabelEnum.NODE_FILTER_TEMPLATE, VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList,
199                 JsonPresentationFields.UNIQUE_ID);
200         }
201     }
202 }