2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 * SPDX-License-Identifier: Apache-2.0
17 * ============LICENSE_END=========================================================
19 package org.openecomp.sdc.be.model.operations.impl;
21 import fj.data.Either;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Optional;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.collections4.MapUtils;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
33 import org.apache.tinkerpop.gremlin.structure.Vertex;
34 import org.janusgraph.core.JanusGraph;
35 import org.openecomp.sdc.be.config.BeEcompErrorManager;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
39 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
40 import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
41 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
42 import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
43 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
44 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
45 import org.openecomp.sdc.be.exception.supplier.DataTypeOperationExceptionSupplier;
46 import org.openecomp.sdc.be.model.DataTypeDefinition;
47 import org.openecomp.sdc.be.model.PropertyDefinition;
48 import org.openecomp.sdc.be.model.dto.PropertyDefinitionDto;
49 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
50 import org.openecomp.sdc.be.model.mapper.PropertyDefinitionDtoMapper;
51 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
52 import org.openecomp.sdc.be.resources.data.DataTypeData;
53 import org.openecomp.sdc.be.resources.data.PropertyData;
54 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57 import org.springframework.beans.factory.annotation.Autowired;
58 import org.springframework.stereotype.Component;
60 @Component("dataType-operation")
61 public class DataTypeOperation extends AbstractOperation {
63 private static final Logger LOGGER = LoggerFactory.getLogger(DataTypeOperation.class);
65 private ModelOperation modelOperation;
66 private PropertyOperation propertyOperation;
69 public DataTypeOperation(final HealingJanusGraphGenericDao janusGraphGenericDao) {
70 this.janusGraphGenericDao = janusGraphGenericDao;
73 //circular dependency ModelOperation->ModelElementOperation->DataTypeOperation
75 public void setModelOperation(final ModelOperation modelOperation) {
76 this.modelOperation = modelOperation;
80 public void setPropertyOperation(PropertyOperation propertyOperation) {
81 this.propertyOperation = propertyOperation;
84 public List<DataTypeData> getAllDataTypeNodes() {
85 final List<DataTypeData> dataTypesFound = new ArrayList<>();
86 final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesWithNullModel =
87 janusGraphGenericDao.getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
89 final var dataTypesValidated = validateDataType(getAllDataTypesWithNullModel, null);
90 if (CollectionUtils.isNotEmpty(dataTypesValidated)) {
91 dataTypesFound.addAll(dataTypesValidated);
94 final List<DataTypeData> allDataTypeNodesWithModel = getAllDataTypesWithModel();
95 if (CollectionUtils.isNotEmpty(allDataTypeNodesWithModel)) {
96 dataTypesFound.addAll(allDataTypeNodesWithModel);
98 return dataTypesFound;
101 public Map<String, List<String>> getAllDataTypeUidsToModels() {
102 final Map<String, List<String>> dataTypesFound = new HashMap<>();
103 final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesWithNullModel =
104 janusGraphGenericDao.getByCriteria(NodeTypeEnum.DataType, null, DataTypeData.class);
106 final var dataTypesValidated = validateDataType(getAllDataTypesWithNullModel, null);
108 for (DataTypeData dataType : dataTypesValidated) {
109 if (!dataTypesFound.containsKey(dataType.getUniqueId())) {
110 dataTypesFound.put(dataType.getUniqueId(), new ArrayList<>());
112 dataTypesFound.get(dataType.getUniqueId()).add(null);
115 modelOperation.findAllModels()
117 for (DataTypeData dataType : getAllDataTypesWithModel(model.getName())) {
118 if (!dataTypesFound.containsKey(dataType.getUniqueId())) {
119 dataTypesFound.put(dataType.getUniqueId(), new ArrayList<>());
121 dataTypesFound.get(dataType.getUniqueId()).add(model.getName());
124 return dataTypesFound;
127 private List<DataTypeData> getAllDataTypesWithModel(final String modelName) {
128 final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesByModel = janusGraphGenericDao
129 .getByCriteriaForModel(NodeTypeEnum.DataType, null, modelName, DataTypeData.class);
130 return validateDataType(getAllDataTypesByModel, modelName);
133 private List<DataTypeData> getAllDataTypesWithModel() {
134 final List<DataTypeData> dataTypesWithModel = new ArrayList<>();
135 modelOperation.findAllModels()
137 final var modelName = model.getName();
138 final Either<List<DataTypeData>, JanusGraphOperationStatus> getAllDataTypesByModel = janusGraphGenericDao
139 .getByCriteriaForModel(NodeTypeEnum.DataType, null, modelName, DataTypeData.class);
140 final var dataTypesValidated = validateDataType(getAllDataTypesByModel, modelName);
141 dataTypesWithModel.addAll(dataTypesValidated);
143 return dataTypesWithModel;
146 private List<DataTypeData> validateDataType(final Either<List<DataTypeData>, JanusGraphOperationStatus> getDataTypes, final String modelName) {
147 if (getDataTypes.isRight() && getDataTypes.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
148 return Collections.emptyList();
150 if (getDataTypes.isRight()) {
151 final var status = getDataTypes.right().value();
152 if (LOGGER.isErrorEnabled()) {
153 final var errorMsg = String.format("Failed to fetch data types from database with model %s. Status is %s", modelName, status);
154 LOGGER.error(String.valueOf(EcompLoggerErrorCode.UNKNOWN_ERROR), DataTypeOperation.class.getName(), errorMsg);
155 BeEcompErrorManager.getInstance().logInternalConnectionError(DataTypeOperation.class.getName(), errorMsg, ErrorSeverity.ERROR);
157 return Collections.emptyList();
159 return getDataTypes.left().value();
162 public void deleteDataTypesByModelId(final String modelId) {
163 final JanusGraph janusGraph = janusGraphGenericDao.getJanusGraph();
164 final GraphTraversalSource traversal = janusGraph.traversal();
165 final List<Vertex> dataTypeList = traversal.V()
166 .has(GraphPropertiesDictionary.UNIQUE_ID.getProperty(), modelId)
167 .out(GraphEdgeLabels.MODEL_ELEMENT.getProperty())
168 .has(GraphPropertiesDictionary.LABEL.getProperty(), NodeTypeEnum.DataType.getName())
170 dataTypeList.forEach(dataTypeVertex -> {
171 traversal.V(dataTypeVertex).out(GraphEdgeLabels.PROPERTY.getProperty()).drop().iterate();
172 dataTypeVertex.remove();
176 public Optional<DataTypeDataDefinition> getDataTypeByUid(final String uniqueId) {
177 final Either<DataTypeData, JanusGraphOperationStatus> dataTypeEither = janusGraphGenericDao
178 .getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.DataType), uniqueId, DataTypeData.class);
179 if (dataTypeEither.isRight()) {
180 if (JanusGraphOperationStatus.NOT_FOUND.equals(dataTypeEither.right().value())) {
181 return Optional.empty();
183 final StorageOperationStatus storageOperationStatus
184 = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(dataTypeEither.right().value());
185 LOGGER.warn("Failed to fetch data type '{}' from JanusGraph. Status is: {}", uniqueId, storageOperationStatus);
186 throw new OperationException(ActionStatus.GENERAL_ERROR,
187 String.format("Failed to fetch data type '%s' from JanusGraph. Status is: %s", uniqueId, storageOperationStatus));
189 return Optional.of(dataTypeEither.left().value().getDataTypeDataDefinition());
192 public Optional<DataTypeDataDefinition> getDataTypeByNameAndModel(final String name, String model) {
193 final Either<DataTypeData, JanusGraphOperationStatus> dataTypeEither = janusGraphGenericDao
194 .getNode("name", name, DataTypeData.class, model);
195 if (dataTypeEither.isRight()) {
196 if (JanusGraphOperationStatus.NOT_FOUND.equals(dataTypeEither.right().value())) {
197 return Optional.empty();
199 final StorageOperationStatus storageOperationStatus
200 = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(dataTypeEither.right().value());
201 LOGGER.warn("Failed to fetch data type '{}' from JanusGraph. Status is: {}", name, storageOperationStatus);
202 throw new OperationException(ActionStatus.GENERAL_ERROR,
203 String.format("Failed to fetch data type '%s' from JanusGraph. Status is: %s", name, storageOperationStatus));
205 return Optional.of(dataTypeEither.left().value().getDataTypeDataDefinition());
208 public List<PropertyDefinition> findAllProperties(final String uniqueId) {
209 final Either<Map<String, PropertyDefinition>, JanusGraphOperationStatus> propertiesEither =
210 propertyOperation.findPropertiesOfNode(NodeTypeEnum.DataType, uniqueId);
211 if (propertiesEither.isRight()) {
212 final JanusGraphOperationStatus status = propertiesEither.right().value();
213 if (status == JanusGraphOperationStatus.NOT_FOUND) {
216 LOGGER.error("Could not retrieve data type '{}' properties. JanusGraphOperationStatus: '{}'", uniqueId, status);
218 throw DataTypeOperationExceptionSupplier.unexpectedErrorWhileFetchingProperties(uniqueId).get();
220 final Map<String, PropertyDefinition> propertyMap = propertiesEither.left().value();
221 if (MapUtils.isEmpty(propertyMap)) {
224 final List<PropertyDefinition> propertyDefinitions = new ArrayList<>(propertyMap.values());
225 propertyDefinitions.sort(Comparator.comparing(PropertyDefinition::getName));
226 return propertyDefinitions;
229 public Optional<DataTypeDefinition> handleDataTypeDownloadRequestById(final String dataTypeId) {
230 if (StringUtils.isNotEmpty(dataTypeId)) {
231 Optional<DataTypeDataDefinition> dataTypeDataDefinition = getDataTypeByUid(dataTypeId);
232 if (dataTypeDataDefinition.isPresent()) {
233 DataTypeDefinition dataTypeDefinition = new DataTypeDefinition(dataTypeDataDefinition.get());
234 dataTypeDefinition.setProperties(findAllProperties(dataTypeId));
235 return Optional.of(dataTypeDefinition);
238 return Optional.empty();
241 public PropertyDefinitionDto createProperty(final String dataTypeId, final PropertyDefinitionDto propertyDefinitionDto) {
242 final String propertyName = propertyDefinitionDto.getName();
243 LOGGER.debug("Adding property '{}' to data type '{}'.", propertyName, dataTypeId);
245 getDataTypeByUid(dataTypeId).orElseThrow(DataTypeOperationExceptionSupplier.dataTypeNotFound(dataTypeId));
247 final Either<PropertyData, JanusGraphOperationStatus> resultEither =
248 propertyOperation.addPropertyToNodeType(propertyName, PropertyDefinitionDtoMapper.mapTo(propertyDefinitionDto),
249 NodeTypeEnum.DataType, dataTypeId, false);
250 if (resultEither.isRight()) {
251 final JanusGraphOperationStatus status = resultEither.right().value();
252 LOGGER.debug("Could not create property '{}' on data type '{}'. JanusGraph status is '{}'", propertyName, dataTypeId, status);
253 if (status == JanusGraphOperationStatus.JANUSGRAPH_SCHEMA_VIOLATION) {
254 throw DataTypeOperationExceptionSupplier.dataTypePropertyAlreadyExists(dataTypeId, propertyName).get();
256 LOGGER.error("Could not create property '{}' on data type '{}'. JanusGraph status is '{}'", propertyName, dataTypeId, status);
257 throw DataTypeOperationExceptionSupplier.unexpectedErrorWhileCreatingProperty(dataTypeId, propertyName).get();
259 LOGGER.debug("Property '{}' was added to data type '{}'.", propertyName, dataTypeId);
260 final PropertyData propertyData = resultEither.left().value();
261 final PropertyDataDefinition propertyDataDefinition = propertyData.getPropertyDataDefinition();
262 propertyDataDefinition.setName(propertyName);
263 return PropertyDefinitionDtoMapper.mapFrom(propertyDataDefinition);