Reformat catalog-be
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / InterfaceDefinitionHandler.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2020 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
8  *
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.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19 package org.openecomp.sdc.be.components.impl;
20
21 import static org.openecomp.sdc.be.components.impl.ImportUtils.Constants.QUOTE;
22 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT;
23 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION;
24 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IMPLEMENTATION;
25 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS;
26 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NOTIFICATIONS;
27 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OPERATIONS;
28 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIRED;
29 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.STATUS;
30 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
31
32 import fj.data.Either;
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.LinkedHashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.Optional;
40 import java.util.UUID;
41 import java.util.stream.Collectors;
42 import org.apache.commons.collections.MapUtils;
43 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
44 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
45 import org.openecomp.sdc.be.dao.api.ActionStatus;
46 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
47 import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition;
48 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
49 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
50 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
51 import org.openecomp.sdc.be.model.InputDefinition;
52 import org.openecomp.sdc.be.model.InterfaceDefinition;
53 import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
54 import org.openecomp.sdc.exception.ResponseFormat;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57 import org.springframework.stereotype.Component;
58
59 /**
60  * Handles interface definition TOSCA conversions
61  */
62 @Component("interfaceDefinitionHandler")
63 public class InterfaceDefinitionHandler {
64
65     private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceDefinitionHandler.class);
66     private final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic;
67
68     public InterfaceDefinitionHandler(final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic) {
69         this.interfaceOperationBusinessLogic = interfaceOperationBusinessLogic;
70     }
71
72     /**
73      * Creates an interface definition based on a TOSCA map representing an interface definition.
74      *
75      * @param interfaceDefinitionToscaMap the TOSCA interface definition structure
76      * @return an interface definition representation
77      */
78     public InterfaceDefinition create(final Map<String, Object> interfaceDefinitionToscaMap) {
79         final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
80         if (interfaceDefinitionToscaMap.containsKey(TYPE.getElementName())) {
81             final Object typeObj = interfaceDefinitionToscaMap.get(TYPE.getElementName());
82             if (!(typeObj instanceof String)) {
83                 throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
84             }
85             final String type = (String) typeObj;
86             interfaceDefinition.setType(type);
87             interfaceDefinition.setUniqueId(type.toLowerCase());
88         }
89         final Map<String, InputDefinition> inputDefinitionMap = handleInputs(interfaceDefinitionToscaMap);
90         if (!inputDefinitionMap.isEmpty()) {
91             final Map<String, InputDataDefinition> collect = inputDefinitionMap.entrySet().stream()
92                 .collect(Collectors.toMap(Entry::getKey, value -> new InputDataDefinition(value.getValue())));
93             interfaceDefinition.setInputs(collect);
94         }
95         final Map<String, OperationDataDefinition> operationMap;
96         if (interfaceDefinitionToscaMap.containsKey(OPERATIONS.getElementName()) || interfaceDefinitionToscaMap
97             .containsKey(NOTIFICATIONS.getElementName())) {
98             operationMap = handleOperations(interfaceDefinitionToscaMap);
99             //TODO handle notifications
100         } else {
101             operationMap = handleLegacyOperations(interfaceDefinitionToscaMap);
102         }
103         if (!operationMap.isEmpty()) {
104             validateOperations(interfaceDefinition.getType(), operationMap);
105             interfaceDefinition.setOperations(operationMap);
106         }
107         return interfaceDefinition;
108     }
109
110     private void validateOperations(final String interfaceType, final Map<String, OperationDataDefinition> operationMap) {
111         if (MapUtils.isEmpty(operationMap)) {
112             return;
113         }
114         Either<Map<String, InterfaceDefinition>, ResponseFormat> interfaceDefinitionMapEither = interfaceOperationBusinessLogic
115             .getAllInterfaceLifecycleTypes();
116         if (interfaceDefinitionMapEither.isRight() || MapUtils.isEmpty(interfaceDefinitionMapEither.left().value())) {
117             throw new ByActionStatusComponentException(ActionStatus.INTERFACE_UNKNOWN, interfaceType);
118         }
119         final Map<String, InterfaceDefinition> interfaceDefinitionMap = interfaceDefinitionMapEither.left().value();
120         final Optional<InterfaceDefinition> interfaceDefinitionOptional = interfaceDefinitionMap.entrySet().stream()
121             .filter(interfaceDefinitionEntry -> interfaceDefinitionEntry.getKey().equalsIgnoreCase(interfaceType)).map(Entry::getValue).findFirst();
122         if (interfaceDefinitionOptional.isEmpty()) {
123             throw new ByActionStatusComponentException(ActionStatus.INTERFACE_UNKNOWN, interfaceType);
124         }
125         final InterfaceDefinition interfaceDefinition = interfaceDefinitionOptional.get();
126         operationMap.keySet().forEach(operation1 -> {
127             if (!interfaceDefinition.hasOperation(operation1)) {
128                 throw new ByActionStatusComponentException(ActionStatus.INTERFACE_OPERATION_NOT_DEFINED, operation1, interfaceType);
129             }
130         });
131     }
132
133     private Map<String, OperationDataDefinition> handleOperations(final Map<String, Object> interfaceDefinitionToscaMap) {
134         if (!interfaceDefinitionToscaMap.containsKey(OPERATIONS.getElementName())) {
135             return Collections.emptyMap();
136         }
137         final Map<String, Object> operationMap = (Map<String, Object>) interfaceDefinitionToscaMap.get(OPERATIONS.getElementName());
138         return operationMap.entrySet().stream()
139             .map(interfaceEntry -> createOperation(interfaceEntry.getKey(), (Map<String, Object>) interfaceEntry.getValue()))
140             .collect(Collectors.toMap(OperationDataDefinition::getName, operationDataDefinition -> operationDataDefinition));
141     }
142
143     private Map<String, OperationDataDefinition> handleLegacyOperations(final Map<String, Object> interfaceDefinitionToscaMap) {
144         final List<String> notALegacyOperationEntry = Arrays
145             .asList(OPERATIONS.getElementName(), TYPE.getElementName(), INPUTS.getElementName(), NOTIFICATIONS.getElementName());
146         return interfaceDefinitionToscaMap.entrySet().stream().filter(interfaceEntry -> !notALegacyOperationEntry.contains(interfaceEntry.getKey()))
147             .map(interfaceEntry -> createOperation(interfaceEntry.getKey(), (Map<String, Object>) interfaceEntry.getValue()))
148             .collect(Collectors.toMap(OperationDataDefinition::getName, operationDataDefinition -> operationDataDefinition));
149     }
150
151     private OperationDataDefinition createOperation(final String operationName, final Map<String, Object> operationDefinitionMap) {
152         final OperationDataDefinition operation = new OperationDataDefinition();
153         operation.setUniqueId(UUID.randomUUID().toString());
154         operation.setName(operationName);
155         operation.setImplementation(handleOperationImplementation(operationDefinitionMap).orElse(new ArtifactDataDefinition()));
156         if (operationDefinitionMap.containsKey(INPUTS.getElementName())) {
157             final Map<String, Object> interfaceInputs = (Map<String, Object>) operationDefinitionMap.get(INPUTS.getElementName());
158             operation.setInputs(handleInterfaceOperationInputs(interfaceInputs));
159         }
160         return operation;
161     }
162
163     private ListDataDefinition<OperationInputDefinition> handleInterfaceOperationInputs(final Map<String, Object> interfaceInputs) {
164         final ListDataDefinition<OperationInputDefinition> inputs = new ListDataDefinition<>();
165         for (final Entry<String, Object> interfaceInput : interfaceInputs.entrySet()) {
166             final OperationInputDefinition operationInput = new OperationInputDefinition();
167             operationInput.setUniqueId(UUID.randomUUID().toString());
168             operationInput.setInputId(operationInput.getUniqueId());
169             operationInput.setName(interfaceInput.getKey());
170             if (interfaceInput.getValue() instanceof Map) {
171                 final LinkedHashMap<String, Object> inputPropertyValue = (LinkedHashMap<String, Object>) interfaceInput.getValue();
172                 LOGGER.info("createModuleInterface: i interfaceInput.getKey() {}, {} , {}  ", interfaceInput.getKey(), inputPropertyValue.keySet(),
173                     inputPropertyValue.values());
174                 if (inputPropertyValue.get(TYPE.getElementName()) != null) {
175                     operationInput.setType(inputPropertyValue.get(TYPE.getElementName()).toString());
176                 }
177                 if (inputPropertyValue.get(DESCRIPTION.getElementName()) != null) {
178                     operationInput.setDescription(inputPropertyValue.get(DESCRIPTION.getElementName()).toString());
179                 }
180                 if (inputPropertyValue.get(REQUIRED.getElementName()) != null) {
181                     operationInput.setRequired(Boolean.getBoolean(inputPropertyValue.get(REQUIRED.getElementName()).toString()));
182                 }
183                 if (inputPropertyValue.get(DEFAULT.getElementName()) != null) {
184                     operationInput.setToscaDefaultValue(inputPropertyValue.get(DEFAULT.getElementName()).toString());
185                 }
186                 if (inputPropertyValue.get(STATUS.getElementName()) != null) {
187                     operationInput.setStatus(inputPropertyValue.get(STATUS.getElementName()).toString());
188                 }
189             } else if (interfaceInput.getValue() instanceof String) {
190                 final String value = (String) interfaceInput.getValue();
191                 operationInput.setDefaultValue(value);
192                 operationInput.setToscaDefaultValue(value);
193                 operationInput.setValue(value);
194             }
195             inputs.add(operationInput);
196         }
197         return inputs;
198     }
199
200     private Optional<ArtifactDataDefinition> handleOperationImplementation(final Map<String, Object> operationDefinitionMap) {
201         if (!operationDefinitionMap.containsKey(IMPLEMENTATION.getElementName())) {
202             return Optional.empty();
203         }
204         final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition();
205         final String artifactName = (String) operationDefinitionMap.get(IMPLEMENTATION.getElementName());
206         if (OperationArtifactUtil.artifactNameIsALiteralValue(artifactName)) {
207             artifactDataDefinition.setArtifactName(artifactName);
208         } else {
209             artifactDataDefinition.setArtifactName(QUOTE + artifactName + QUOTE);
210         }
211         return Optional.of(artifactDataDefinition);
212     }
213
214     private Map<String, InputDefinition> handleInputs(final Map<String, Object> interfaceDefinitionToscaMap) {
215         if (!interfaceDefinitionToscaMap.containsKey(INPUTS.getElementName())) {
216             return Collections.emptyMap();
217         }
218         final Either<Map<String, InputDefinition>, ResultStatusEnum> inputMapEither = ImportUtils.getInputs(interfaceDefinitionToscaMap);
219         if (inputMapEither.isRight()) {
220             return Collections.emptyMap();
221         }
222         return inputMapEither.left().value();
223     }
224 }