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