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