fix vendor name on normative import
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ImportUtils.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
21 package org.openecomp.sdc.be.components.impl;
22
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import com.google.gson.reflect.TypeToken;
26 import fj.data.Either;
27 import org.apache.commons.lang3.StringEscapeUtils;
28 import org.openecomp.sdc.be.components.impl.utils.ExceptionUtils;
29 import org.openecomp.sdc.be.datatypes.elements.Annotation;
30 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
31 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
32 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
33 import org.openecomp.sdc.be.impl.ComponentsUtils;
34 import org.openecomp.sdc.be.model.*;
35 import org.openecomp.sdc.be.model.heat.HeatParameterType;
36 import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
37 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
38 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
39 import org.openecomp.sdc.be.utils.TypeUtils;
40 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
41 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43 import org.openecomp.sdc.exception.ResponseFormat;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.beans.factory.config.YamlProcessor;
46 import org.yaml.snakeyaml.DumperOptions;
47 import org.yaml.snakeyaml.Yaml;
48 import org.yaml.snakeyaml.constructor.Constructor;
49 import org.yaml.snakeyaml.nodes.Tag;
50 import org.yaml.snakeyaml.representer.Representer;
51 import org.yaml.snakeyaml.resolver.Resolver;
52
53 import java.lang.reflect.Type;
54 import java.util.*;
55 import java.util.Map.Entry;
56 import java.util.function.Consumer;
57 import java.util.function.Function;
58
59 import static org.apache.commons.collections.CollectionUtils.isEmpty;
60 import static org.openecomp.sdc.be.components.impl.ResourceImportManager.PROPERTY_NAME_PATTERN_IGNORE_LENGTH;
61 import static org.openecomp.sdc.be.datatypes.elements.Annotation.setAnnotationsName;
62
63
64 public final class ImportUtils {
65
66
67     private static final CustomResolver customResolver = new CustomResolver();
68     private static final Yaml strictYamlLoader =  new YamlLoader().getStrictYamlLoader();
69
70     @Autowired
71     protected static ComponentsUtils componentsUtils;
72
73     @Autowired
74     private ExceptionUtils exceptionUtils;
75
76     private static final Logger log = Logger.getLogger(ImportUtils.class);
77
78     private ImportUtils() {
79
80     }
81
82     private static class CustomResolver extends Resolver {
83         @Override
84         protected void addImplicitResolvers() {
85             // avoid implicit resolvers for strings that can be interpreted as boolean values
86             addImplicitResolver(Tag.STR, EMPTY, "");
87             addImplicitResolver(Tag.STR, NULL, null);
88             addImplicitResolver(Tag.NULL, NULL, "~nN\0");
89             addImplicitResolver(Tag.NULL, EMPTY, null);
90             addImplicitResolver(Tag.INT, INT, "-+0123456789");
91             addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
92             addImplicitResolver(Tag.YAML, YAML, "!&*");
93         }
94     }
95
96
97     private static void buildMap(Map<String, Object> output, Map<String, Object> map) {
98         for (Entry<String, Object> entry : map.entrySet()) {
99             String key = entry.getKey();
100             Object value = entry.getValue();
101             if (value instanceof Map) {
102                 Map<String, Object> result = new LinkedHashMap<>();
103                 buildMap(result, (Map) value);
104                 output.put(key, result);
105             }
106             else if (value instanceof Collection) {
107                 Map<String, Object> result = new LinkedHashMap<>();
108                 int i = 0;
109                 for(Object item : (Collection<Object>) value) {
110                     buildMap(result, Collections.singletonMap("[" + (i++) + "]", item));
111                 }
112                 output.put(key, new ArrayList<>(result.values()));
113             }
114             else {
115                 output.put(key, value);
116             }
117         }
118     }
119
120     public static Map<String, Object> loadYamlAsStrictMap(String content){
121         Map<String, Object> result = new LinkedHashMap<>();
122         Object map = strictYamlLoader.load(content);
123         buildMap(result, (Map<String, Object>)map);
124         return result;
125     }
126
127     private static class YamlLoader extends YamlProcessor {
128         public Yaml getStrictYamlLoader() {
129             return createYaml();
130         }
131     }
132
133     @SuppressWarnings("unchecked")
134     public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParamsWithoutImplicitTypes(String heatDecodedPayload, String artifactType) {
135         Map<String, Object> heatData = (Map<String, Object>) new Yaml(new Constructor(), new Representer(), new DumperOptions(), customResolver).load(heatDecodedPayload);
136         return getHeatParameters(heatData, artifactType);
137     }
138
139     public static class Constants {
140         public static final String FIRST_NON_CERTIFIED_VERSION = "0.1";
141         public static final String VENDOR_NAME = "ONAP (Tosca)";
142         public static final String VENDOR_RELEASE = "1.0.0.wd03";
143         public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE = LifecycleStateEnum.CERTIFIED;
144         public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT;
145         public static final boolean NORMATIVE_TYPE_HIGHEST_VERSION = true;
146         public static final String ABSTRACT_CATEGORY_NAME = "Generic";
147         public static final String ABSTRACT_SUBCATEGORY = "Abstract";
148         public static final String DEFAULT_ICON = "defaulticon";
149         public static final String INNER_VFC_DESCRIPTION = "Not reusable inner VFC";
150         public static final String USER_DEFINED_RESOURCE_NAMESPACE_PREFIX = "org.openecomp.resource.";
151         public static final String UI_JSON_PAYLOAD_NAME = "payloadName";
152         public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF";
153
154         private Constants() {}
155     }
156
157     public enum ResultStatusEnum {
158         ELEMENT_NOT_FOUND, GENERAL_ERROR, OK, INVALID_PROPERTY_DEFAULT_VALUE, INVALID_PROPERTY_TYPE, INVALID_PROPERTY_VALUE, MISSING_ENTRY_SCHEMA_TYPE, INVALID_PROPERTY_NAME
159     }
160
161     public enum ToscaElementTypeEnum {
162         BOOLEAN, STRING, MAP, LIST, ALL
163     }
164
165     @SuppressWarnings("unchecked")
166     private static void handleElementNameNotFound(String elementName, Object elementValue, ToscaElementTypeEnum elementType, List<Object> returnedList) {
167         if (elementValue instanceof Map) {
168             ImportUtils.findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
169         } else if (elementValue instanceof List) {
170             ImportUtils.findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
171         }
172     }
173
174     @SuppressWarnings("unchecked")
175     private static void addFoundElementAccordingToItsType(String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList, Object elementValue) {
176
177         if (elementValue instanceof Boolean) {
178             if (elementType == ToscaElementTypeEnum.BOOLEAN || elementType == ToscaElementTypeEnum.ALL) {
179                 returnedList.add(elementValue);
180             }
181         }
182
183         else if (elementValue instanceof String) {
184             if (elementType == ToscaElementTypeEnum.STRING || elementType == ToscaElementTypeEnum.ALL) {
185                 returnedList.add(elementValue);
186             }
187         } else if (elementValue instanceof Map) {
188             if (elementType == ToscaElementTypeEnum.MAP || elementType == ToscaElementTypeEnum.ALL) {
189                 returnedList.add(elementValue);
190             }
191             ImportUtils.findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
192
193         } else if (elementValue instanceof List) {
194             if (elementType == ToscaElementTypeEnum.LIST || elementType == ToscaElementTypeEnum.ALL) {
195                 returnedList.add(elementValue);
196             }
197             ImportUtils.findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
198
199         }
200         // For Integer, Double etc...
201         else if (elementType == ToscaElementTypeEnum.ALL && elementValue != null) {
202             returnedList.add(String.valueOf(elementValue));
203         }
204     }
205
206     private static void findAllToscaElementsInList(List<Object> list, String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList) {
207         list.forEach(elementValue -> handleElementNameNotFound(elementName, elementValue, elementType, returnedList));
208     }
209
210     public static Either<Object, ResultStatusEnum> findToscaElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum elementName, ToscaElementTypeEnum elementType) {
211         List<Object> foundElements = new ArrayList<>();
212         ImportUtils.findToscaElements(toscaJson, elementName.getElementName(), elementType, foundElements);
213         if (!isEmpty(foundElements)) {
214             return Either.left(foundElements.get(0));
215         }
216         return Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
217     }
218
219     /**
220      * Recursively searches for all tosca elements with key equals to elementName and value equals to elementType. <br>
221      * Returns Either element with:<br>
222      * List with all value if values found<br>
223      * Or ELEMENT_NOT_FOUND ActionStatus
224      *
225      * @param toscaJson
226      * @return
227      */
228     public static Either<List<Object>, ResultStatusEnum> findToscaElements(Map<String, Object> toscaJson, String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList) {
229         Either<List<Object>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
230         String skipKey = null;
231         if (toscaJson.containsKey(elementName)) {
232             skipKey = handleFoundElement(toscaJson, elementName, elementType, returnedList);
233         }
234
235
236         Iterator<Entry<String, Object>> keyValItr = toscaJson.entrySet().iterator();
237         while (keyValItr.hasNext()) {
238             Entry<String, Object> keyValEntry = keyValItr.next();
239             if (!String.valueOf(keyValEntry.getKey()).equals(skipKey)) {
240                 handleElementNameNotFound(elementName, keyValEntry.getValue(), elementType, returnedList);
241             }
242         }
243
244         if (!isEmpty(returnedList)) {
245             returnedElement = Either.left(returnedList);
246         }
247
248         return returnedElement;
249     }
250
251     private static String handleFoundElement(Map<String, Object> toscaJson, String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList) {
252         Object elementValue = toscaJson.get(elementName);
253         addFoundElementAccordingToItsType(elementName, elementType, returnedList, elementValue);
254         return elementName;
255
256     }
257
258     @SuppressWarnings("unchecked")
259     public static <T> Either<List<T>, ResultStatusEnum> findFirstToscaListElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
260         Either<List<T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
261         Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.LIST);
262         if (findFirstToscaElement.isLeft()) {
263             returnedElement = Either.left((List<T>) findFirstToscaElement.left().value());
264         }
265         return returnedElement;
266
267     }
268
269     @SuppressWarnings("unchecked")
270     public static <T> Either<Map<String, T>, ResultStatusEnum> findFirstToscaMapElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
271         Either<Map<String, T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
272         Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.MAP);
273         if (findFirstToscaElement.isLeft()) {
274             returnedElement = Either.left((Map<String, T>) findFirstToscaElement.left().value());
275         }
276         return returnedElement;
277
278     }
279
280     public static Either<String, ResultStatusEnum> findFirstToscaStringElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
281         Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
282         Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.STRING);
283         if (findFirstToscaElements.isLeft()) {
284             returnedElement = Either.left((String) findFirstToscaElements.left().value());
285         }
286         return returnedElement;
287     }
288
289     /**
290      * searches for first Tosca in Json map (toscaJson) boolean element by name (toscaTagName) returns found element or ELEMENT_NOT_FOUND status
291      *
292      * @param toscaJson
293      * @param toscaTagName
294      * @return
295      */
296     public static Either<String, ResultStatusEnum> findFirstToscaBooleanElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
297         Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
298         Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.BOOLEAN);
299         if (findFirstToscaElements.isLeft()) {
300             returnedElement = Either.left(String.valueOf(findFirstToscaElements.left().value()));
301         }
302         return returnedElement;
303     }
304
305     private static void setPropertyConstraints(Map<String, Object> propertyValue, PropertyDefinition property) {
306         Either<List<Object>, ResultStatusEnum> propertyFieldconstraints = findFirstToscaListElement(propertyValue, TypeUtils.ToscaTagNamesEnum.CONSTRAINTS);
307         if (propertyFieldconstraints.isLeft()) {
308             List<Object> jsonConstraintList = propertyFieldconstraints.left().value();
309
310             List<PropertyConstraint> constraintList = new ArrayList<>();
311             Type constraintType = new TypeToken<PropertyConstraint>() {
312             }.getType();
313             Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create();
314
315             for (Object constraintJson : jsonConstraintList) {
316                 PropertyConstraint propertyConstraint = gson.fromJson(gson.toJson(constraintJson), constraintType);
317                 constraintList.add(propertyConstraint);
318             }
319             property.setConstraints(constraintList);
320         }
321     }
322
323     public static PropertyDefinition createModuleProperty(Map<String, Object> propertyValue) {
324
325         PropertyDefinition propertyDef = new PropertyDefinition();
326         setField(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE, propertyDef::setType);
327         setFieldBoolean(propertyValue, ToscaTagNamesEnum.REQUIRED, req -> propertyDef.setRequired(Boolean.parseBoolean(req)));
328         setField(propertyValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, propertyDef::setDescription);
329
330         setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, propertyDef.getType(), propertyDef::setDefaultValue);
331         setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.VALUE, propertyDef.getType(), propertyDef::setValue);
332
333         setFieldBoolean(propertyValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> propertyDef.setPassword(Boolean.parseBoolean(pass)));
334         setField(propertyValue, TypeUtils.ToscaTagNamesEnum.STATUS, propertyDef::setStatus);
335         setScheme(propertyValue, propertyDef);
336         setPropertyConstraints(propertyValue, propertyDef);
337
338         return propertyDef;
339     }
340
341
342     private static void setJsonStringField(Map<String, Object> propertyValue, ToscaTagNamesEnum elementName, String type, Consumer<String> setter) {
343         Either<Object, ResultStatusEnum> eitherValue = ImportUtils.findToscaElement(propertyValue, elementName, ToscaElementTypeEnum.ALL);
344         if (eitherValue.isLeft()) {
345             String propertyJsonStringValue = getPropertyJsonStringValue(eitherValue.left().value(), type);
346             setter.accept(propertyJsonStringValue);
347         }
348     }
349
350
351
352     public static Annotation createModuleAnnotation(Map<String, Object> annotationMap, AnnotationTypeOperations annotationTypeOperations) {
353         String parsedAnnotationType = findFirstToscaStringElement(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE).left().value();
354         AnnotationTypeDefinition annotationTypeObject = annotationTypeOperations.getLatestType(parsedAnnotationType);
355         if (annotationTypeObject != null) {
356             Annotation annotation = new Annotation();
357             ImportUtils.setField(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE, annotation::setType);
358             ImportUtils.setField(annotationMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotation::setDescription);
359             Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = getProperties(annotationMap);
360             modifyPropertiesKeysToProperForm(properties, annotation);
361             return annotation;
362         }
363         return null;
364     }
365
366     private static Either<Boolean, ResponseFormat> modifyPropertiesKeysToProperForm(Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties, Annotation annotation) {
367         Either<Boolean, ResponseFormat> result = Either.left(true);
368         if (properties.isLeft()) {
369             List<PropertyDataDefinition> propertiesList = new ArrayList<>();
370             Map<String, PropertyDefinition> value = properties.left().value();
371             if (value != null) {
372                 for (Entry<String, PropertyDefinition> entry : value.entrySet()) {
373                     String name = entry.getKey();
374                     if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
375                         log.debug("The property with invalid name {} occurred upon import resource {}. ", name, annotation.getName());
376                         result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME, JsonPresentationFields.PROPERTY)));
377                     }
378                     PropertyDefinition propertyDefinition = entry.getValue();
379                     propertyDefinition.setValue(propertyDefinition.getName());
380                     propertyDefinition.setName(name);
381                     propertiesList.add(propertyDefinition);
382                 }
383             }
384             annotation.setProperties(propertiesList);
385         }
386         else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) {
387             result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(properties
388                     .right()
389                     .value(), JsonPresentationFields.PROPERTY)));
390         }
391         return result;
392     }
393
394     public static InputDefinition createModuleInput(Map<String, Object> inputValue, AnnotationTypeOperations annotationTypeOperations) {
395
396         InputDefinition inputDef = new InputDefinition();
397         ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.TYPE, inputDef::setType);
398         ImportUtils.setFieldBoolean(inputValue, ToscaTagNamesEnum.REQUIRED, req -> inputDef.setRequired(Boolean.parseBoolean(req)));
399         ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, inputDef::setDescription);
400
401         setJsonStringField(inputValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, inputDef.getType(), inputDef::setDefaultValue);
402
403         ImportUtils.setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> inputDef.setPassword(Boolean.parseBoolean(pass)));
404         ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.STATUS, inputDef::setStatus);
405         ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.LABEL, inputDef::setLabel);
406         ImportUtils.setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.HIDDEN, hidden -> inputDef.setHidden(Boolean.parseBoolean(hidden)));
407         ImportUtils.setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IMMUTABLE, immutable -> inputDef.setImmutable(Boolean.parseBoolean(immutable)));
408
409         ImportUtils.setScheme(inputValue, inputDef);
410         ImportUtils.setPropertyConstraints(inputValue, inputDef);
411
412         return parseAnnotationsAndAddItToInput(inputDef, inputValue, annotationTypeOperations);
413
414     }
415
416
417     public static InputDefinition parseAnnotationsAndAddItToInput(InputDefinition inputDef, Map<String, Object> inputValue, AnnotationTypeOperations annotationTypeOperations){
418         Function<String, Annotation> elementGenByName = ImportUtils::createAnnotation;
419         Function<Map<String, Object>, Annotation> func = annotation -> createModuleAnnotation(annotation, annotationTypeOperations);
420         return getElements(inputValue, TypeUtils.ToscaTagNamesEnum.ANNOTATIONS, elementGenByName, func).
421                 left().map( annotations -> modifyInputWithAnnotations(inputDef, annotations)).
422                 left().on(err -> { log.error("Parsing annotations or adding them to the PropertyDataDefinition object failed");
423                                     return inputDef;});
424     }
425
426     private static InputDefinition modifyInputWithAnnotations(InputDefinition inputDef, Map<String, Annotation> annotationsMap) {
427         setAnnotationsName(annotationsMap);
428         inputDef.setAnnotationsToInput(annotationsMap.values());
429         return inputDef;
430     }
431
432
433     public static PropertyDefinition createModuleAttribute(Map<String, Object> attributeMap) {
434
435         PropertyDefinition attributeDef = new PropertyDefinition();
436         setField(attributeMap, TypeUtils.ToscaTagNamesEnum.TYPE, attributeDef::setType);
437         setField(attributeMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, attributeDef::setDescription);
438         setField(attributeMap, TypeUtils.ToscaTagNamesEnum.STATUS, attributeDef::setStatus);
439
440         setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, attributeDef.getType(), attributeDef::setDefaultValue);
441         setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.VALUE, attributeDef.getType(), attributeDef::setValue);
442
443         setScheme(attributeMap, attributeDef);
444         return attributeDef;
445     }
446
447     private static void setScheme(Map<String, Object> propertyValue, PropertyDefinition propertyDefinition) {
448         Either<SchemaDefinition, ResultStatusEnum> eitherSchema = getSchema(propertyValue);
449         if (eitherSchema.isLeft()) {
450             SchemaDefinition schemaDef = new SchemaDefinition();
451             schemaDef.setProperty(eitherSchema.left().value().getProperty());
452             propertyDefinition.setSchema(schemaDef);
453         }
454
455     }
456
457     private static Either<SchemaDefinition, ResultStatusEnum> getSchema(Map<String, Object> propertyValue) {
458         Either<SchemaDefinition, ResultStatusEnum> result = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
459         Either<Object, ResultStatusEnum> propertyFieldEntryScheme = findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA, ToscaElementTypeEnum.ALL);
460         if (propertyFieldEntryScheme.isLeft()) {
461             if (propertyFieldEntryScheme.left().value() instanceof String) {
462                 String schemaType = (String) propertyFieldEntryScheme.left().value();
463                 SchemaDefinition schema = new SchemaDefinition();
464                 PropertyDefinition schemeProperty = new PropertyDefinition();
465                 schemeProperty.setType(schemaType);
466                 schema.setProperty(schemeProperty);
467                 result = Either.left(schema);
468
469             } else if (propertyFieldEntryScheme.left().value() instanceof Map) {
470                 PropertyDefinition schemeProperty = createModuleProperty((Map<String, Object>) propertyFieldEntryScheme.left().value());
471                 SchemaDefinition schema = new SchemaDefinition();
472                 schema.setProperty(schemeProperty);
473                 result = Either.left(schema);
474             }
475         }
476         return result;
477     }
478
479     public static void setField(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName, Consumer<String> setter) {
480         Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaStringElement(toscaJson, tagName);
481         if (fieldStringValue.isLeft()) {
482             setter.accept(fieldStringValue.left().value());
483         }
484
485     }
486
487     public static void setFieldBoolean(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName, Consumer<String> setter) {
488         Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaBooleanElement(toscaJson, tagName);
489         if (fieldStringValue.isLeft()) {
490             setter.accept(fieldStringValue.left().value());
491         }
492
493     }
494
495
496     public static Either<Map<String, PropertyDefinition>, ResultStatusEnum> getProperties(Map<String, Object> toscaJson) {
497         Function<String, PropertyDefinition> elementGenByName = ImportUtils::createProperties;
498         Function<Map<String, Object>, PropertyDefinition> func = ImportUtils::createModuleProperty;
499
500         return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.PROPERTIES, elementGenByName, func);
501
502     }
503
504     public static Either<Map<String, InputDefinition>, ResultStatusEnum> getInputs(Map<String, Object> toscaJson, AnnotationTypeOperations annotationTypeOperations) {
505         Function<String, InputDefinition> elementGenByName = ImportUtils::createInputs;
506         Function<Map<String, Object>, InputDefinition> func = object -> createModuleInput(object, annotationTypeOperations);
507
508         return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.INPUTS, elementGenByName, func);
509
510     }
511
512     public static Either<Map<String, PropertyDefinition>, ResultStatusEnum> getAttributes(Map<String, Object> toscaJson) {
513         Function<String, PropertyDefinition> elementGenByName = ImportUtils::createAttribute;
514         Function<Map<String, Object>, PropertyDefinition> func = ImportUtils::createModuleAttribute;
515
516         return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.ATTRIBUTES, elementGenByName, func);
517     }
518
519     public static <T> Either<Map<String, T>, ResultStatusEnum>  getElements(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum elementTagName, Function<String, T> elementGenByName,
520                                                                            Function<Map<String, Object>, T> func) {
521         Either<Map<String, T>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
522         Either<Map<String, Object>, ResultStatusEnum> toscaAttributes = findFirstToscaMapElement(toscaJson, elementTagName);
523         if (toscaAttributes.isLeft()) {
524             Map<String, Object> jsonAttributes = toscaAttributes.left().value();
525             Map<String, T> moduleAttributes = new HashMap<>();
526             Iterator<Entry<String, Object>> propertiesNameValue = jsonAttributes.entrySet().iterator();
527             while (propertiesNameValue.hasNext()) {
528                 Entry<String, Object> attributeNameValue = propertiesNameValue.next();
529                 if (attributeNameValue.getValue() instanceof Map) {
530                     @SuppressWarnings("unchecked")
531                     T attribute = func.apply((Map<String, Object>) attributeNameValue.getValue());
532                     if (attribute != null){
533                         moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), attribute);
534                     }
535                 }
536                 else {
537                     T element = elementGenByName.apply(String.valueOf(attributeNameValue.getValue()));
538                     moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), element);
539                 }
540             }
541             if (moduleAttributes.size() > 0) {
542                 eitherResult = Either.left(moduleAttributes);
543             }
544
545         }
546         return eitherResult;
547
548     }
549
550     private static PropertyDefinition createAttribute(String name) {
551         PropertyDefinition attribute = new PropertyDefinition();
552
553         attribute.setName(name);
554         return attribute;
555     }
556
557     private static PropertyDefinition createProperties(String name) {
558         PropertyDefinition property = new PropertyDefinition();
559         property.setDefaultValue(name);
560         property.setName(name);
561         return property;
562     }
563
564
565
566     private static InputDefinition createInputs(String name) {
567         InputDefinition input = new InputDefinition();
568
569         input.setName(name);
570         return input;
571     }
572
573     private static Annotation createAnnotation(String name) {
574         Annotation annotation = new Annotation();
575         annotation.setName(name);
576         return annotation;
577     }
578
579
580
581     public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParameters(Map<String, Object> heatData, String artifactType) {
582
583         Either<List<HeatParameterDefinition>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
584         Either<Map<String, Object>, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(heatData, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
585         if (toscaProperties.isLeft()) {
586             Map<String, Object> jsonProperties = toscaProperties.left().value();
587             List<HeatParameterDefinition> moduleProperties = new ArrayList<>();
588             Iterator<Entry<String, Object>> propertiesNameValue = jsonProperties.entrySet().iterator();
589             while (propertiesNameValue.hasNext()) {
590                 Entry<String, Object> propertyNameValue = propertiesNameValue.next();
591                 if (propertyNameValue.getValue() instanceof Map || propertyNameValue.getValue() instanceof List) {
592                     if (!artifactType.equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
593                         @SuppressWarnings("unchecked")
594                         Either<HeatParameterDefinition, ResultStatusEnum> propertyStatus = createModuleHeatParameter((Map<String, Object>) propertyNameValue.getValue());
595                         if (propertyStatus.isRight()) {
596                             return Either.right(propertyStatus.right().value());
597                         }
598                         HeatParameterDefinition property = propertyStatus.left().value();
599                         property.setName(String.valueOf(propertyNameValue.getKey()));
600                         moduleProperties.add(property);
601                     } else {
602                         addHeatParamDefinition(moduleProperties, propertyNameValue, true);
603                     }
604                 } else {
605                     addHeatParamDefinition(moduleProperties, propertyNameValue, false);
606                 }
607
608             }
609
610             if (!isEmpty(moduleProperties)) {
611                 eitherResult = Either.left(moduleProperties);
612             }
613
614         }
615         return eitherResult;
616
617     }
618
619     private static void addHeatParamDefinition(List<HeatParameterDefinition> moduleProperties, Entry<String, Object> propertyNameValue, boolean isJson) {
620         HeatParameterDefinition property = new HeatParameterDefinition();
621         Object value = propertyNameValue.getValue();
622         if (value != null) {
623             property.setDefaultValue(isJson ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value)));
624         }
625         property.setName(String.valueOf(propertyNameValue.getKey()));
626         moduleProperties.add(property);
627     }
628
629     private static Either<HeatParameterDefinition, ResultStatusEnum> createModuleHeatParameter(Map<String, Object> propertyValue) {
630         HeatParameterDefinition propertyDef = new HeatParameterDefinition();
631         String type;
632         Either<String, ResultStatusEnum> propertyFieldType = findFirstToscaStringElement(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE);
633         if (propertyFieldType.isLeft()) {
634             type = propertyFieldType.left().value();
635             propertyDef.setType(type);
636         } else {
637             return Either.right(ResultStatusEnum.INVALID_PROPERTY_TYPE);
638         }
639         Either<String, ResultStatusEnum> propertyFieldDescription = findFirstToscaStringElement(propertyValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION);
640         if (propertyFieldDescription.isLeft()) {
641             propertyDef.setDescription(propertyFieldDescription.left().value());
642         }
643
644         Either<Object, ResultStatusEnum> propertyFieldDefaultVal = findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, ToscaElementTypeEnum.ALL);
645         if (propertyFieldDefaultVal.isLeft()) {
646             if (propertyFieldDefaultVal.left().value() == null) {
647                 return Either.right(ResultStatusEnum.INVALID_PROPERTY_VALUE);
648             }
649             Object value = propertyFieldDefaultVal.left().value();
650             String defaultValue = type.equals(HeatParameterType.JSON.getType()) ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value));
651             propertyDef.setDefaultValue(defaultValue);
652             propertyDef.setCurrentValue(defaultValue);
653         }
654
655         return Either.left(propertyDef);
656     }
657     public static boolean containsGetInput(Object propValue) {
658         String value = getPropertyJsonStringValue(propValue, ToscaPropertyType.MAP.getType());
659         return value != null && value.contains(TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName());
660     }
661
662     public static String getPropertyJsonStringValue(Object value, String type) {
663         Gson gson = new Gson();
664         if (type == null) {
665             return null;
666         }
667         ToscaPropertyType validType = ToscaPropertyType.isValidType(type);
668         if (validType == null ||  validType.equals(ToscaPropertyType.JSON) ||validType.equals(ToscaPropertyType.MAP) || validType.equals(ToscaPropertyType.LIST)) {
669             return gson.toJson(value);
670         }
671         return value.toString();
672     }
673
674     /**
675      * removes from Json map (toscaJson) first element found by name (elementName) note that this method could update the received argument toscaJson
676      *
677      * @param toscaJson
678      * @param elementName
679      */
680     public static void removeElementFromJsonMap(Map<String, Object> toscaJson, String elementName) {
681         for (Entry<String, Object> entry : toscaJson.entrySet()) {
682             String key = entry.getKey();
683             Object value = entry.getValue();
684             if (key.equals(elementName)) {
685                 toscaJson.remove(elementName);
686                 return;
687             } else if (value instanceof Map) {
688                 removeElementFromJsonMap((Map<String, Object>) value, elementName);
689             }
690         }
691     }
692 }