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