Upgrade SDC from Titan to Janus Graph
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / operations / impl / PolicyTypeOperation.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
21 package org.openecomp.sdc.be.model.operations.impl;
22
23 import org.janusgraph.graphdb.query.JanusGraphPredicate;
24 import fj.data.Either;
25 import org.openecomp.sdc.be.config.BeEcompErrorManager;
26 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
27 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
28 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
29 import org.openecomp.sdc.be.datatypes.elements.PolicyTypeDataDefinition;
30 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
31 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
32 import org.openecomp.sdc.be.model.PropertyDefinition;
33 import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
34 import org.openecomp.sdc.be.model.operations.api.IPolicyTypeOperation;
35 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
36 import org.openecomp.sdc.be.resources.data.PolicyTypeData;
37 import org.openecomp.sdc.be.resources.data.PropertyData;
38 import org.openecomp.sdc.common.log.wrappers.Logger;
39 import org.springframework.beans.factory.annotation.Autowired;
40 import org.springframework.stereotype.Component;
41
42 import java.util.*;
43 import java.util.stream.Collectors;
44
45 import static org.openecomp.sdc.be.dao.janusgraph.JanusGraphUtils.buildNotInPredicate;
46
47 @Component("policy-type-operation")
48 public class PolicyTypeOperation extends AbstractOperation implements IPolicyTypeOperation {
49
50     private static final Logger log = Logger.getLogger(PolicyTypeOperation.class.getName());
51     private static final String CREATE_FLOW_CONTEXT = "CreatePolicyType";
52     private static final String GET_FLOW_CONTEXT = "GetPolicyType";
53
54     @Autowired
55     private PropertyOperation propertyOperation;
56     @Autowired
57     private DerivedFromOperation derivedFromOperation;
58     @Autowired
59     private OperationUtils operationUtils;
60
61     @Override
62     public Either<PolicyTypeDefinition, StorageOperationStatus> getLatestPolicyTypeByType(String type) {
63         Map<String, Object> mapCriteria = new HashMap<>();
64         mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type);
65         mapCriteria.put(GraphPropertiesDictionary.IS_HIGHEST_VERSION.getProperty(), true);
66         return getPolicyTypeByCriteria(type, mapCriteria);
67     }
68
69     @Override
70     public Either<PolicyTypeDefinition, StorageOperationStatus> addPolicyType(PolicyTypeDefinition policyTypeDef) {
71         Either<PolicyTypeDefinition, StorageOperationStatus> result;
72         Either<PolicyTypeData, StorageOperationStatus> eitherStatus = addPolicyTypeToGraph(policyTypeDef);
73         if (eitherStatus.isRight()) {
74             BeEcompErrorManager.getInstance().logBeFailedCreateNodeError(CREATE_FLOW_CONTEXT, policyTypeDef.getType(), eitherStatus.right().value().name());
75             result = Either.right(eitherStatus.right().value());
76         } else {
77             PolicyTypeData policyTypeData = eitherStatus.left().value();
78             String uniqueId = policyTypeData.getUniqueId();
79             Either<PolicyTypeDefinition, StorageOperationStatus> policyTypeRes = this.getPolicyTypeByUid(uniqueId);
80
81             if (policyTypeRes.isRight()) {
82                 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(GET_FLOW_CONTEXT, policyTypeDef.getType(), eitherStatus.right().value().name());
83             }
84             result = policyTypeRes;
85         }
86         return result;
87     }
88
89     @Override
90     public Either<PolicyTypeDefinition, StorageOperationStatus> updatePolicyType(PolicyTypeDefinition updatedPolicyType, PolicyTypeDefinition currPolicyType) {
91         log.debug("updating policy type {}", updatedPolicyType.getType());
92         return updatePolicyTypeOnGraph(updatedPolicyType, currPolicyType);
93     }
94
95     @Override
96     public List<PolicyTypeDefinition> getAllPolicyTypes(Set<String> excludedPolicyTypes) {
97         Map<String, Map.Entry<JanusGraphPredicate, Object>> predicateCriteria = buildNotInPredicate(GraphPropertiesDictionary.TYPE.getProperty(), excludedPolicyTypes);
98         return janusGraphGenericDao
99             .getByCriteriaWithPredicate(NodeTypeEnum.PolicyType, predicateCriteria, PolicyTypeData.class)
100                 .left()
101                 .map(this::convertPolicyTypesToDefinition)
102                 .left()
103                 .on(operationUtils::onJanusGraphOperationFailure);
104     }
105
106     private List<PolicyTypeDefinition> convertPolicyTypesToDefinition(List<PolicyTypeData> policiesTypes) {
107         return policiesTypes.stream().map(type -> new PolicyTypeDefinition(type.getPolicyTypeDataDefinition())).collect(Collectors.toList());
108     }
109
110
111     private Either<PolicyTypeData, StorageOperationStatus> addPolicyTypeToGraph(PolicyTypeDefinition policyTypeDef) {
112         log.debug("Got policy type {}", policyTypeDef);
113
114         String ptUniqueId = UniqueIdBuilder.buildPolicyTypeUid(policyTypeDef.getType(), policyTypeDef.getVersion(), "policytype");
115         PolicyTypeData policyTypeData = buildPolicyTypeData(policyTypeDef, ptUniqueId);
116         log.debug("Before adding policy type to graph. policyTypeData = {}", policyTypeData);
117         Either<PolicyTypeData, JanusGraphOperationStatus> eitherPolicyTypeData = janusGraphGenericDao
118             .createNode(policyTypeData, PolicyTypeData.class);
119         log.debug("After adding policy type to graph. status is = {}", eitherPolicyTypeData);
120         if (eitherPolicyTypeData.isRight()) {
121             JanusGraphOperationStatus operationStatus = eitherPolicyTypeData.right().value();
122             log.error("Failed to add policy type {} to graph. status is {}", policyTypeDef.getType(), operationStatus);
123             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus));
124         }
125         List<PropertyDefinition> properties = policyTypeDef.getProperties();
126         Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToPolicyType = propertyOperation.addPropertiesToElementType(ptUniqueId, NodeTypeEnum.PolicyType, properties);
127         if (addPropertiesToPolicyType.isRight()) {
128             log.error("Failed add properties {} to policy {}", properties, policyTypeDef.getType());
129             return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToPolicyType.right().value()));
130         }
131         return addDerivedFromRelation(policyTypeDef, ptUniqueId)
132             .left()
133             .map(updatedDerivedFrom -> eitherPolicyTypeData.left().value());
134     }
135
136     private Either<PolicyTypeDefinition, StorageOperationStatus> getPolicyTypeByCriteria(String type, Map<String, Object> properties) {
137         Either<PolicyTypeDefinition, StorageOperationStatus> result;
138         if (type == null || type.isEmpty()) {
139             log.error("type is empty");
140             result = Either.right(StorageOperationStatus.INVALID_ID);
141             return result;
142         }
143
144         Either<List<PolicyTypeData>, JanusGraphOperationStatus> eitherPolicyData = janusGraphGenericDao
145             .getByCriteria(NodeTypeEnum.PolicyType, properties, PolicyTypeData.class);
146         if (eitherPolicyData.isRight()) {
147             result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(eitherPolicyData.right().value()));
148         } else {
149             PolicyTypeDataDefinition dataDefinition = eitherPolicyData.left().value().stream().map(PolicyTypeData::getPolicyTypeDataDefinition).findFirst().get();
150             result = getPolicyTypeByUid(dataDefinition.getUniqueId());
151         }
152         return result;
153
154     }
155
156     private Either<PolicyTypeDefinition, StorageOperationStatus> getPolicyTypeByUid(String uniqueId) {
157         log.debug("#getPolicyTypeByUid - fetching policy type with id {}", uniqueId);
158         return janusGraphGenericDao
159             .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.PolicyType), uniqueId, PolicyTypeData.class)
160                 .right()
161                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
162                 .left()
163                 .bind(policyType -> createPolicyTypeDefinition(uniqueId, policyType));
164     }
165
166     private Either<PolicyTypeDefinition, StorageOperationStatus> createPolicyTypeDefinition(String uniqueId, PolicyTypeData policyTypeNode) {
167         PolicyTypeDefinition policyType = new PolicyTypeDefinition(policyTypeNode.getPolicyTypeDataDefinition());
168         return fillDerivedFrom(uniqueId, policyType)
169                 .left()
170                 .map(derivedFrom -> fillProperties(uniqueId, policyType, derivedFrom))
171                 .left()
172                 .map(props -> policyType);
173     }
174
175     private Either<List<PropertyDefinition>, StorageOperationStatus> fillProperties(String uniqueId, PolicyTypeDefinition policyType, PolicyTypeData derivedFromNode) {
176         log.debug("#fillProperties - fetching all properties for policy type {}", policyType.getType());
177         return propertyOperation.findPropertiesOfNode(NodeTypeEnum.PolicyType, uniqueId)
178                 .right()
179                 .bind(this::handlePolicyTypeHasNoProperties)
180                 .left()
181                 .bind(propsMap -> fillDerivedFromProperties(policyType, derivedFromNode, new ArrayList<>(propsMap.values())));
182     }
183
184     private Either<List<PropertyDefinition>, StorageOperationStatus> fillDerivedFromProperties(PolicyTypeDefinition policyType, PolicyTypeData derivedFromNode, List<PropertyDefinition> policyTypeDirectProperties) {
185         if (derivedFromNode == null) {
186             policyType.setProperties(policyTypeDirectProperties);
187             return Either.left(policyTypeDirectProperties);
188         }
189         log.debug("#fillDerivedFromProperties - fetching all properties of derived from chain for policy type {}", policyType.getType());
190         return propertyOperation.getAllPropertiesRec(derivedFromNode.getUniqueId(), NodeTypeEnum.PolicyType, PolicyTypeData.class)
191                 .left()
192                 .map(derivedFromProps -> {policyTypeDirectProperties.addAll(derivedFromProps); return policyTypeDirectProperties;})
193                 .left()
194                 .map(allProps -> {policyType.setProperties(allProps);return allProps;});
195     }
196
197     private Either<PolicyTypeData, StorageOperationStatus> fillDerivedFrom(String uniqueId, PolicyTypeDefinition policyType) {
198         log.debug("#fillDerivedFrom - fetching policy type {} derived node", policyType.getType());
199         return derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.PolicyType, PolicyTypeData.class)
200                 .right()
201                 .bind(this::handleDerivedFromNotExist)
202                 .left()
203                 .map(derivedFrom -> setDerivedFrom(policyType, derivedFrom));
204
205     }
206
207     private Either<PolicyTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
208         if (err == StorageOperationStatus.NOT_FOUND) {
209             return Either.left(null);
210         }
211         return Either.right(err);
212     }
213
214     Either<Map<String, PropertyDefinition>, StorageOperationStatus> handlePolicyTypeHasNoProperties(JanusGraphOperationStatus err) {
215         if (err == JanusGraphOperationStatus.NOT_FOUND) {
216             return Either.left(new HashMap<>());
217         }
218         return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(err));
219     }
220
221     private PolicyTypeData setDerivedFrom(PolicyTypeDefinition policyTypeDefinition, PolicyTypeData derivedFrom) {
222         if (derivedFrom != null) {
223             policyTypeDefinition.setDerivedFrom(derivedFrom.getPolicyTypeDataDefinition().getType());
224         }
225         return derivedFrom;
226     }
227
228     private PolicyTypeData buildPolicyTypeData(PolicyTypeDefinition policyTypeDefinition, String ptUniqueId) {
229
230         PolicyTypeData policyTypeData = new PolicyTypeData(policyTypeDefinition);
231
232         policyTypeData.getPolicyTypeDataDefinition().setUniqueId(ptUniqueId);
233         Long creationDate = policyTypeData.getPolicyTypeDataDefinition().getCreationTime();
234         if (creationDate == null) {
235             creationDate = System.currentTimeMillis();
236         }
237
238         policyTypeData.getPolicyTypeDataDefinition().setCreationTime(creationDate);
239         policyTypeData.getPolicyTypeDataDefinition().setModificationTime(creationDate);
240         return policyTypeData;
241     }
242
243     private Either<PolicyTypeDefinition, StorageOperationStatus> updatePolicyTypeOnGraph(PolicyTypeDefinition updatedPolicyType, PolicyTypeDefinition currPolicyType) {
244         updatePolicyTypeData(updatedPolicyType, currPolicyType);
245         return janusGraphGenericDao.updateNode(new PolicyTypeData(updatedPolicyType), PolicyTypeData.class)
246                 .right()
247                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus)
248                 .left()
249                 .bind(updatedNode -> updatePolicyProperties(updatedPolicyType.getUniqueId(), updatedPolicyType.getProperties()))
250                 .left()
251                 .bind(updatedProperties -> updatePolicyDerivedFrom(updatedPolicyType, currPolicyType.getDerivedFrom()))
252                 .left()
253                 .map(updatedDerivedFrom -> updatedPolicyType);
254     }
255
256     private Either<Map<String, PropertyData>, StorageOperationStatus> updatePolicyProperties(String policyId, List<PropertyDefinition> properties) {
257         log.debug("#updatePolicyProperties - updating policy type properties for policy type with id {}", policyId);
258         return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.PolicyType, policyId)
259                 .left()
260                 .bind(deleteProps -> addPropertiesToPolicy(policyId, properties));
261     }
262
263     private Either<GraphRelation, StorageOperationStatus> updatePolicyDerivedFrom(PolicyTypeDefinition updatedPolicyType, String currDerivedFromPolicyType) {
264         String policyTypeId = updatedPolicyType.getUniqueId();
265         log.debug("#updatePolicyDerivedFrom - updating policy derived from relation for policy type with id {}. old derived type {}. new derived type {}", policyTypeId, currDerivedFromPolicyType, updatedPolicyType.getDerivedFrom());
266         StorageOperationStatus deleteDerivedRelationStatus = deleteDerivedFromPolicyType(policyTypeId, currDerivedFromPolicyType);
267         if (deleteDerivedRelationStatus != StorageOperationStatus.OK) {
268             return Either.right(deleteDerivedRelationStatus);
269         }
270         return addDerivedFromRelation(updatedPolicyType, policyTypeId);
271     }
272
273     private Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(PolicyTypeDataDefinition policyTypeDef, String ptUniqueId) {
274         String derivedFrom = policyTypeDef.getDerivedFrom();
275         if (derivedFrom == null) {
276             return Either.left(null);
277         }
278         log.debug("#addDerivedFromRelationBefore - adding derived from relation between policy type {} to its parent {}", policyTypeDef.getType(), derivedFrom);
279         return this.getLatestPolicyTypeByType(derivedFrom)
280                 .left()
281                 .bind(derivedFromPolicy -> derivedFromOperation.addDerivedFromRelation(ptUniqueId, derivedFromPolicy.getUniqueId(), NodeTypeEnum.PolicyType));
282     }
283
284     private StorageOperationStatus deleteDerivedFromPolicyType(String policyTypeId, String derivedFromType) {
285         if (derivedFromType == null) {
286             return StorageOperationStatus.OK;
287         }
288         log.debug("#deleteDerivedFromPolicyType - deleting derivedFrom relation for policy type with id {} and its derived type {}", policyTypeId, derivedFromType);
289         return getLatestPolicyTypeByType(derivedFromType)
290                 .either(derivedFromNode -> derivedFromOperation.removeDerivedFromRelation(policyTypeId, derivedFromNode.getUniqueId(), NodeTypeEnum.PolicyType),
291                         err -> err);
292     }
293
294     private  Either<Map<String, PropertyData>, StorageOperationStatus> addPropertiesToPolicy(String policyTypeId, List<PropertyDefinition> properties) {
295         log.debug("#addPropertiesToPolicy - adding policy type properties for policy type with id {}", policyTypeId);
296         return propertyOperation.addPropertiesToElementType(policyTypeId, NodeTypeEnum.PolicyType, properties)
297                 .right()
298                 .map(DaoStatusConverter::convertJanusGraphStatusToStorageStatus);
299     }
300
301     private void updatePolicyTypeData(PolicyTypeDefinition updatedTypeDefinition, PolicyTypeDefinition currTypeDefinition) {
302         updatedTypeDefinition.setUniqueId(currTypeDefinition.getUniqueId());
303         updatedTypeDefinition.setCreationTime(currTypeDefinition.getCreationTime());
304         updatedTypeDefinition.setModificationTime(System.currentTimeMillis());
305     }
306
307 }