Update base types based on model
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / GroupTypeImportManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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  */
20 package org.openecomp.sdc.be.components.impl;
21
22 import fj.data.Either;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.stream.Collectors;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
30 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
31 import org.openecomp.sdc.be.config.BeEcompErrorManager;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
34 import org.openecomp.sdc.be.impl.ComponentsUtils;
35 import org.openecomp.sdc.be.model.CapabilityDefinition;
36 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
37 import org.openecomp.sdc.be.model.GroupTypeDefinition;
38 import org.openecomp.sdc.be.model.PropertyDefinition;
39 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
40 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
41 import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation;
42 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
43 import org.openecomp.sdc.be.model.utils.TypeCompareUtils;
44 import org.openecomp.sdc.be.utils.TypeUtils;
45 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
46 import org.openecomp.sdc.common.log.wrappers.Logger;
47 import org.openecomp.sdc.exception.ResponseFormat;
48 import org.springframework.stereotype.Component;
49
50 @Component("groupTypeImportManager")
51 public class GroupTypeImportManager {
52
53     private static final Logger log = Logger.getLogger(GroupTypeImportManager.class);
54     private final GroupTypeOperation groupTypeOperation;
55     private final ComponentsUtils componentsUtils;
56     private final ToscaOperationFacade toscaOperationFacade;
57     private final CommonImportManager commonImportManager;
58
59     public GroupTypeImportManager(GroupTypeOperation groupTypeOperation, ComponentsUtils componentsUtils, ToscaOperationFacade toscaOperationFacade,
60                                   CommonImportManager commonImportManager) {
61         this.groupTypeOperation = groupTypeOperation;
62         this.componentsUtils = componentsUtils;
63         this.toscaOperationFacade = toscaOperationFacade;
64         this.commonImportManager = commonImportManager;
65     }
66
67     public Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat> createGroupTypes(ToscaTypeImportData toscaTypeImportData, String modelName) {
68         return commonImportManager.createElementTypes(toscaTypeImportData, this::createGroupTypesFromYml, this::upsertGroupTypesByDao, modelName);
69     }
70
71     private Either<List<GroupTypeDefinition>, ActionStatus> createGroupTypesFromYml(String groupTypesYml, String modelName) {
72         Either<List<GroupTypeDefinition>, ActionStatus> groupTypes = commonImportManager.createElementTypesFromYml(groupTypesYml, this::createGroupType);
73         if (groupTypes.isLeft() && StringUtils.isNotEmpty(modelName)){
74             groupTypes.left().value().forEach(groupType -> groupType.setModel(modelName));
75         }
76         return groupTypes;
77     }
78
79     private Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat> upsertGroupTypesByDao(
80         List<GroupTypeDefinition> groupTypesToCreate, String modelName) {
81         return commonImportManager.createElementTypesWithVersionByDao(groupTypesToCreate, this::validateGroupType,
82             groupType -> new ImmutablePair<>(ElementTypeEnum.GROUP_TYPE, UniqueIdBuilder.buildGroupTypeUid(groupType.getModel(),
83                 groupType.getType(), groupType.getVersion(), NodeTypeEnum.GroupType.getName()).toLowerCase()), groupTypeOperation::getLatestGroupTypeByType,
84             groupTypeOperation::addGroupType, this::updateGroupType, modelName);
85     }
86
87     private Either<GroupTypeDefinition, StorageOperationStatus> updateGroupType(GroupTypeDefinition newGroupType, GroupTypeDefinition oldGroupType) {
88         Either<GroupTypeDefinition, StorageOperationStatus> validationRes = groupTypeOperation.validateUpdateProperties(newGroupType);
89         if (validationRes.isRight()) {
90             log.error("#updateGroupType - One or all properties of group type {} not valid. status is {}", newGroupType,
91                 validationRes.right().value());
92             return validationRes;
93         }
94         if (TypeCompareUtils.isGroupTypesEquals(newGroupType, oldGroupType)) {
95             return TypeCompareUtils.typeAlreadyExists();
96         }
97         return groupTypeOperation.updateGroupType(newGroupType, oldGroupType);
98     }
99
100     private Either<ActionStatus, ResponseFormat> validateGroupType(GroupTypeDefinition groupType) {
101         Either<ActionStatus, ResponseFormat> result = Either.left(ActionStatus.OK);
102         if (groupType.getMembers() != null) {
103             if (groupType.getMembers().isEmpty()) {
104                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GROUP_MEMBER_EMPTY, groupType.getType());
105                 result = Either.right(responseFormat);
106             } else {
107                 for (String member : groupType.getMembers()) {
108                     // Verify that such Resource exist
109                     Either<org.openecomp.sdc.be.model.Resource, StorageOperationStatus> eitherMemberExist = toscaOperationFacade
110                         .getLatestByToscaResourceName(member, groupType.getModel());
111                     if (eitherMemberExist.isRight()) {
112                         StorageOperationStatus operationStatus = eitherMemberExist.right().value();
113                         log.debug("Error when fetching parent resource {}, error: {}", member, operationStatus);
114                         ActionStatus convertFromStorageResponse = componentsUtils.convertFromStorageResponse(operationStatus);
115                         BeEcompErrorManager.getInstance().logBeComponentMissingError("Import GroupType", "resource", member);
116                         result = Either.right(componentsUtils.getResponseFormat(convertFromStorageResponse, member));
117                         break;
118                     }
119                 }
120             }
121         }
122         return result;
123     }
124
125     private GroupTypeDefinition createGroupType(String groupTypeName, Map<String, Object> toscaJson) {
126         GroupTypeDefinition groupType = new GroupTypeDefinition();
127         if (toscaJson != null) {
128             // Description
129             commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName(), groupType::setDescription);
130             // Derived From
131             commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName(), groupType::setDerivedFrom);
132             // Properties
133             CommonImportManager.setProperties(toscaJson, groupType::setProperties);
134             // Metadata
135             commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.METADATA.getElementName(), groupType::setMetadata);
136             // Capabilities
137             Map<String, CapabilityDefinition> capabilities = createCapabilities(toscaJson);
138             groupType.setCapabilities(capabilities);
139             // Members
140             commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.MEMBERS.getElementName(), groupType::setMembers);
141             groupType.setType(groupTypeName);
142             groupType.setHighestVersion(true);
143             groupType.setVersion(TypeUtils.getFirstCertifiedVersionVersion());
144         }
145         return groupType;
146     }
147
148     /**
149      * @param toscaJson
150      * @return
151      */
152     private Map<String, CapabilityDefinition> createCapabilities(Map<String, Object> toscaJson) {
153         CapabilityTypeToscaJsonHolder capabilityTypeToscaJsonHolder = new CapabilityTypeToscaJsonHolder();
154         commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.CAPABILITIES.getElementName(),
155             capabilityTypeToscaJsonHolder::setCapabilityTypeToscaJson);
156         Map<String, CapabilityDefinition> capabilities;
157         if (capabilityTypeToscaJsonHolder.isEmpty()) {
158             capabilities = Collections.emptyMap();
159         } else {
160             capabilities = commonImportManager
161                 .createElementTypesMapFromToscaJsonMap(this::createCapability, capabilityTypeToscaJsonHolder.getCapabilityTypeToscaJson());
162         }
163         return capabilities;
164     }
165
166     private CapabilityDefinition createCapability(String capabilityName, Map<String, Object> toscaJson) {
167         CapabilityDefinition capability = new CapabilityDefinition();
168         capability.setName(capabilityName);
169         commonImportManager.setField(toscaJson, ToscaTagNamesEnum.TYPE.getElementName(), capability::setType);
170         // Properties
171         CommonImportManager.setProperties(toscaJson, pl -> capability.setProperties(map(pl)));
172         return capability;
173     }
174
175     /**
176      * @param pl
177      * @return
178      */
179     private List<ComponentInstanceProperty> map(List<PropertyDefinition> pl) {
180         return pl.stream().map(ComponentInstanceProperty::new).collect(Collectors.toList());
181     }
182
183     private class CapabilityTypeToscaJsonHolder {
184
185         private Map<String, Object> capabilityTypeToscaJson;
186
187         public Map<String, Object> getCapabilityTypeToscaJson() {
188             return capabilityTypeToscaJson;
189         }
190
191         public void setCapabilityTypeToscaJson(Map<String, Object> capabilityTypeToscaJson) {
192             this.capabilityTypeToscaJson = capabilityTypeToscaJson;
193         }
194
195         public boolean isEmpty() {
196             return capabilityTypeToscaJson == null;
197         }
198     }
199 }