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.components.impl;
23 import fj.data.Either;
24 import org.apache.commons.lang3.tuple.ImmutablePair;
25 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
26 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
27 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
28 import org.openecomp.sdc.be.config.BeEcompErrorManager;
29 import org.openecomp.sdc.be.dao.api.ActionStatus;
30 import org.openecomp.sdc.be.datatypes.elements.ToscaTypeDataDefinition;
31 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
32 import org.openecomp.sdc.be.impl.ComponentsUtils;
33 import org.openecomp.sdc.be.model.*;
34 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
35 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
36 import org.openecomp.sdc.be.model.operations.api.TypeOperations;
37 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
38 import org.openecomp.sdc.common.log.wrappers.Logger;
39 import org.openecomp.sdc.exception.ResponseFormat;
40 import org.springframework.stereotype.Component;
41 import org.yaml.snakeyaml.Yaml;
44 import java.util.Map.Entry;
45 import java.util.function.BiFunction;
46 import java.util.function.Consumer;
47 import java.util.function.Function;
48 import java.util.stream.Collectors;
50 import static java.util.stream.Collectors.toList;
52 @Component("commonImportManager")
53 public class CommonImportManager {
55 private static final Logger log = Logger.getLogger(CommonImportManager.class.getName());
57 private final ComponentsUtils componentsUtils;
58 private final PropertyOperation propertyOperation;
60 public CommonImportManager(ComponentsUtils componentsUtils, PropertyOperation propertyOperation) {
61 this.componentsUtils = componentsUtils;
62 this.propertyOperation = propertyOperation;
65 public static void setProperties(Map<String, Object> toscaJson, Consumer<List<PropertyDefinition>> consumer) {
66 consumer.accept(getProperties(toscaJson));
69 private static List<PropertyDefinition> getProperties(Map<String, Object> toscaJson) {
70 List<PropertyDefinition> values = null;
71 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = ImportUtils.getProperties(toscaJson);
73 if (properties.isLeft()) {
74 values = new ArrayList<>();
75 Map<String, PropertyDefinition> propertiesMap = properties.left().value();
76 if (propertiesMap != null && !propertiesMap.isEmpty()) {
78 for (Entry<String, PropertyDefinition> entry : propertiesMap.entrySet()) {
79 String propName = entry.getKey();
80 PropertyDefinition propertyDefinition = entry.getValue();
81 PropertyDefinition newPropertyDefinition = new PropertyDefinition(propertyDefinition);
82 newPropertyDefinition.setName(propName);
83 values.add(newPropertyDefinition);
91 protected void setPropertiesMap(Map<String, Object> toscaJson, Consumer<Map<String, PropertyDefinition>> consumer) {
92 final List<PropertyDefinition> properties = getProperties(toscaJson);
93 if (properties != null) {
94 Map<String, PropertyDefinition> collect = properties.stream()
95 .collect(Collectors.toMap(PropertyDefinition::getName, Function.identity()));
96 consumer.accept(collect);
100 public interface ICreateElementType<T1, T2, T3> {
101 T3 createElement(T1 firstArg, T2 secondArg);
104 protected <T> Either<List<T>, ActionStatus> createElementTypesFromYml(String elementTypesYml, ICreateElementType<String, Map<String, Object>, T> createApi) {
106 List<T> elementTypes;
107 Map<String, Object> toscaJson = convertToFieldMap(elementTypesYml);
108 if (toscaJson==null) {
109 return Either.right(ActionStatus.INVALID_YAML_FILE);
111 elementTypes = createElementTypesFromToscaJsonMap(createApi, toscaJson);
112 return Either.left(elementTypes);
115 @SuppressWarnings("unchecked")
116 private Map<String, Object> convertToFieldMap(String elementTypesYml) {
117 Map<String, Object> toscaJson = null;
119 toscaJson = (Map<String, Object>) new Yaml().load(elementTypesYml);
120 } catch (Exception e) {
121 log.debug("Failed to yaml file {}", elementTypesYml, e);
127 protected <T extends ToscaDataDefinition> List<T> createTypesFromToscaJsonMap(
128 BiFunction<String, Map<String, Object>, T> createApi, Map<String, Object> toscaJson) {
129 List<T> elementTypes = new ArrayList<>();
131 for (Entry<String, Object> elementTypeNameDataEntry : toscaJson.entrySet()) {
132 String elementTypeName = elementTypeNameDataEntry.getKey();
133 Map<String, Object> elementTypeJsonData = (Map<String, Object>) elementTypeNameDataEntry.getValue();
134 T elementDefinition = createApi.apply(elementTypeName, elementTypeJsonData);
135 elementTypes.add(elementDefinition);
140 protected <T> List<T> createElementTypesFromToscaJsonMap(
141 ICreateElementType<String, Map<String, Object>, T> createApi, Map<String, Object> toscaJson) {
142 List<T> elementTypes = new ArrayList<>();
144 for (Entry<String, Object> elementTypeNameDataEntry : toscaJson.entrySet()) {
145 String elementTypeName = elementTypeNameDataEntry.getKey();
146 Map<String, Object> elementTypeJsonData = (Map<String, Object>) elementTypeNameDataEntry.getValue();
147 T elementDefinition = createApi.createElement(elementTypeName, elementTypeJsonData);
148 elementTypes.add(elementDefinition);
153 protected <T> Map<String, T> createElementTypesMapFromToscaJsonMap(
154 ICreateElementType<String, Map<String, Object>, T> createApi, Map<String, Object> toscaJson) {
155 Map<String, T> elementTypesMap = new HashMap<>();
157 Iterator<Entry<String, Object>> elementTypesEntryItr = toscaJson.entrySet().iterator();
158 while (elementTypesEntryItr.hasNext()) {
159 Entry<String, Object> elementTypeNameDataEntry = elementTypesEntryItr.next();
160 String elementTypeName = elementTypeNameDataEntry.getKey();
161 Map<String, Object> elementTypeJsonData = (Map<String, Object>) elementTypeNameDataEntry.getValue();
162 T elementDefinition = createApi.createElement(elementTypeName, elementTypeJsonData);
163 elementTypesMap.put(elementTypeName, elementDefinition);
165 return elementTypesMap;
168 protected <F> void setField(Map<String, Object> toscaJson, String fieldName, Consumer<F> setter) {
169 if (toscaJson.containsKey(fieldName)) {
170 F fieldValue = (F) toscaJson.get(fieldName);
171 setter.accept(fieldValue);
175 public enum ElementTypeEnum {
176 POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE
179 private ActionStatus convertFromStorageResponseForElementType(StorageOperationStatus status, ElementTypeEnum elementTypeEnum) {
181 switch (elementTypeEnum) {
183 ret = componentsUtils.convertFromStorageResponseForGroupType(status);
186 ret = componentsUtils.convertFromStorageResponseForDataType(status);
188 case CAPABILITY_TYPE:
189 ret = componentsUtils.convertFromStorageResponseForCapabilityType(status);
191 case INTERFACE_LIFECYCLE_TYPE:
192 ret = componentsUtils.convertFromStorageResponseForLifecycleType(status);
195 ret = componentsUtils.convertFromStorageResponse(status);
201 private <T> ResponseFormat getResponseFormatForElementType(ActionStatus actionStatus, ElementTypeEnum elementTypeEnum, T elementTypeDefinition) {
203 switch (elementTypeEnum) {
205 ret = componentsUtils.getResponseFormatByGroupType(actionStatus, (GroupTypeDefinition) elementTypeDefinition);
208 ret = componentsUtils.getResponseFormatByPolicyType(actionStatus, (PolicyTypeDefinition) elementTypeDefinition);
211 ret = componentsUtils.getResponseFormatByDataType(actionStatus, (DataTypeDefinition) elementTypeDefinition, null);
213 case CAPABILITY_TYPE:
214 ret = componentsUtils.getResponseFormatByCapabilityType(actionStatus, (CapabilityTypeDefinition) elementTypeDefinition);
218 ret = componentsUtils.getResponseFormat(actionStatus);
224 private <T extends ToscaDataDefinition> List<ImmutablePair<T, Boolean>> createTypesByDao(List<T> elementTypesToCreate,
225 TypeOperations<T> typeOperations) {
226 List<ImmutablePair<T, Boolean>> createdElementTypes = new ArrayList<>();
227 for (T newTypeDefinition : elementTypesToCreate) {
229 String typeName = newTypeDefinition.getType();
230 T existingDefinition = typeOperations.getLatestType(typeName);
231 if (existingDefinition == null /*new type*/) {
232 typeOperations.addType(newTypeDefinition);
234 if (typeOperations.isSameType(newTypeDefinition, existingDefinition)) {
235 propertyOperation.getTitanGenericDao().rollback();
236 createdElementTypes.add(new ImmutablePair<>(newTypeDefinition, null));
239 typeOperations.updateType(existingDefinition, newTypeDefinition);
242 propertyOperation.getTitanGenericDao().commit();
243 createdElementTypes.add(new ImmutablePair<>(newTypeDefinition, true));
244 } catch (Exception e) {
245 propertyOperation.getTitanGenericDao().rollback();
246 createdElementTypes.add(new ImmutablePair<>(newTypeDefinition, false));
250 return createdElementTypes;
253 protected <T> Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> createElementTypesByDao(List<T> elementTypesToCreate,
254 Function<T, Either<ActionStatus, ResponseFormat>> validator, Function<T, ImmutablePair<ElementTypeEnum, String>> elementInfoGetter,
255 Function<String, Either<T, StorageOperationStatus>> elementFetcher, Function<T, Either<T, StorageOperationStatus>> elementAdder,
256 BiFunction<T, T, Either<T, StorageOperationStatus>> elementUpgrader) {
258 List<ImmutablePair<T, Boolean>> createdElementTypes = new ArrayList<>();
260 Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> eitherResult = Either.left(createdElementTypes);
261 Iterator<T> elementTypeItr = elementTypesToCreate.iterator();
264 while (elementTypeItr.hasNext()) {
265 T elementType = elementTypeItr.next();
266 eitherResult = handleType(elementType, validator, elementInfoGetter, elementFetcher, elementAdder, elementUpgrader)
268 .map(elem -> append(createdElementTypes, elem));
270 if (eitherResult.isRight()) {
274 if(!elementTypeItr.hasNext()) {
275 log.info("all {} were created successfully!!!", elementType);
280 eitherResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
284 if (eitherResult.isLeft()) {
285 propertyOperation.getTitanGenericDao().commit();
288 propertyOperation.getTitanGenericDao().rollback();
295 private static <T> List<T> append(List<T> list, T value) {
301 private <T> Either<ImmutablePair<T, Boolean>, ResponseFormat> handleType(T elementType,
302 Function<T, Either<ActionStatus, ResponseFormat>> validator, Function<T, ImmutablePair<ElementTypeEnum, String>> elementInfoGetter,
303 Function<String, Either<T, StorageOperationStatus>> elementFetcher, Function<T, Either<T, StorageOperationStatus>> elementAdder,
304 BiFunction<T, T, Either<T, StorageOperationStatus>> elementUpgrader) {
306 final ImmutablePair<ElementTypeEnum, String> elementInfo = elementInfoGetter.apply(elementType);
307 ElementTypeEnum elementTypeEnum = elementInfo.left;
308 String elementName = elementInfo.right;
310 Either<ActionStatus, ResponseFormat> validateElementType = validator.apply(elementType);
311 if (validateElementType.isRight()) {
312 ResponseFormat responseFormat = validateElementType.right().value();
313 log.debug("Failed in validation of element type: {}. Response is {}", elementType, responseFormat.getFormattedMessage());
314 return Either.right(responseFormat);
317 log.info("send {} : {} to dao for create", elementTypeEnum, elementName);
319 Either<T, StorageOperationStatus> findElementType = elementFetcher.apply(elementName);
320 if (findElementType.isRight()) {
321 StorageOperationStatus status = findElementType.right().value();
322 log.debug("searched {} finished with result:{}", elementTypeEnum, status);
323 if (status != StorageOperationStatus.NOT_FOUND) {
324 ResponseFormat responseFormat = getResponseFormatForElementType(convertFromStorageResponseForElementType(status, elementTypeEnum), elementTypeEnum, elementType);
325 return Either.right(responseFormat);
327 return addElementType(elementType, elementAdder, elementTypeEnum, elementName);
331 if (elementUpgrader != null) {
332 return updateElementType(elementType, elementUpgrader, elementTypeEnum, elementName, findElementType.left().value());
335 // mshitrit Once GroupType Versions are supported add
337 log.debug("{} : {} already exists.", elementTypeEnum, elementName);
338 return Either.left(new ImmutablePair<>(elementType, false));
344 private <T> Either<ImmutablePair<T, Boolean>, ResponseFormat> addElementType(T elementType, Function<T, Either<T, StorageOperationStatus>> elementAdder, ElementTypeEnum elementTypeEnum, String elementName) {
345 Either<T, StorageOperationStatus> dataModelResponse = elementAdder.apply(elementType);
347 if (dataModelResponse.isRight()) {
348 BeEcompErrorManager.getInstance().logBeFailedAddingNodeTypeError("Create {}", elementTypeEnum.name());
349 log.debug("failed to create {}: {}", elementTypeEnum, elementName);
350 if (dataModelResponse.right().value() != StorageOperationStatus.OK) {
351 ResponseFormat responseFormat = getResponseFormatForElementType(convertFromStorageResponseForElementType(dataModelResponse.right().value(), elementTypeEnum), elementTypeEnum, elementType);
353 return Either.right(responseFormat);
355 return Either.left(new ImmutablePair<>(elementType, false));
358 log.debug("{} : {} was created successfully.", elementTypeEnum, elementName);
359 return Either.left(new ImmutablePair<>(elementType, true));
364 private <T> Either<ImmutablePair<T, Boolean>, ResponseFormat> updateElementType(T elementType, BiFunction<T, T, Either<T, StorageOperationStatus>> elementUpgrader,
365 ElementTypeEnum elementTypeEnum, String elementName, T existingElementType) {
366 Either<T, StorageOperationStatus> upgradeResponse = elementUpgrader.apply(elementType, existingElementType);
367 if (upgradeResponse.isRight()) {
368 StorageOperationStatus status = upgradeResponse.right().value();
369 if (status == StorageOperationStatus.OK) {
370 return Either.left(new ImmutablePair<>(elementType, false));
372 ResponseFormat responseFormat = getResponseFormatForElementType(convertFromStorageResponseForElementType(upgradeResponse.right().value(), elementTypeEnum), elementTypeEnum, elementType);
373 return Either.right(responseFormat);
376 log.debug("{} : {} was upgraded successfully.", elementTypeEnum, elementName);
377 return Either.left(new ImmutablePair<>(elementType, true));
382 public <T extends ToscaTypeDataDefinition> Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> createElementTypes(ToscaTypeImportData toscaTypeImportData, Function<String, Either<List<T>, ActionStatus>> elementTypeFromYmlCreater,
383 Function<List<T>, Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> elementTypeDaoCreater) {
384 Either<List<T>, ActionStatus> elementTypes = elementTypeFromYmlCreater.apply(toscaTypeImportData.getToscaTypesYml());
387 .map(err -> componentsUtils.getResponseFormat(err, ""))
389 .map(toscaTypes -> enrichTypesWithNonToscaMetadata(toscaTypes, toscaTypeImportData.getToscaTypeMetadata()))
391 .bind(elementTypeDaoCreater::apply);
394 public <T extends ToscaDataDefinition> List<ImmutablePair<T, Boolean>> createElementTypes(String toscaTypesYml,
395 BiFunction<String, Map<String, Object>, T> createApi,
396 TypeOperations<T> typeOperations) {
397 Map<String, Object> fieldMap = convertToFieldMap(toscaTypesYml);
398 if (fieldMap==null) {
399 throw new ComponentException(ActionStatus.INVALID_YAML_FILE);
401 List<T> elementTypes = createTypesFromToscaJsonMap(createApi, fieldMap);
402 return createTypesByDao(elementTypes, typeOperations);
405 private <T extends ToscaTypeDataDefinition> List<T> enrichTypesWithNonToscaMetadata(List<T> toscaTypes, Map<String, ToscaTypeMetadata> toscaTypeMetadata) {
406 return toscaTypes.stream()
407 .map(toscaType -> setNonToscaMetaDataOnType(toscaTypeMetadata, toscaType))
411 private <T extends ToscaTypeDataDefinition> T setNonToscaMetaDataOnType(Map<String, ToscaTypeMetadata> toscaTypeMetadata, T toscaTypeDefinition) {
412 String toscaType = toscaTypeDefinition.getType();
413 ToscaTypeMetadata typeMetaData = toscaTypeMetadata.get(toscaType);
414 if (typeMetaData == null) {
415 log.debug("failing while trying to associate metadata for type {}. type not exist", toscaType);
416 throw new ComponentException(ActionStatus.GENERAL_ERROR);
418 toscaTypeDefinition.setIcon(typeMetaData.getIcon());
419 toscaTypeDefinition.setName(typeMetaData.getDisplayName());
420 return toscaTypeDefinition;
423 public <T> Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> createElementTypes(String elementTypesYml, Function<String, Either<List<T>, ActionStatus>> elementTypeFromYmlCreater,
424 Function<List<T>, Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> elementTypeDaoCreater, ElementTypeEnum elementTypeEnum) {
426 Either<List<T>, ActionStatus> elementTypes = elementTypeFromYmlCreater.apply(elementTypesYml);
427 if (elementTypes.isRight()) {
428 ActionStatus status = elementTypes.right().value();
429 ResponseFormat responseFormat = getResponseFormatForElementType(status, elementTypeEnum, null);
430 return Either.right(responseFormat);
432 return elementTypeDaoCreater.apply(elementTypes.left().value());