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=========================================================
19 * Modifications copyright (c) 2019 Nokia
20 * ================================================================================
23 package org.openecomp.sdc.be.components.impl;
25 import fj.data.Either;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
28 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
29 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
30 import org.openecomp.sdc.be.config.BeEcompErrorManager;
31 import org.openecomp.sdc.be.dao.api.ActionStatus;
32 import org.openecomp.sdc.be.datatypes.elements.ToscaTypeDataDefinition;
33 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
34 import org.openecomp.sdc.be.impl.ComponentsUtils;
35 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
36 import org.openecomp.sdc.be.model.DataTypeDefinition;
37 import org.openecomp.sdc.be.model.GroupTypeDefinition;
38 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
39 import org.openecomp.sdc.be.model.PropertyDefinition;
40 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
41 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
42 import org.openecomp.sdc.be.model.operations.api.TypeOperations;
43 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
44 import org.openecomp.sdc.common.log.wrappers.Logger;
45 import org.openecomp.sdc.exception.ResponseFormat;
46 import org.springframework.beans.factory.annotation.Autowired;
47 import org.springframework.stereotype.Component;
48 import org.yaml.snakeyaml.Yaml;
50 import java.util.ArrayList;
51 import java.util.HashMap;
52 import java.util.Iterator;
53 import java.util.List;
55 import java.util.Map.Entry;
56 import java.util.function.BiFunction;
57 import java.util.function.Consumer;
58 import java.util.function.Function;
59 import java.util.stream.Collectors;
61 import static java.util.stream.Collectors.toList;
63 @Component("commonImportManager")
64 public class CommonImportManager {
66 private static final Logger log = Logger.getLogger(CommonImportManager.class.getName());
68 private final ComponentsUtils componentsUtils;
69 private final PropertyOperation propertyOperation;
72 public CommonImportManager(ComponentsUtils componentsUtils, PropertyOperation propertyOperation) {
73 this.componentsUtils = componentsUtils;
74 this.propertyOperation = propertyOperation;
77 public static void setProperties(Map<String, Object> toscaJson, Consumer<List<PropertyDefinition>> consumer) {
78 consumer.accept(getProperties(toscaJson));
81 private static List<PropertyDefinition> getProperties(Map<String, Object> toscaJson) {
82 List<PropertyDefinition> values = null;
83 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = ImportUtils.getProperties(toscaJson);
85 if (properties.isLeft()) {
86 values = new ArrayList<>();
87 Map<String, PropertyDefinition> propertiesMap = properties.left().value();
88 if (propertiesMap != null && !propertiesMap.isEmpty()) {
90 for (Entry<String, PropertyDefinition> entry : propertiesMap.entrySet()) {
91 String propName = entry.getKey();
92 PropertyDefinition propertyDefinition = entry.getValue();
93 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
94 newPropertyDefinition.setName(propName);
95 values.add(newPropertyDefinition);
103 protected void setPropertiesMap(Map<String, Object> toscaJson, Consumer<Map<String, PropertyDefinition>> consumer) {
104 final List<PropertyDefinition> properties = getProperties(toscaJson);
105 if (properties != null) {
106 Map<String, PropertyDefinition> collect = properties.stream()
107 .collect(Collectors.toMap(PropertyDefinition::getName, Function.identity()));
108 consumer.accept(collect);
112 public interface ICreateElementType<T1, T2, T3> {
113 T3 createElement(T1 firstArg, T2 secondArg);
116 protected <T> Either<List<T>, ActionStatus> createElementTypesFromYml(String elementTypesYml, ICreateElementType<String, Map<String, Object>, T> createApi) {
118 List<T> elementTypes;
119 Map<String, Object> toscaJson = convertToFieldMap(elementTypesYml);
120 if (toscaJson==null) {
121 return Either.right(ActionStatus.INVALID_YAML_FILE);
123 elementTypes = createElementTypesFromToscaJsonMap(createApi, toscaJson);
124 return Either.left(elementTypes);
127 @SuppressWarnings("unchecked")
128 private Map<String, Object> convertToFieldMap(String elementTypesYml) {
129 Map<String, Object> toscaJson = null;
131 toscaJson = (Map<String, Object>) new Yaml().load(elementTypesYml);
132 } catch (Exception e) {
133 log.debug("Failed to yaml file {}", elementTypesYml, e);
139 protected <T extends ToscaDataDefinition> List<T> createTypesFromToscaJsonMap(
140 BiFunction<String, Map<String, Object>, T> createApi, Map<String, Object> toscaJson) {
141 List<T> elementTypes = new ArrayList<>();
143 for (Entry<String, Object> elementTypeNameDataEntry : toscaJson.entrySet()) {
144 String elementTypeName = elementTypeNameDataEntry.getKey();
145 Map<String, Object> elementTypeJsonData = (Map<String, Object>) elementTypeNameDataEntry.getValue();
146 T elementDefinition = createApi.apply(elementTypeName, elementTypeJsonData);
147 elementTypes.add(elementDefinition);
152 protected <T> List<T> createElementTypesFromToscaJsonMap(
153 ICreateElementType<String, Map<String, Object>, T> createApi, Map<String, Object> toscaJson) {
154 List<T> elementTypes = new ArrayList<>();
156 for (Entry<String, Object> elementTypeNameDataEntry : toscaJson.entrySet()) {
157 String elementTypeName = elementTypeNameDataEntry.getKey();
158 Map<String, Object> elementTypeJsonData = (Map<String, Object>) elementTypeNameDataEntry.getValue();
159 T elementDefinition = createApi.createElement(elementTypeName, elementTypeJsonData);
160 elementTypes.add(elementDefinition);
165 protected <T> Map<String, T> createElementTypesMapFromToscaJsonMap(
166 ICreateElementType<String, Map<String, Object>, T> createApi, Map<String, Object> toscaJson) {
167 Map<String, T> elementTypesMap = new HashMap<>();
169 Iterator<Entry<String, Object>> elementTypesEntryItr = toscaJson.entrySet().iterator();
170 while (elementTypesEntryItr.hasNext()) {
171 Entry<String, Object> elementTypeNameDataEntry = elementTypesEntryItr.next();
172 String elementTypeName = elementTypeNameDataEntry.getKey();
173 Map<String, Object> elementTypeJsonData = (Map<String, Object>) elementTypeNameDataEntry.getValue();
174 T elementDefinition = createApi.createElement(elementTypeName, elementTypeJsonData);
175 elementTypesMap.put(elementTypeName, elementDefinition);
177 return elementTypesMap;
180 protected <F> void setField(Map<String, Object> toscaJson, String fieldName, Consumer<F> setter) {
181 if (toscaJson.containsKey(fieldName)) {
182 F fieldValue = (F) toscaJson.get(fieldName);
183 setter.accept(fieldValue);
187 public enum ElementTypeEnum {
188 POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE, RELATIONSHIP_TYPE
191 private ActionStatus convertFromStorageResponseForElementType(StorageOperationStatus status, ElementTypeEnum elementTypeEnum) {
193 switch (elementTypeEnum) {
195 ret = componentsUtils.convertFromStorageResponseForGroupType(status);
198 ret = componentsUtils.convertFromStorageResponseForDataType(status);
200 case CAPABILITY_TYPE:
201 ret = componentsUtils.convertFromStorageResponseForCapabilityType(status);
203 case INTERFACE_LIFECYCLE_TYPE:
204 ret = componentsUtils.convertFromStorageResponseForLifecycleType(status);
206 case RELATIONSHIP_TYPE:
207 ret = componentsUtils.convertFromStorageResponseForRelationshipType(status);
210 ret = componentsUtils.convertFromStorageResponse(status);
216 private <T> ResponseFormat getResponseFormatForElementType(ActionStatus actionStatus, ElementTypeEnum elementTypeEnum, T elementTypeDefinition) {
218 switch (elementTypeEnum) {
220 ret = componentsUtils.getResponseFormatByGroupType(actionStatus, (GroupTypeDefinition) elementTypeDefinition);
223 ret = componentsUtils.getResponseFormatByPolicyType(actionStatus, (PolicyTypeDefinition) elementTypeDefinition);
226 ret = componentsUtils.getResponseFormatByDataType(actionStatus, (DataTypeDefinition) elementTypeDefinition, null);
228 case CAPABILITY_TYPE:
229 ret = componentsUtils.getResponseFormatByCapabilityType(actionStatus, (CapabilityTypeDefinition) elementTypeDefinition);
233 ret = componentsUtils.getResponseFormat(actionStatus);
239 private <T extends ToscaDataDefinition> List<ImmutablePair<T, Boolean>> createTypesByDao(List<T> elementTypesToCreate,
240 TypeOperations<T> typeOperations) {
241 List<ImmutablePair<T, Boolean>> createdElementTypes = new ArrayList<>();
242 for (T newTypeDefinition : elementTypesToCreate) {
244 String typeName = newTypeDefinition.getType();
245 T existingDefinition = typeOperations.getLatestType(typeName);
246 if (existingDefinition == null /*new type*/) {
247 typeOperations.addType(newTypeDefinition);
249 if (typeOperations.isSameType(newTypeDefinition, existingDefinition)) {
250 propertyOperation.getJanusGraphGenericDao().rollback();
251 createdElementTypes.add(new ImmutablePair<>(newTypeDefinition, null));
254 typeOperations.updateType(existingDefinition, newTypeDefinition);
257 propertyOperation.getJanusGraphGenericDao().commit();
258 createdElementTypes.add(new ImmutablePair<>(newTypeDefinition, true));
259 } catch (Exception e) {
260 propertyOperation.getJanusGraphGenericDao().rollback();
261 createdElementTypes.add(new ImmutablePair<>(newTypeDefinition, false));
265 return createdElementTypes;
268 protected <T> Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> createElementTypesByDao(List<T> elementTypesToCreate,
269 Function<T, Either<ActionStatus, ResponseFormat>> validator, Function<T, ImmutablePair<ElementTypeEnum, String>> elementInfoGetter,
270 Function<String, Either<T, StorageOperationStatus>> elementFetcher, Function<T, Either<T, StorageOperationStatus>> elementAdder,
271 BiFunction<T, T, Either<T, StorageOperationStatus>> elementUpgrader) {
273 List<ImmutablePair<T, Boolean>> createdElementTypes = new ArrayList<>();
275 Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> eitherResult = Either.left(createdElementTypes);
276 Iterator<T> elementTypeItr = elementTypesToCreate.iterator();
279 while (elementTypeItr.hasNext()) {
280 T elementType = elementTypeItr.next();
281 eitherResult = handleType(elementType, validator, elementInfoGetter, elementFetcher, elementAdder, elementUpgrader)
283 .map(elem -> append(createdElementTypes, elem));
285 if (eitherResult.isRight()) {
289 if(!elementTypeItr.hasNext()) {
290 log.info("all {} were created successfully!!!", elementType);
295 eitherResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
299 if (eitherResult.isLeft()) {
300 propertyOperation.getJanusGraphGenericDao().commit();
303 propertyOperation.getJanusGraphGenericDao().rollback();
310 private static <T> List<T> append(List<T> list, T value) {
316 private <T> Either<ImmutablePair<T, Boolean>, ResponseFormat> handleType(T elementType,
317 Function<T, Either<ActionStatus, ResponseFormat>> validator, Function<T, ImmutablePair<ElementTypeEnum, String>> elementInfoGetter,
318 Function<String, Either<T, StorageOperationStatus>> elementFetcher, Function<T, Either<T, StorageOperationStatus>> elementAdder,
319 BiFunction<T, T, Either<T, StorageOperationStatus>> elementUpgrader) {
321 final ImmutablePair<ElementTypeEnum, String> elementInfo = elementInfoGetter.apply(elementType);
322 ElementTypeEnum elementTypeEnum = elementInfo.left;
323 String elementName = elementInfo.right;
325 Either<ActionStatus, ResponseFormat> validateElementType = validator.apply(elementType);
326 if (validateElementType.isRight()) {
327 ResponseFormat responseFormat = validateElementType.right().value();
328 log.debug("Failed in validation of element type: {}. Response is {}", elementType, responseFormat.getFormattedMessage());
329 return Either.right(responseFormat);
332 log.info("send {} : {} to dao for create", elementTypeEnum, elementName);
334 Either<T, StorageOperationStatus> findElementType = elementFetcher.apply(elementName);
335 if (findElementType.isRight()) {
336 StorageOperationStatus status = findElementType.right().value();
337 log.debug("searched {} finished with result:{}", elementTypeEnum, status);
338 if (status != StorageOperationStatus.NOT_FOUND) {
339 ResponseFormat responseFormat = getResponseFormatForElementType(convertFromStorageResponseForElementType(status, elementTypeEnum), elementTypeEnum, elementType);
340 return Either.right(responseFormat);
342 return addElementType(elementType, elementAdder, elementTypeEnum, elementName);
346 if (elementUpgrader != null) {
347 return updateElementType(elementType, elementUpgrader, elementTypeEnum, elementName, findElementType.left().value());
350 // mshitrit Once GroupType Versions are supported add
352 log.debug("{} : {} already exists.", elementTypeEnum, elementName);
353 return Either.left(new ImmutablePair<>(elementType, false));
359 private <T> Either<ImmutablePair<T, Boolean>, ResponseFormat> addElementType(T elementType, Function<T, Either<T, StorageOperationStatus>> elementAdder, ElementTypeEnum elementTypeEnum, String elementName) {
360 Either<T, StorageOperationStatus> dataModelResponse = elementAdder.apply(elementType);
362 if (dataModelResponse.isRight()) {
363 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("Create {}", elementTypeEnum.name());
364 log.debug("failed to create {}: {}", elementTypeEnum, elementName);
365 if (dataModelResponse.right().value() != StorageOperationStatus.OK) {
366 ResponseFormat responseFormat = getResponseFormatForElementType(convertFromStorageResponseForElementType(dataModelResponse.right().value(), elementTypeEnum), elementTypeEnum, elementType);
368 return Either.right(responseFormat);
370 return Either.left(new ImmutablePair<>(elementType, false));
373 log.debug("{} : {} was created successfully.", elementTypeEnum, elementName);
374 return Either.left(new ImmutablePair<>(elementType, true));
379 private <T> Either<ImmutablePair<T, Boolean>, ResponseFormat> updateElementType(T elementType, BiFunction<T, T, Either<T, StorageOperationStatus>> elementUpgrader,
380 ElementTypeEnum elementTypeEnum, String elementName, T existingElementType) {
381 Either<T, StorageOperationStatus> upgradeResponse = elementUpgrader.apply(elementType, existingElementType);
382 if (upgradeResponse.isRight()) {
383 StorageOperationStatus status = upgradeResponse.right().value();
384 if (status == StorageOperationStatus.OK) {
385 return Either.left(new ImmutablePair<>(elementType, false));
387 ResponseFormat responseFormat = getResponseFormatForElementType(convertFromStorageResponseForElementType(upgradeResponse.right().value(), elementTypeEnum), elementTypeEnum, elementType);
388 return Either.right(responseFormat);
391 log.debug("{} : {} was upgraded successfully.", elementTypeEnum, elementName);
392 return Either.left(new ImmutablePair<>(elementType, true));
397 public <T extends ToscaTypeDataDefinition> Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> createElementTypes(ToscaTypeImportData toscaTypeImportData, Function<String, Either<List<T>, ActionStatus>> elementTypeFromYmlCreater,
398 Function<List<T>, Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> elementTypeDaoCreater) {
399 Either<List<T>, ActionStatus> elementTypes = elementTypeFromYmlCreater.apply(toscaTypeImportData.getToscaTypesYml());
402 .map(err -> componentsUtils.getResponseFormat(err, ""))
404 .map(toscaTypes -> enrichTypesWithNonToscaMetadata(toscaTypes, toscaTypeImportData.getToscaTypeMetadata()))
406 .bind(elementTypeDaoCreater::apply);
409 public <T extends ToscaDataDefinition> List<ImmutablePair<T, Boolean>> createElementTypes(String toscaTypesYml,
410 BiFunction<String, Map<String, Object>, T> createApi,
411 TypeOperations<T> typeOperations) {
412 Map<String, Object> fieldMap = convertToFieldMap(toscaTypesYml);
413 if (fieldMap==null) {
414 throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML_FILE);
416 List<T> elementTypes = createTypesFromToscaJsonMap(createApi, fieldMap);
417 return createTypesByDao(elementTypes, typeOperations);
420 private <T extends ToscaTypeDataDefinition> List<T> enrichTypesWithNonToscaMetadata(List<T> toscaTypes, Map<String, ToscaTypeMetadata> toscaTypeMetadata) {
421 return toscaTypes.stream()
422 .map(toscaType -> setNonToscaMetaDataOnType(toscaTypeMetadata, toscaType))
426 private <T extends ToscaTypeDataDefinition> T setNonToscaMetaDataOnType(Map<String, ToscaTypeMetadata> toscaTypeMetadata, T toscaTypeDefinition) {
427 String toscaType = toscaTypeDefinition.getType();
428 ToscaTypeMetadata typeMetaData = toscaTypeMetadata.get(toscaType);
429 if (typeMetaData == null) {
430 log.debug("failing while trying to associate metadata for type {}. type not exist", toscaType);
431 throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
433 toscaTypeDefinition.setIcon(typeMetaData.getIcon());
434 toscaTypeDefinition.setName(typeMetaData.getDisplayName());
435 return toscaTypeDefinition;
438 public <T> Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> createElementTypes(String elementTypesYml, Function<String, Either<List<T>, ActionStatus>> elementTypeFromYmlCreater,
439 Function<List<T>, Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> elementTypeDaoCreater, ElementTypeEnum elementTypeEnum) {
441 Either<List<T>, ActionStatus> elementTypes = elementTypeFromYmlCreater.apply(elementTypesYml);
442 if (elementTypes.isRight()) {
443 ActionStatus status = elementTypes.right().value();
444 ResponseFormat responseFormat = getResponseFormatForElementType(status, elementTypeEnum, null);
445 return Either.right(responseFormat);
447 return elementTypeDaoCreater.apply(elementTypes.left().value());