2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.components.impl;
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import com.google.gson.JsonParseException;
26 import com.google.gson.reflect.TypeToken;
27 import fj.data.Either;
28 import org.apache.commons.collections.CollectionUtils;
29 import org.apache.commons.lang3.StringEscapeUtils;
30 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
31 import org.openecomp.sdc.be.config.BeEcompErrorManager;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.datatypes.elements.Annotation;
34 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
36 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
37 import org.openecomp.sdc.be.impl.ComponentsUtils;
38 import org.openecomp.sdc.be.model.AnnotationTypeDefinition;
39 import org.openecomp.sdc.be.model.HeatParameterDefinition;
40 import org.openecomp.sdc.be.model.InputDefinition;
41 import org.openecomp.sdc.be.model.LifecycleStateEnum;
42 import org.openecomp.sdc.be.model.PropertyConstraint;
43 import org.openecomp.sdc.be.model.PropertyDefinition;
44 import org.openecomp.sdc.be.model.heat.HeatParameterType;
45 import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
46 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
47 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
48 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType;
49 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
50 import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException;
51 import org.openecomp.sdc.be.utils.TypeUtils;
52 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
53 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
54 import org.openecomp.sdc.common.log.wrappers.Logger;
55 import org.openecomp.sdc.exception.ResponseFormat;
56 import org.springframework.beans.factory.annotation.Autowired;
57 import org.springframework.beans.factory.config.YamlProcessor;
58 import org.springframework.stereotype.Component;
59 import org.yaml.snakeyaml.DumperOptions;
60 import org.yaml.snakeyaml.Yaml;
61 import org.yaml.snakeyaml.constructor.Constructor;
62 import org.yaml.snakeyaml.nodes.Tag;
63 import org.yaml.snakeyaml.representer.Representer;
64 import org.yaml.snakeyaml.resolver.Resolver;
66 import java.lang.reflect.Type;
67 import java.util.ArrayList;
68 import java.util.Collection;
69 import java.util.Collections;
70 import java.util.HashMap;
71 import java.util.Iterator;
72 import java.util.LinkedHashMap;
73 import java.util.List;
75 import java.util.Map.Entry;
76 import java.util.function.Consumer;
77 import java.util.function.Function;
79 import static org.apache.commons.collections.CollectionUtils.isEmpty;
80 import static org.openecomp.sdc.be.components.impl.ResourceImportManager.PROPERTY_NAME_PATTERN_IGNORE_LENGTH;
81 import static org.openecomp.sdc.be.datatypes.elements.Annotation.setAnnotationsName;
84 public final class ImportUtils {
86 private static final CustomResolver customResolver = new CustomResolver();
87 private static final Yaml strictYamlLoader = new YamlLoader().getStrictYamlLoader();
89 protected static ComponentsUtils componentsUtils;
91 private static final Logger log = Logger.getLogger(ImportUtils.class);
93 private ImportUtils() {
97 public static void setComponentsUtils(ComponentsUtils componentsUtils) {
98 ImportUtils.componentsUtils = componentsUtils;
101 private static class CustomResolver extends Resolver {
103 protected void addImplicitResolvers() {
104 // avoid implicit resolvers for strings that can be interpreted as boolean values
105 addImplicitResolver(Tag.STR, EMPTY, "");
106 addImplicitResolver(Tag.STR, NULL, null);
107 addImplicitResolver(Tag.NULL, NULL, "~nN\0");
108 addImplicitResolver(Tag.NULL, EMPTY, null);
109 addImplicitResolver(Tag.INT, INT, "-+0123456789");
110 addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
111 addImplicitResolver(Tag.YAML, YAML, "!&*");
116 private static void buildMap(Map<String, Object> output, Map<String, Object> map) {
117 for (Entry<String, Object> entry : map.entrySet()) {
118 String key = entry.getKey();
119 Object value = entry.getValue();
120 if (value instanceof Map) {
121 Map<String, Object> result = new LinkedHashMap<>();
122 buildMap(result, (Map) value);
123 output.put(key, result);
125 else if (value instanceof Collection) {
126 Map<String, Object> result = new LinkedHashMap<>();
128 for(Object item : (Collection<Object>) value) {
129 buildMap(result, Collections.singletonMap("[" + (i++) + "]", item));
131 output.put(key, new ArrayList<>(result.values()));
134 output.put(key, value);
139 public static Map<String, Object> loadYamlAsStrictMap(String content){
140 Map<String, Object> result = new LinkedHashMap<>();
141 Object map = strictYamlLoader.load(content);
142 buildMap(result, (Map<String, Object>)map);
146 private static class YamlLoader extends YamlProcessor {
147 public Yaml getStrictYamlLoader() {
152 @SuppressWarnings("unchecked")
153 public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParamsWithoutImplicitTypes(String heatDecodedPayload, String artifactType) {
154 Map<String, Object> heatData = (Map<String, Object>) new Yaml(new Constructor(), new Representer(), new DumperOptions(), customResolver).load(heatDecodedPayload);
155 return getHeatParameters(heatData, artifactType);
158 public static class Constants {
159 public static final String FIRST_NON_CERTIFIED_VERSION = "0.1";
160 public static final String VENDOR_NAME = "ONAP (Tosca)";
161 public static final String VENDOR_RELEASE = "1.0.0.wd03";
162 public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE = LifecycleStateEnum.CERTIFIED;
163 public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT;
164 public static final boolean NORMATIVE_TYPE_HIGHEST_VERSION = true;
165 public static final String ABSTRACT_CATEGORY_NAME = "Generic";
166 public static final String ABSTRACT_SUBCATEGORY = "Abstract";
167 public static final String DEFAULT_ICON = "defaulticon";
168 public static final String INNER_VFC_DESCRIPTION = "Not reusable inner VFC";
169 public static final String USER_DEFINED_RESOURCE_NAMESPACE_PREFIX = "org.openecomp.resource.";
170 public static final String UI_JSON_PAYLOAD_NAME = "payloadName";
171 public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF";
172 public static final String ESCAPED_DOUBLE_QUOTE = "\"";
173 public static final String QUOTE = "'";
175 private Constants() {}
178 public enum ResultStatusEnum {
179 ELEMENT_NOT_FOUND, GENERAL_ERROR, OK, INVALID_PROPERTY_DEFAULT_VALUE, INVALID_PROPERTY_TYPE, INVALID_PROPERTY_VALUE, MISSING_ENTRY_SCHEMA_TYPE, INVALID_PROPERTY_NAME
182 public enum ToscaElementTypeEnum {
183 BOOLEAN, STRING, MAP, LIST, ALL
186 @SuppressWarnings("unchecked")
187 private static void handleElementNameNotFound(String elementName, Object elementValue, ToscaElementTypeEnum elementType, List<Object> returnedList) {
188 if (elementValue instanceof Map) {
189 ImportUtils.findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
190 } else if (elementValue instanceof List) {
191 ImportUtils.findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
195 @SuppressWarnings("unchecked")
196 private static void addFoundElementAccordingToItsType(String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList, Object elementValue) {
198 if (elementValue instanceof Boolean) {
199 if (elementType == ToscaElementTypeEnum.BOOLEAN || elementType == ToscaElementTypeEnum.ALL) {
200 returnedList.add(elementValue);
204 else if (elementValue instanceof String) {
205 if (elementType == ToscaElementTypeEnum.STRING || elementType == ToscaElementTypeEnum.ALL) {
206 returnedList.add(elementValue);
208 } else if (elementValue instanceof Map) {
209 if (elementType == ToscaElementTypeEnum.MAP || elementType == ToscaElementTypeEnum.ALL) {
210 returnedList.add(elementValue);
212 ImportUtils.findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
214 } else if (elementValue instanceof List) {
215 if (elementType == ToscaElementTypeEnum.LIST || elementType == ToscaElementTypeEnum.ALL) {
216 returnedList.add(elementValue);
218 ImportUtils.findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
221 // For Integer, Double etc...
222 else if (elementType == ToscaElementTypeEnum.ALL && elementValue != null) {
223 returnedList.add(String.valueOf(elementValue));
227 private static void findAllToscaElementsInList(List<Object> list, String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList) {
228 list.forEach(elementValue -> handleElementNameNotFound(elementName, elementValue, elementType, returnedList));
231 public static Either<Object, ResultStatusEnum> findToscaElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum elementName, ToscaElementTypeEnum elementType) {
232 List<Object> foundElements = new ArrayList<>();
233 ImportUtils.findToscaElements(toscaJson, elementName.getElementName(), elementType, foundElements);
234 if (!isEmpty(foundElements)) {
235 return Either.left(foundElements.get(0));
237 return Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
241 * Recursively searches for all tosca elements with key equals to elementName and value equals to elementType. <br>
242 * Returns Either element with:<br>
243 * List with all value if values found<br>
244 * Or ELEMENT_NOT_FOUND ActionStatus
249 public static Either<List<Object>, ResultStatusEnum> findToscaElements(Map<String, Object> toscaJson, String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList) {
250 Either<List<Object>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
251 String skipKey = null;
252 if (toscaJson.containsKey(elementName)) {
253 skipKey = handleFoundElement(toscaJson, elementName, elementType, returnedList);
257 Iterator<Entry<String, Object>> keyValItr = toscaJson.entrySet().iterator();
258 while (keyValItr.hasNext()) {
259 Entry<String, Object> keyValEntry = keyValItr.next();
260 if (!String.valueOf(keyValEntry.getKey()).equals(skipKey)) {
261 handleElementNameNotFound(elementName, keyValEntry.getValue(), elementType, returnedList);
265 if (!isEmpty(returnedList)) {
266 returnedElement = Either.left(returnedList);
269 return returnedElement;
272 private static String handleFoundElement(Map<String, Object> toscaJson, String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList) {
273 Object elementValue = toscaJson.get(elementName);
274 addFoundElementAccordingToItsType(elementName, elementType, returnedList, elementValue);
279 @SuppressWarnings("unchecked")
280 public static <T> Either<List<T>, ResultStatusEnum> findFirstToscaListElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
281 Either<List<T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
282 Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.LIST);
283 if (findFirstToscaElement.isLeft()) {
284 returnedElement = Either.left((List<T>) findFirstToscaElement.left().value());
286 return returnedElement;
290 @SuppressWarnings("unchecked")
291 public static <T> Either<Map<String, T>, ResultStatusEnum> findFirstToscaMapElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
292 Either<Map<String, T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
293 Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.MAP);
294 if (findFirstToscaElement.isLeft()) {
295 returnedElement = Either.left((Map<String, T>) findFirstToscaElement.left().value());
297 return returnedElement;
301 public static Either<String, ResultStatusEnum> findFirstToscaStringElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
302 Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
303 Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.STRING);
304 if (findFirstToscaElements.isLeft()) {
305 returnedElement = Either.left((String) findFirstToscaElements.left().value());
307 return returnedElement;
311 * searches for first Tosca in Json map (toscaJson) boolean element by name (toscaTagName) returns found element or ELEMENT_NOT_FOUND status
314 * @param toscaTagName
317 public static Either<String, ResultStatusEnum> findFirstToscaBooleanElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum toscaTagName) {
318 Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
319 Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.BOOLEAN);
320 if (findFirstToscaElements.isLeft()) {
321 returnedElement = Either.left(String.valueOf(findFirstToscaElements.left().value()));
323 return returnedElement;
326 private static void setPropertyConstraints(Map<String, Object> propertyValue, PropertyDefinition property) {
327 List<PropertyConstraint> constraints = getPropertyConstraints(propertyValue, property.getType());
328 if (CollectionUtils.isNotEmpty(constraints)) {
329 property.setConstraints(constraints);
333 private static List<PropertyConstraint> getPropertyConstraints(Map<String, Object> propertyValue, String propertyType) {
334 List<Object> propertyFieldConstraints = findCurrentLevelConstraintsElement(propertyValue);
335 if (CollectionUtils.isNotEmpty(propertyFieldConstraints)) {
336 List<PropertyConstraint> constraintList = new ArrayList<>();
337 Type constraintType = new TypeToken<PropertyConstraint>() {
339 Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create();
341 for (Object constraintJson : propertyFieldConstraints) {
342 PropertyConstraint propertyConstraint = validateAndGetPropertyConstraint(propertyType, constraintType, gson, constraintJson);
343 constraintList.add(propertyConstraint);
345 return constraintList;
350 private static List<Object> findCurrentLevelConstraintsElement(Map<String, Object> toscaJson) {
351 List<Object> constraints = null;
352 if (toscaJson.containsKey(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName())) {
354 constraints = (List<Object>) toscaJson.get(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName());
355 } catch (ClassCastException e){
356 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS_FORMAT, toscaJson.get(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName()).toString());
363 private static PropertyConstraint validateAndGetPropertyConstraint(String propertyType, Type constraintType, Gson gson, Object constraintJson) {
364 PropertyConstraint propertyConstraint;
366 propertyConstraint = gson.fromJson(gson.toJson(constraintJson), constraintType);
367 } catch (ClassCastException|JsonParseException e){
368 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS_FORMAT, constraintJson.toString());
370 if(propertyConstraint!= null && propertyConstraint instanceof ValidValuesConstraint){
372 ((ValidValuesConstraint)propertyConstraint).validateType(propertyType);
373 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
374 BeEcompErrorManager.getInstance().logInternalFlowError("GetInitializedPropertyConstraint",
375 e.getMessage(), BeEcompErrorManager.ErrorSeverity.ERROR);
376 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS, ConstraintType.VALID_VALUES.name(),
377 ((ValidValuesConstraint) propertyConstraint).getValidValues().toString(), propertyType);
380 return propertyConstraint;
383 public static PropertyDefinition createModuleProperty(Map<String, Object> propertyValue) {
385 PropertyDefinition propertyDef = new PropertyDefinition();
386 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE, propertyDef::setType);
387 setFieldBoolean(propertyValue, ToscaTagNamesEnum.REQUIRED, req -> propertyDef.setRequired(Boolean.parseBoolean(req)));
388 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, propertyDef::setDescription);
390 setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, propertyDef.getType(), propertyDef::setDefaultValue);
391 setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.VALUE, propertyDef.getType(), propertyDef::setValue);
393 setFieldBoolean(propertyValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> propertyDef.setPassword(Boolean.parseBoolean(pass)));
394 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.STATUS, propertyDef::setStatus);
395 setScheme(propertyValue, propertyDef);
396 setPropertyConstraints(propertyValue, propertyDef);
402 private static void setJsonStringField(Map<String, Object> propertyValue, ToscaTagNamesEnum elementName, String type, Consumer<String> setter) {
403 Either<Object, ResultStatusEnum> eitherValue = ImportUtils.findToscaElement(propertyValue, elementName, ToscaElementTypeEnum.ALL);
404 if (eitherValue.isLeft()) {
405 String propertyJsonStringValue = getPropertyJsonStringValue(eitherValue.left().value(), type);
406 setter.accept(propertyJsonStringValue);
412 public static Annotation createModuleAnnotation(Map<String, Object> annotationMap, AnnotationTypeOperations annotationTypeOperations) {
413 String parsedAnnotationType = findFirstToscaStringElement(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE).left().value();
414 AnnotationTypeDefinition annotationTypeObject = annotationTypeOperations.getLatestType(parsedAnnotationType);
415 if (annotationTypeObject != null) {
416 Annotation annotation = new Annotation();
417 ImportUtils.setField(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE, annotation::setType);
418 ImportUtils.setField(annotationMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotation::setDescription);
419 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = getProperties(annotationMap);
420 modifyPropertiesKeysToProperForm(properties, annotation);
426 private static Either<Boolean, ResponseFormat> modifyPropertiesKeysToProperForm(Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties, Annotation annotation) {
427 Either<Boolean, ResponseFormat> result = Either.left(true);
428 if (properties.isLeft()) {
429 List<PropertyDataDefinition> propertiesList = new ArrayList<>();
430 Map<String, PropertyDefinition> value = properties.left().value();
432 for (Entry<String, PropertyDefinition> entry : value.entrySet()) {
433 String name = entry.getKey();
434 if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
435 log.debug("The property with invalid name {} occurred upon import resource {}. ", name, annotation.getName());
436 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME, JsonPresentationFields.PROPERTY)));
438 PropertyDefinition propertyDefinition = entry.getValue();
439 propertyDefinition.setValue(propertyDefinition.getName());
440 propertyDefinition.setName(name);
441 propertiesList.add(propertyDefinition);
444 annotation.setProperties(propertiesList);
446 else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) {
447 result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(properties
449 .value(), JsonPresentationFields.PROPERTY)));
454 public static InputDefinition createModuleInput(Map<String, Object> inputValue, AnnotationTypeOperations annotationTypeOperations) {
456 InputDefinition inputDef = new InputDefinition();
457 ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.TYPE, inputDef::setType);
458 ImportUtils.setFieldBoolean(inputValue, ToscaTagNamesEnum.REQUIRED, req -> inputDef.setRequired(Boolean.parseBoolean(req)));
459 ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, inputDef::setDescription);
461 setJsonStringField(inputValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, inputDef.getType(), inputDef::setDefaultValue);
463 ImportUtils.setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> inputDef.setPassword(Boolean.parseBoolean(pass)));
464 ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.STATUS, inputDef::setStatus);
465 ImportUtils.setField(inputValue, TypeUtils.ToscaTagNamesEnum.LABEL, inputDef::setLabel);
466 ImportUtils.setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.HIDDEN, hidden -> inputDef.setHidden(Boolean.parseBoolean(hidden)));
467 ImportUtils.setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IMMUTABLE, immutable -> inputDef.setImmutable(Boolean.parseBoolean(immutable)));
469 ImportUtils.setScheme(inputValue, inputDef);
470 ImportUtils.setPropertyConstraints(inputValue, inputDef);
472 return parseAnnotationsAndAddItToInput(inputDef, inputValue, annotationTypeOperations);
477 public static InputDefinition parseAnnotationsAndAddItToInput(InputDefinition inputDef, Map<String, Object> inputValue, AnnotationTypeOperations annotationTypeOperations){
478 Function<String, Annotation> elementGenByName = ImportUtils::createAnnotation;
479 Function<Map<String, Object>, Annotation> func = annotation -> createModuleAnnotation(annotation, annotationTypeOperations);
480 return getElements(inputValue, TypeUtils.ToscaTagNamesEnum.ANNOTATIONS, elementGenByName, func).
481 left().map( annotations -> modifyInputWithAnnotations(inputDef, annotations)).
482 left().on(err -> { log.error("Parsing annotations or adding them to the PropertyDataDefinition object failed");
486 private static InputDefinition modifyInputWithAnnotations(InputDefinition inputDef, Map<String, Annotation> annotationsMap) {
487 setAnnotationsName(annotationsMap);
488 inputDef.setAnnotationsToInput(annotationsMap.values());
493 public static PropertyDefinition createModuleAttribute(Map<String, Object> attributeMap) {
495 PropertyDefinition attributeDef = new PropertyDefinition();
496 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.TYPE, attributeDef::setType);
497 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, attributeDef::setDescription);
498 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.STATUS, attributeDef::setStatus);
500 setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, attributeDef.getType(), attributeDef::setDefaultValue);
501 setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.VALUE, attributeDef.getType(), attributeDef::setValue);
503 setScheme(attributeMap, attributeDef);
507 private static void setScheme(Map<String, Object> propertyValue, PropertyDefinition propertyDefinition) {
508 Either<Object, ResultStatusEnum> schemaElementRes = findSchemaElement(propertyValue);
509 if (schemaElementRes.isLeft()) {
510 SchemaDefinition schemaDef = getSchema(schemaElementRes.left().value());
511 propertyDefinition.setSchema(schemaDef);
515 private static Either<Object,ResultStatusEnum> findSchemaElement(Map<String, Object> propertyValue) {
516 return findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA, ToscaElementTypeEnum.ALL);
519 private static SchemaDefinition getSchema(Object propertyFieldEntryScheme) {
520 SchemaDefinition schema = new SchemaDefinition();
521 if (propertyFieldEntryScheme instanceof String) {
522 String schemaType = (String) propertyFieldEntryScheme;
523 PropertyDefinition schemeProperty = new PropertyDefinition();
524 schemeProperty.setType(schemaType);
525 schema.setProperty(schemeProperty);
526 } else if (propertyFieldEntryScheme instanceof Map) {
527 PropertyDefinition schemeProperty = createModuleProperty((Map<String, Object>) propertyFieldEntryScheme);
528 schema.setProperty(schemeProperty);
533 public static void setField(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName, Consumer<String> setter) {
534 Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaStringElement(toscaJson, tagName);
535 if (fieldStringValue.isLeft()) {
536 setter.accept(fieldStringValue.left().value());
541 public static void setFieldBoolean(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName, Consumer<String> setter) {
542 Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaBooleanElement(toscaJson, tagName);
543 if (fieldStringValue.isLeft()) {
544 setter.accept(fieldStringValue.left().value());
550 public static Either<Map<String, PropertyDefinition>, ResultStatusEnum> getProperties(Map<String, Object> toscaJson) {
551 Function<String, PropertyDefinition> elementGenByName = ImportUtils::createProperties;
552 Function<Map<String, Object>, PropertyDefinition> func = ImportUtils::createModuleProperty;
554 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.PROPERTIES, elementGenByName, func);
558 public static Either<Map<String, InputDefinition>, ResultStatusEnum> getInputs(Map<String, Object> toscaJson, AnnotationTypeOperations annotationTypeOperations) {
559 Function<String, InputDefinition> elementGenByName = ImportUtils::createInputs;
560 Function<Map<String, Object>, InputDefinition> func = object -> createModuleInput(object, annotationTypeOperations);
562 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.INPUTS, elementGenByName, func);
566 public static Either<Map<String, PropertyDefinition>, ResultStatusEnum> getAttributes(Map<String, Object> toscaJson) {
567 Function<String, PropertyDefinition> elementGenByName = ImportUtils::createAttribute;
568 Function<Map<String, Object>, PropertyDefinition> func = ImportUtils::createModuleAttribute;
570 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.ATTRIBUTES, elementGenByName, func);
573 public static <T> Either<Map<String, T>, ResultStatusEnum> getElements(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum elementTagName, Function<String, T> elementGenByName,
574 Function<Map<String, Object>, T> func) {
575 Either<Map<String, T>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
576 Either<Map<String, Object>, ResultStatusEnum> toscaAttributes = findFirstToscaMapElement(toscaJson, elementTagName);
577 if (toscaAttributes.isLeft()) {
578 Map<String, Object> jsonAttributes = toscaAttributes.left().value();
579 Map<String, T> moduleAttributes = new HashMap<>();
580 Iterator<Entry<String, Object>> propertiesNameValue = jsonAttributes.entrySet().iterator();
581 while (propertiesNameValue.hasNext()) {
582 Entry<String, Object> attributeNameValue = propertiesNameValue.next();
583 if (attributeNameValue.getValue() instanceof Map) {
584 @SuppressWarnings("unchecked")
585 T attribute = func.apply((Map<String, Object>) attributeNameValue.getValue());
586 if (attribute != null){
587 moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), attribute);
591 T element = elementGenByName.apply(String.valueOf(attributeNameValue.getValue()));
592 moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), element);
595 if (moduleAttributes.size() > 0) {
596 eitherResult = Either.left(moduleAttributes);
604 private static PropertyDefinition createAttribute(String name) {
605 PropertyDefinition attribute = new PropertyDefinition();
607 attribute.setName(name);
611 private static PropertyDefinition createProperties(String name) {
612 PropertyDefinition property = new PropertyDefinition();
613 property.setDefaultValue(name);
614 property.setName(name);
620 private static InputDefinition createInputs(String name) {
621 InputDefinition input = new InputDefinition();
627 private static Annotation createAnnotation(String name) {
628 Annotation annotation = new Annotation();
629 annotation.setName(name);
635 public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParameters(Map<String, Object> heatData, String artifactType) {
637 Either<List<HeatParameterDefinition>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
638 Either<Map<String, Object>, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(heatData, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
639 if (toscaProperties.isLeft()) {
640 Map<String, Object> jsonProperties = toscaProperties.left().value();
641 List<HeatParameterDefinition> moduleProperties = new ArrayList<>();
642 Iterator<Entry<String, Object>> propertiesNameValue = jsonProperties.entrySet().iterator();
643 while (propertiesNameValue.hasNext()) {
644 Entry<String, Object> propertyNameValue = propertiesNameValue.next();
645 if (propertyNameValue.getValue() instanceof Map || propertyNameValue.getValue() instanceof List) {
646 if (!artifactType.equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
647 @SuppressWarnings("unchecked")
648 Either<HeatParameterDefinition, ResultStatusEnum> propertyStatus = createModuleHeatParameter((Map<String, Object>) propertyNameValue.getValue());
649 if (propertyStatus.isRight()) {
650 return Either.right(propertyStatus.right().value());
652 HeatParameterDefinition property = propertyStatus.left().value();
653 property.setName(String.valueOf(propertyNameValue.getKey()));
654 moduleProperties.add(property);
656 addHeatParamDefinition(moduleProperties, propertyNameValue, true);
659 addHeatParamDefinition(moduleProperties, propertyNameValue, false);
664 if (!isEmpty(moduleProperties)) {
665 eitherResult = Either.left(moduleProperties);
673 private static void addHeatParamDefinition(List<HeatParameterDefinition> moduleProperties, Entry<String, Object> propertyNameValue, boolean isJson) {
674 HeatParameterDefinition property = new HeatParameterDefinition();
675 Object value = propertyNameValue.getValue();
677 property.setDefaultValue(isJson ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value)));
679 property.setName(String.valueOf(propertyNameValue.getKey()));
680 moduleProperties.add(property);
683 private static Either<HeatParameterDefinition, ResultStatusEnum> createModuleHeatParameter(Map<String, Object> propertyValue) {
684 HeatParameterDefinition propertyDef = new HeatParameterDefinition();
686 Either<String, ResultStatusEnum> propertyFieldType = findFirstToscaStringElement(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE);
687 if (propertyFieldType.isLeft()) {
688 type = propertyFieldType.left().value();
689 propertyDef.setType(type);
691 return Either.right(ResultStatusEnum.INVALID_PROPERTY_TYPE);
693 Either<String, ResultStatusEnum> propertyFieldDescription = findFirstToscaStringElement(propertyValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION);
694 if (propertyFieldDescription.isLeft()) {
695 propertyDef.setDescription(propertyFieldDescription.left().value());
698 Either<Object, ResultStatusEnum> propertyFieldDefaultVal = findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, ToscaElementTypeEnum.ALL);
699 if (propertyFieldDefaultVal.isLeft()) {
700 if (propertyFieldDefaultVal.left().value() == null) {
701 return Either.right(ResultStatusEnum.INVALID_PROPERTY_VALUE);
703 Object value = propertyFieldDefaultVal.left().value();
704 String defaultValue = type.equals(HeatParameterType.JSON.getType()) ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value));
705 propertyDef.setDefaultValue(defaultValue);
706 propertyDef.setCurrentValue(defaultValue);
709 return Either.left(propertyDef);
711 public static boolean containsGetInput(Object propValue) {
712 String value = getPropertyJsonStringValue(propValue, ToscaPropertyType.MAP.getType());
713 return value != null && value.contains(TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName());
716 public static String getPropertyJsonStringValue(Object value, String type) {
717 Gson gson = new Gson();
721 ToscaPropertyType validType = ToscaPropertyType.isValidType(type);
722 if (validType == null || validType == ToscaPropertyType.JSON || validType == ToscaPropertyType.MAP || validType == ToscaPropertyType.LIST) {
723 return gson.toJson(value);
725 return value.toString();
729 * removes from Json map (toscaJson) first element found by name (elementName) note that this method could update the received argument toscaJson
734 public static void removeElementFromJsonMap(Map<String, Object> toscaJson, String elementName) {
735 for (Entry<String, Object> entry : toscaJson.entrySet()) {
736 String key = entry.getKey();
737 Object value = entry.getValue();
738 if (key.equals(elementName)) {
739 toscaJson.remove(elementName);
741 } else if (value instanceof Map) {
742 removeElementFromJsonMap((Map<String, Object>) value, elementName);