fixed interfaces + interface_types when no op
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / utils / InterfacesOperationsToscaUtil.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
17 package org.openecomp.sdc.be.tosca.utils;
18
19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25 import org.apache.commons.collections.MapUtils;
26 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
27 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
28 import org.openecomp.sdc.be.model.Component;
29 import org.openecomp.sdc.be.model.InterfaceDefinition;
30 import org.openecomp.sdc.be.model.Product;
31 import org.openecomp.sdc.be.model.Resource;
32 import org.openecomp.sdc.be.model.Service;
33 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
34 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceNodeType;
35 import org.openecomp.sdc.be.tosca.model.ToscaLifecycleOperationDefinition;
36 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
37 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
38
39 /**
40  * @author KATYR
41  * @since March 20, 2018
42  */
43
44 public class InterfacesOperationsToscaUtil {
45
46     private static final String DERIVED_FROM_STANDARD_INTERFACE = "tosca.interfaces.node.lifecycle.Standard";
47     private static final String OPERATIONS_KEY = "operations";
48
49     private static final String DEFAULT = "default";
50     private static final String _DEFAULT = "_default";
51     private static final String DOT = ".";
52     private static final String DEFAULT_INPUT_TYPE = "string";
53     private static final String SELF = "SELF";
54     private static final String GET_PROPERTY = "get_property";
55     public static final String DEFAULTP = "defaultp";
56
57     /**
58      * Creates the interface_types element
59      *
60      * @param component to work on
61      * @return the added element
62      */
63     public static Map<String, Object> addInterfaceTypeElement(Component component) {
64         Map<String, Object> toscaInterfaceTypes = new HashMap<>();
65         if ((component instanceof Service) || (component instanceof Product)) {
66             return null;
67         }
68
69         final Map<String, InterfaceDefinition> interfaces = ((Resource) component).getInterfaces();
70         if ( MapUtils.isEmpty(interfaces)) {
71             return null;
72         }
73
74         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
75             ToscaInterfaceNodeType toscaInterfaceType = new ToscaInterfaceNodeType();
76             toscaInterfaceType.setDerived_from(DERIVED_FROM_STANDARD_INTERFACE);
77
78             final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
79             Map<String, Object> toscaOperations = new HashMap<>();
80
81             for (String operationId : operations.keySet()) {
82                 toscaOperations.put(operations.get(operationId).getName(),
83                         null); //currently not initializing any of the operations' fields as it is not needed
84             }
85
86
87             toscaInterfaceType.setOperations(toscaOperations);
88             Map<String, Object> interfacesAsMap = getObjectAsMap(toscaInterfaceType);
89             Map<String, Object> operationsMap = (Map<String, Object>) interfacesAsMap.remove(OPERATIONS_KEY);
90             interfacesAsMap.putAll(operationsMap);
91
92             toscaInterfaceTypes.put(interfaceDefinition.getToscaResourceName(), interfacesAsMap);
93         }
94         return toscaInterfaceTypes;
95     }
96
97     /**
98      * Adds the 'interfaces' element to the node type provided
99      *
100      * @param component to work on
101      * @param nodeType  to which the interfaces element will be added
102      */
103     public static void addInterfaceDefinitionElement(Component component, ToscaNodeType nodeType) {
104         Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
105
106         if ((component instanceof Service) || (component instanceof Product)) {
107             return;
108         }
109
110         final Map<String, InterfaceDefinition> interfaces = ((Resource) component).getInterfaces();
111         if ( MapUtils.isEmpty(interfaces)) {
112             return;
113         }
114         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
115             ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition();
116             final String toscaResourceName = interfaceDefinition.getToscaResourceName();
117             toscaInterfaceDefinition.setType(toscaResourceName);
118             final Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
119             Map<String, Object> toscaOperations = new HashMap<>();
120
121             String operationArtifactPath;
122             for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
123                 ToscaLifecycleOperationDefinition toscaOperation = new ToscaLifecycleOperationDefinition();
124                 if (isArtifactPresent(operationEntry)) {
125                     operationArtifactPath = OperationArtifactUtil
126                                                     .createOperationArtifactPath(component.getNormalizedName(),
127                                                             interfaceDefinition.getToscaResourceName(),
128                                                             operationEntry.getValue());
129                     toscaOperation.setImplementation(operationArtifactPath);
130                 }
131                 toscaOperation.setDescription(operationEntry.getValue().getDescription());
132                 fillToscaOperationInputs(operationEntry.getValue(), toscaOperation);
133
134                 toscaOperations.put(operationEntry.getValue().getName(), toscaOperation);
135             }
136
137             toscaInterfaceDefinition.setOperations(toscaOperations);
138             Map<String, Object> interfaceDefAsMap = getObjectAsMap(toscaInterfaceDefinition);
139             Map<String, Object> operationsMap = (Map<String, Object>) interfaceDefAsMap.remove(OPERATIONS_KEY);
140             handleDefaults(operationsMap);
141             interfaceDefAsMap.putAll(operationsMap);
142             toscaInterfaceDefinitions.put(getLastPartOfName(toscaResourceName), interfaceDefAsMap);
143         }
144         nodeType.setInterfaces(toscaInterfaceDefinitions);
145     }
146
147     /***
148      * workaround for : currently "defaultp" is not being converted to "default" by the relevant code in ToscaExportHandler
149      * so, any string Map key named "defaultp" will have its named changed to "default"
150      * @param operationsMap the map to update
151      */
152     private static void handleDefaults(Map<String, Object> operationsMap) {
153         for (String key : operationsMap.keySet()) {
154             Object value = operationsMap.get(key);
155             if (value instanceof Map) {
156                 handleDefaults((Map<String, Object>) value);
157             }
158             if (key.equals(DEFAULTP)) {
159                 Object removed = operationsMap.remove(key);
160                 operationsMap.put(DEFAULT, removed);
161             }
162         }
163
164
165     }
166
167     private static String getLastPartOfName(String toscaResourceName) {
168         return toscaResourceName.substring(toscaResourceName.lastIndexOf(DOT) + 1);
169
170     }
171
172     private static boolean isArtifactPresent(Map.Entry<String, OperationDataDefinition> operationEntry) {
173         final boolean isImplementationPresent = !Objects.isNull(operationEntry.getValue().getImplementation());
174         if (isImplementationPresent) {
175             return !Objects.isNull(operationEntry.getValue().getImplementation().getArtifactName());
176         }
177         return false;
178     }
179
180     private static void fillToscaOperationInputs(OperationDataDefinition operation,
181             ToscaLifecycleOperationDefinition toscaOperation) {
182         if (Objects.isNull(operation.getInputs())) {
183             return;
184         }
185         Map<String, ToscaProperty> toscaInputs = new HashMap<>();
186
187         for (OperationInputDefinition input : operation.getInputs().getListToscaDataDefinition()) {
188             ToscaProperty toscaInput = new ToscaProperty();
189             toscaInput.setDescription(input.getDescription());
190             toscaInput.setType(DEFAULT_INPUT_TYPE);
191
192             toscaInput.setDefaultp(createDefaultValue(getLastPartOfName(input.getInputId())));
193             toscaInputs.put(input.getName(), toscaInput);
194         }
195
196         toscaOperation.setInputs(toscaInputs);
197     }
198
199     private static Map<String, List<String>> createDefaultValue(String propertyName) {
200         Map<String, List<String>> getPropertyMap = new HashMap<>();
201         List<String> values = new ArrayList<>();
202         values.add(SELF);
203         values.add(propertyName);
204         getPropertyMap.put(GET_PROPERTY, values);
205
206         return getPropertyMap;
207     }
208
209
210     private static Map<String, Object> getObjectAsMap(Object obj) {
211         Map<String, Object> objectAsMap =
212                 obj instanceof Map ? (Map<String, Object>) obj : new ObjectMapper().convertValue(obj, Map.class);
213
214         if (objectAsMap.containsKey(DEFAULT)) {
215             Object defaultValue = objectAsMap.get(DEFAULT);
216             objectAsMap.remove(DEFAULT);
217             objectAsMap.put(_DEFAULT, defaultValue);
218         }
219         return objectAsMap;
220     }
221
222 }