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;
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.openecomp.sdc.be.config.BeEcompErrorManager;
31 import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
32 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
33 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
34 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
35 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
36 import org.openecomp.sdc.be.datatypes.elements.GroupTypeDataDefinition;
37 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
38 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
39 import org.openecomp.sdc.be.model.GroupTypeDefinition;
40 import org.openecomp.sdc.be.model.PropertyDefinition;
41 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
42 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
43 import org.openecomp.sdc.be.resources.data.CapabilityTypeData;
44 import org.openecomp.sdc.be.resources.data.GroupTypeData;
45 import org.openecomp.sdc.be.resources.data.PropertyData;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Qualifier;
49 import org.springframework.stereotype.Component;
51 import fj.data.Either;
53 @Component("group-type-operation")
54 public class GroupTypeOperation extends AbstractOperation implements IGroupTypeOperation {
56 String CREATE_FLOW_CONTEXT = "CreateGroupType";
57 String GET_FLOW_CONTEXT = "GetGroupType";
59 private PropertyOperation propertyOperation;
61 private TitanGenericDao titanGenericDao;
63 public GroupTypeOperation(@Qualifier("titan-generic-dao") TitanGenericDao titanGenericDao, @Qualifier("property-operation")PropertyOperation propertyOperation) {
65 this.propertyOperation = propertyOperation;
66 this.titanGenericDao = titanGenericDao;
69 private static Logger log = LoggerFactory.getLogger(GroupTypeOperation.class.getName());
74 * @param titanGenericDao
76 public void setTitanGenericDao(TitanGenericDao titanGenericDao) {
77 this.titanGenericDao = titanGenericDao;
81 public Either<GroupTypeDefinition, StorageOperationStatus> addGroupType(GroupTypeDefinition groupTypeDefinition) {
83 return addGroupType(groupTypeDefinition, false);
87 public Either<GroupTypeDefinition, StorageOperationStatus> addGroupType(GroupTypeDefinition groupTypeDefinition, boolean inTransaction) {
89 Either<GroupTypeDefinition, StorageOperationStatus> result = null;
93 Either<GroupTypeData, TitanOperationStatus> eitherStatus = addGroupTypeToGraph(groupTypeDefinition);
95 if (eitherStatus.isRight()) {
96 BeEcompErrorManager.getInstance().logBeFailedCreateNodeError(CREATE_FLOW_CONTEXT, groupTypeDefinition.getType(), eitherStatus.right().value().name());
97 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(eitherStatus.right().value()));
100 GroupTypeData groupTypeData = eitherStatus.left().value();
102 String uniqueId = groupTypeData.getUniqueId();
103 Either<GroupTypeDefinition, StorageOperationStatus> groupTypeRes = this.getGroupType(uniqueId, true);
105 if (groupTypeRes.isRight()) {
106 BeEcompErrorManager.getInstance().logBeFailedRetrieveNodeError(GET_FLOW_CONTEXT, groupTypeDefinition.getType(), eitherStatus.right().value().name());
109 result = groupTypeRes;
116 handleTransactionCommitRollback(inTransaction, result);
121 public Either<GroupTypeDefinition, TitanOperationStatus> getGroupTypeByUid(String uniqueId) {
123 Either<GroupTypeDefinition, TitanOperationStatus> result = null;
125 Either<GroupTypeData, TitanOperationStatus> groupTypesRes = titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.GroupType), uniqueId, GroupTypeData.class);
127 if (groupTypesRes.isRight()) {
128 TitanOperationStatus status = groupTypesRes.right().value();
129 log.debug("Group type {} cannot be found in graph. status is {}", uniqueId, status);
130 return Either.right(status);
133 GroupTypeData gtData = groupTypesRes.left().value();
134 GroupTypeDefinition groupTypeDefinition = new GroupTypeDefinition(gtData.getGroupTypeDataDefinition());
136 TitanOperationStatus propertiesStatus = propertyOperation.fillProperties(uniqueId, properList -> groupTypeDefinition.setProperties(properList));
138 if (propertiesStatus != TitanOperationStatus.OK) {
139 log.error("Failed to fetch properties of capability type {}", uniqueId);
140 return Either.right(propertiesStatus);
143 result = Either.left(groupTypeDefinition);
149 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupType(String uniqueId) {
151 return getGroupType(uniqueId, false);
156 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupType(String uniqueId, boolean inTransaction) {
157 return getElementType(this::getGroupTypeByUid, uniqueId, inTransaction);
161 public Either<GroupTypeDefinition, StorageOperationStatus> getLatestGroupTypeByType(String type) {
162 return getLatestGroupTypeByType(type, false);
166 public Either<GroupTypeDefinition, StorageOperationStatus> getLatestGroupTypeByType(String type, boolean inTransaction) {
167 Map<String, Object> mapCriteria = new HashMap<>();
168 mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type);
169 mapCriteria.put(GraphPropertiesDictionary.IS_HIGHEST_VERSION.getProperty(), true);
171 return getGroupTypeByCriteria(type, mapCriteria, inTransaction);
175 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupTypeByCriteria(String type, Map<String, Object> properties, boolean inTransaction) {
176 Either<GroupTypeDefinition, StorageOperationStatus> result = null;
178 if (type == null || type.isEmpty()) {
179 log.error("type is empty");
180 result = Either.right(StorageOperationStatus.INVALID_ID);
184 Either<List<GroupTypeData>, TitanOperationStatus> groupTypeEither = titanGenericDao.getByCriteria(NodeTypeEnum.GroupType, properties, GroupTypeData.class);
185 if (groupTypeEither.isRight()) {
186 result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(groupTypeEither.right().value()));
188 GroupTypeDataDefinition dataDefinition = groupTypeEither.left().value().stream().map(e -> e.getGroupTypeDataDefinition()).findFirst().get();
189 result = getGroupType(dataDefinition.getUniqueId(), inTransaction);
195 handleTransactionCommitRollback(inTransaction, result);
200 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupTypeByTypeAndVersion(String type, String version) {
201 return getGroupTypeByTypeAndVersion(type, version, false);
205 public Either<GroupTypeDefinition, StorageOperationStatus> getGroupTypeByTypeAndVersion(String type, String version, boolean inTransaction) {
206 Map<String, Object> mapCriteria = new HashMap<>();
207 mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type);
208 mapCriteria.put(GraphPropertiesDictionary.VERSION.getProperty(), version);
210 return getGroupTypeByCriteria(type, mapCriteria, inTransaction);
215 * Add group type to graph.
217 * 1. Add group type node
219 * 2. Add edge between the former node to its parent(if exists)
221 * 3. Add property node and associate it to the node created at #1. (per property & if exists)
223 * @param groupTypeDefinition
226 private Either<GroupTypeData, TitanOperationStatus> addGroupTypeToGraph(GroupTypeDefinition groupTypeDefinition) {
228 log.debug("Got group type {}", groupTypeDefinition);
230 String ctUniqueId = UniqueIdBuilder.buildGroupTypeUid(groupTypeDefinition.getType(), groupTypeDefinition.getVersion());
231 // capabilityTypeDefinition.setUniqueId(ctUniqueId);
233 GroupTypeData groupTypeData = buildGroupTypeData(groupTypeDefinition, ctUniqueId);
235 log.debug("Before adding group type to graph. groupTypeData = {}", groupTypeData);
237 Either<GroupTypeData, TitanOperationStatus> createGTResult = titanGenericDao.createNode(groupTypeData, GroupTypeData.class);
238 log.debug("After adding group type to graph. status is = {}", createGTResult);
240 if (createGTResult.isRight()) {
241 TitanOperationStatus operationStatus = createGTResult.right().value();
242 log.error("Failed to add group type {} to graph. status is {}", groupTypeDefinition.getType(), operationStatus);
243 return Either.right(operationStatus);
246 GroupTypeData resultCTD = createGTResult.left().value();
247 List<PropertyDefinition> properties = groupTypeDefinition.getProperties();
248 Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToCapablityType = propertyOperation.addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.GroupType, properties);
249 if (addPropertiesToCapablityType.isRight()) {
250 log.error("Failed add properties {} to capability {}", properties, groupTypeDefinition.getType());
251 return Either.right(addPropertiesToCapablityType.right().value());
254 String derivedFrom = groupTypeDefinition.getDerivedFrom();
255 if (derivedFrom != null) {
257 // TODO: Need to find the parent. need to take the latest one since
258 // we may have many versions of the same type
260 * log.debug("Before creating relation between group type {} to its parent {}", ctUniqueId, derivedFrom); UniqueIdData from = new UniqueIdData(NodeTypeEnum.CapabilityType, ctUniqueId); UniqueIdData to = new
261 * UniqueIdData(NodeTypeEnum.CapabilityType, derivedFrom); Either<GraphRelation, TitanOperationStatus> createRelation = titanGenericDao .createRelation(from, to, GraphEdgeLabels.DERIVED_FROM, null);
262 * 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()); }
267 return Either.left(createGTResult.left().value());
273 * convert between graph Node object to Java object
275 * @param capabilityTypeData
278 protected CapabilityTypeDefinition convertCTDataToCTDefinition(CapabilityTypeData capabilityTypeData) {
279 log.debug("The object returned after create capability is {}", capabilityTypeData);
281 CapabilityTypeDefinition capabilityTypeDefResult = new CapabilityTypeDefinition(capabilityTypeData.getCapabilityTypeDataDefinition());
283 return capabilityTypeDefResult;
286 private GroupTypeData buildGroupTypeData(GroupTypeDefinition groupTypeDefinition, String ctUniqueId) {
288 GroupTypeData groupTypeData = new GroupTypeData(groupTypeDefinition);
290 groupTypeData.getGroupTypeDataDefinition().setUniqueId(ctUniqueId);
291 Long creationDate = groupTypeData.getGroupTypeDataDefinition().getCreationTime();
292 if (creationDate == null) {
293 creationDate = System.currentTimeMillis();
295 groupTypeData.getGroupTypeDataDefinition().setCreationTime(creationDate);
296 groupTypeData.getGroupTypeDataDefinition().setModificationTime(creationDate);
298 return groupTypeData;
301 public Either<Boolean, StorageOperationStatus> isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) {
302 Map<String, Object> propertiesToMatch = new HashMap<String, Object>();
303 propertiesToMatch.put(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), childCandidateType);
304 Either<List<CapabilityTypeData>, TitanOperationStatus> getResponse = titanGenericDao.getByCriteria(NodeTypeEnum.CapabilityType, propertiesToMatch, CapabilityTypeData.class);
305 if (getResponse.isRight()) {
306 TitanOperationStatus titanOperationStatus = getResponse.right().value();
307 log.debug("Couldn't fetch capability type {}, error: {}", childCandidateType, titanOperationStatus);
308 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus));
310 String childUniqueId = getResponse.left().value().get(0).getUniqueId();
311 Set<String> travelledTypes = new HashSet<>();
313 travelledTypes.add(childUniqueId);
314 Either<List<ImmutablePair<CapabilityTypeData, GraphEdge>>, TitanOperationStatus> childrenNodes = titanGenericDao.getChildrenNodes(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), childUniqueId, GraphEdgeLabels.DERIVED_FROM,
315 NodeTypeEnum.CapabilityType, CapabilityTypeData.class);
316 if (childrenNodes.isRight()) {
317 if (childrenNodes.right().value() != TitanOperationStatus.NOT_FOUND) {
318 TitanOperationStatus titanOperationStatus = getResponse.right().value();
319 log.debug("Couldn't fetch derived from node for capability type {}, error: {}", childCandidateType, titanOperationStatus);
320 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(titanOperationStatus));
322 log.debug("Derived from node is not found for type {} - this is OK for root capability.");
323 return Either.left(false);
326 String derivedFromUniqueId = childrenNodes.left().value().get(0).getLeft().getUniqueId();
327 if (derivedFromUniqueId.equals(parentCandidateType)) {
328 log.debug("Verified that capability type {} derives from capability type {}", childCandidateType, parentCandidateType);
329 return Either.left(true);
331 childUniqueId = derivedFromUniqueId;
332 } while (!travelledTypes.contains(childUniqueId));
333 // this stop condition should never be used, if we use it, we have an
334 // illegal cycle in graph - "derived from" hierarchy cannot be cycled.
335 // It's here just to avoid infinite loop in case we have such cycle.
336 log.error("Detected a cycle of \"derived from\" edges starting at capability type node {}", childUniqueId);
337 return Either.right(StorageOperationStatus.GENERAL_ERROR);
343 * @param propertyOperation
345 public void setPropertyOperation(PropertyOperation propertyOperation) {
346 this.propertyOperation = propertyOperation;
350 public Either<GroupTypeData, TitanOperationStatus> getLatestGroupTypeByNameFromGraph(String name) {