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.be.model.operations.impl;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
28 import java.util.function.Function;
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.openecomp.sdc.be.config.BeEcompErrorManager;
32 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
33 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
34 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
35 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
36 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
37 import org.openecomp.sdc.be.datatypes.elements.GroupTypeDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
39 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
40 import org.openecomp.sdc.be.model.GroupTypeDefinition;
41 import org.openecomp.sdc.be.model.PropertyDefinition;
42 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
43 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
44 import org.openecomp.sdc.be.resources.data.CapabilityTypeData;
45 import org.openecomp.sdc.be.resources.data.GroupTypeData;
46 import org.openecomp.sdc.be.resources.data.PropertyData;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.beans.factory.annotation.Qualifier;
50 import org.springframework.stereotype.Component;
52 import fj.data.Either;
54 @Component("group-type-operation")
55 public class GroupTypeOperation extends AbstractOperation implements IGroupTypeOperation {
57 String CREATE_FLOW_CONTEXT = "CreateGroupType";
58 String GET_FLOW_CONTEXT = "GetGroupType";
60 private PropertyOperation propertyOperation;
62 private TitanGenericDao titanGenericDao;
64 public GroupTypeOperation(@Qualifier("titan-generic-dao") TitanGenericDao titanGenericDao, @Qualifier("property-operation")PropertyOperation propertyOperation) {
66 this.propertyOperation = propertyOperation;
67 this.titanGenericDao = titanGenericDao;
70 private static Logger log = LoggerFactory.getLogger(GroupTypeOperation.class.getName());
75 * @param titanGenericDao
77 public void setTitanGenericDao(TitanGenericDao titanGenericDao) {
78 this.titanGenericDao = titanGenericDao;
82 public Either<GroupTypeDefinition, StorageOperationStatus> addGroupType(GroupTypeDefinition groupTypeDefinition) {
84 return addGroupType(groupTypeDefinition, false);
88 public Either<GroupTypeDefinition, StorageOperationStatus> addGroupType(GroupTypeDefinition groupTypeDefinition, boolean inTransaction) {
90 Either<GroupTypeDefinition, StorageOperationStatus> result = null;
94 Either<GroupTypeData, TitanOperationStatus> eitherStatus = addGroupTypeToGraph(groupTypeDefinition);
96 if (eitherStatus.isRight()) {
97 BeEcompErrorManager.getInstance().logBeFailedCreateNodeError(CREATE_FLOW_CONTEXT, groupTypeDefinition.getType(), eitherStatus.right().value().name());
98 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(eitherStatus.right().value()));
101 GroupTypeData groupTypeData = eitherStatus.left().value();
103 String uniqueId = groupTypeData.getUniqueId();
104 Either<GroupTypeDefinition, StorageOperationStatus> groupTypeRes = this.getGroupType(uniqueId, true);
106 if (groupTypeRes.isRight()) {
107 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(GET_FLOW_CONTEXT, groupTypeDefinition.getType(), eitherStatus.right().value().name());
110 result = groupTypeRes;
117 handleTransactionCommitRollback(inTransaction, result);
122 public Either<GroupTypeDefinition, TitanOperationStatus> getGroupTypeByUid(String uniqueId) {
124 Either<GroupTypeDefinition, TitanOperationStatus> result = null;
126 Either<GroupTypeData, TitanOperationStatus> groupTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.GroupType), uniqueId, GroupTypeData.class);
128 if (groupTypesRes.isRight()) {
129 TitanOperationStatus status = groupTypesRes.right().value();
130 log.debug("Group type {} cannot be found in graph. status is {}", uniqueId, status);
131 return Either.right(status);
134 GroupTypeData gtData = groupTypesRes.left().value();
135 GroupTypeDefinition groupTypeDefinition = new GroupTypeDefinition(gtData.getGroupTypeDataDefinition());
137 TitanOperationStatus propertiesStatus = propertyOperation.fillProperties(uniqueId, properList -> groupTypeDefinition.setProperties(properList));
139 if (propertiesStatus != TitanOperationStatus.OK) {
140 log.error("Failed to fetch properties of capability type {}", uniqueId);
141 return Either.right(propertiesStatus);
144 result = Either.left(groupTypeDefinition);
150 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupType(String uniqueId) {
152 return getGroupType(uniqueId, false);
157 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupType(String uniqueId, boolean inTransaction) {
158 Function<String, Either<GroupTypeDefinition, TitanOperationStatus>> groupTypeGetter = uId -> getGroupTypeByUid(uId);
159 return getElementType(groupTypeGetter, uniqueId, inTransaction);
164 public Either<GroupTypeDefinition, StorageOperationStatus> getLatestGroupTypeByType(String type) {
165 return getLatestGroupTypeByType(type, false);
169 public Either<GroupTypeDefinition, StorageOperationStatus> getLatestGroupTypeByType(String type, boolean inTransaction) {
170 Map<String, Object> mapCriteria = new HashMap<>();
171 mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type);
172 mapCriteria.put(GraphPropertiesDictionary.IS_HIGHEST_VERSION.getProperty(), true);
174 return getGroupTypeByCriteria(type, mapCriteria, inTransaction);
178 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupTypeByCriteria(String type, Map<String, Object> properties, boolean inTransaction) {
179 Either<GroupTypeDefinition, StorageOperationStatus> result = null;
181 if (type == null || type.isEmpty()) {
182 log.error("type is empty");
183 result = Either.right(StorageOperationStatus.INVALID_ID);
187 Either<List<GroupTypeData>, TitanOperationStatus> groupTypeEither = titanGenericDao.getByCriteria(NodeTypeEnum.GroupType, properties, GroupTypeData.class);
188 if (groupTypeEither.isRight()) {
189 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(groupTypeEither.right().value()));
191 GroupTypeDataDefinition dataDefinition = groupTypeEither.left().value().stream().map(e -> e.getGroupTypeDataDefinition()).findFirst().get();
192 result = getGroupType(dataDefinition.getUniqueId(), inTransaction);
198 handleTransactionCommitRollback(inTransaction, result);
203 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupTypeByTypeAndVersion(String type, String version) {
204 return getGroupTypeByTypeAndVersion(type, version, false);
208 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupTypeByTypeAndVersion(String type, String version, boolean inTransaction) {
209 Map<String, Object> mapCriteria = new HashMap<>();
210 mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type);
211 mapCriteria.put(GraphPropertiesDictionary.VERSION.getProperty(), version);
213 return getGroupTypeByCriteria(type, mapCriteria, inTransaction);
218 * Add group type to graph.
220 * 1. Add group type node
222 * 2. Add edge between the former node to its parent(if exists)
224 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
226 * @param groupTypeDefinition
229 private Either<GroupTypeData, TitanOperationStatus> addGroupTypeToGraph(GroupTypeDefinition groupTypeDefinition) {
231 log.debug("Got group type {}", groupTypeDefinition);
233 String ctUniqueId = UniqueIdBuilder.buildGroupTypeUid(groupTypeDefinition.getType(), groupTypeDefinition.getVersion());
234 // capabilityTypeDefinition.setUniqueId(ctUniqueId);
236 GroupTypeData groupTypeData = buildGroupTypeData(groupTypeDefinition, ctUniqueId);
238 log.debug("Before adding group type to graph. groupTypeData = {}", groupTypeData);
240 Either<GroupTypeData, TitanOperationStatus> createGTResult = titanGenericDao.createNode(groupTypeData, GroupTypeData.class);
241 log.debug("After adding group type to graph. status is = {}", createGTResult);
243 if (createGTResult.isRight()) {
244 TitanOperationStatus operationStatus = createGTResult.right().value();
245 log.error("Failed to add group type {} to graph. status is {}", groupTypeDefinition.getType(), operationStatus);
246 return Either.right(operationStatus);
249 GroupTypeData resultCTD = createGTResult.left().value();
250 List<PropertyDefinition> properties = groupTypeDefinition.getProperties();
251 Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToCapablityType = propertyOperation.addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.GroupType, properties);
252 if (addPropertiesToCapablityType.isRight()) {
253 log.error("Failed add properties {} to capability {}", properties, groupTypeDefinition.getType());
254 return Either.right(addPropertiesToCapablityType.right().value());
257 String derivedFrom = groupTypeDefinition.getDerivedFrom();
258 if (derivedFrom != null) {
260 // TODO: Need to find the parent. need to take the latest one since
261 // we may have many versions of the same type
263 * log.debug("Before creating relation between group type {} to its parent {}", ctUniqueId, derivedFrom); UniqueIdData from = new UniqueIdData(NodeTypeEnum.CapabilityType, ctUniqueId); UniqueIdData to = new
264 * UniqueIdData(NodeTypeEnum.CapabilityType, derivedFrom); Either<GraphRelation, TitanOperationStatus> createRelation = titanGenericDao .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
265 * log.debug("After create relation between capability type {} to its parent {}. status is {}", ctUniqueId, derivedFrom, createRelation); if (createRelation.isRight()) { return Either.right(createRelation.right().value()); }
270 return Either.left(createGTResult.left().value());
276 * convert between graph Node object to Java object
278 * @param capabilityTypeData
281 protected CapabilityTypeDefinition convertCTDataToCTDefinition(CapabilityTypeData capabilityTypeData) {
282 log.debug("The object returned after create capability is {}", capabilityTypeData);
284 CapabilityTypeDefinition capabilityTypeDefResult = new CapabilityTypeDefinition(capabilityTypeData.getCapabilityTypeDataDefinition());
286 return capabilityTypeDefResult;
289 private GroupTypeData buildGroupTypeData(GroupTypeDefinition groupTypeDefinition, String ctUniqueId) {
291 GroupTypeData groupTypeData = new GroupTypeData(groupTypeDefinition);
293 groupTypeData.getGroupTypeDataDefinition().setUniqueId(ctUniqueId);
294 Long creationDate = groupTypeData.getGroupTypeDataDefinition().getCreationTime();
295 if (creationDate == null) {
296 creationDate = System.currentTimeMillis();
298 groupTypeData.getGroupTypeDataDefinition().setCreationTime(creationDate);
299 groupTypeData.getGroupTypeDataDefinition().setModificationTime(creationDate);
301 return groupTypeData;
304 public Either<Boolean, StorageOperationStatus> isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) {
305 Map<String, Object> propertiesToMatch = new HashMap<String, Object>();
306 propertiesToMatch.put(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), childCandidateType);
307 Either<List<CapabilityTypeData>, TitanOperationStatus> getResponse = titanGenericDao.getByCriteria(NodeTypeEnum.CapabilityType, propertiesToMatch, CapabilityTypeData.class);
308 if (getResponse.isRight()) {
309 TitanOperationStatus titanOperationStatus = getResponse.right().value();
310 log.debug("Couldn't fetch capability type {}, error: {}", childCandidateType, titanOperationStatus);
311 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus));
313 String childUniqueId = getResponse.left().value().get(0).getUniqueId();
314 Set<String> travelledTypes = new HashSet<>();
316 travelledTypes.add(childUniqueId);
317 Either<List<ImmutablePair<CapabilityTypeData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), childUniqueId, GraphEdgeLabels.DERIVED_FROM,
318 NodeTypeEnum.CapabilityType, CapabilityTypeData.class);
319 if (childrenNodes.isRight()) {
320 if (childrenNodes.right().value() != TitanOperationStatus.NOT_FOUND) {
321 TitanOperationStatus titanOperationStatus = getResponse.right().value();
322 log.debug("Couldn't fetch derived from node for capability type {}, error: {}", childCandidateType, titanOperationStatus);
323 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus));
325 log.debug("Derived from node is not found for type {} - this is OK for root capability.");
326 return Either.left(false);
329 String derivedFromUniqueId = childrenNodes.left().value().get(0).getLeft().getUniqueId();
330 if (derivedFromUniqueId.equals(parentCandidateType)) {
331 log.debug("Verified that capability type {} derives from capability type {}", childCandidateType, parentCandidateType);
332 return Either.left(true);
334 childUniqueId = derivedFromUniqueId;
335 } while (!travelledTypes.contains(childUniqueId));
336 // this stop condition should never be used, if we use it, we have an
337 // illegal cycle in graph - "derived from" hierarchy cannot be cycled.
338 // It's here just to avoid infinite loop in case we have such cycle.
339 log.error("Detected a cycle of \"derived from\" edges starting at capability type node {}", childUniqueId);
340 return Either.right(StorageOperationStatus.GENERAL_ERROR);
346 * @param propertyOperation
348 public void setPropertyOperation(PropertyOperation propertyOperation) {
349 this.propertyOperation = propertyOperation;
353 public Either<GroupTypeData, TitanOperationStatus> getLatestGroupTypeByNameFromGraph(String name) {