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