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 static org.apache.commons.collections.CollectionUtils.isEmpty;
24 import static org.openecomp.sdc.be.components.impl.ResourceImportManager.PROPERTY_NAME_PATTERN_IGNORE_LENGTH;
25 import static org.openecomp.sdc.be.datatypes.elements.Annotation.setAnnotationsName;
27 import com.google.gson.Gson;
28 import com.google.gson.GsonBuilder;
29 import com.google.gson.JsonParseException;
30 import com.google.gson.reflect.TypeToken;
31 import fj.data.Either;
32 import java.lang.reflect.Type;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.LinkedHashMap;
39 import java.util.List;
41 import java.util.Map.Entry;
42 import java.util.function.Consumer;
43 import java.util.function.Function;
44 import org.apache.commons.collections.CollectionUtils;
45 import org.apache.commons.lang3.StringEscapeUtils;
46 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
47 import org.openecomp.sdc.be.config.BeEcompErrorManager;
48 import org.openecomp.sdc.be.dao.api.ActionStatus;
49 import org.openecomp.sdc.be.datatypes.elements.Annotation;
50 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
51 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
52 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
53 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
54 import org.openecomp.sdc.be.impl.ComponentsUtils;
55 import org.openecomp.sdc.be.model.AnnotationTypeDefinition;
56 import org.openecomp.sdc.be.model.AttributeDefinition;
57 import org.openecomp.sdc.be.model.HeatParameterDefinition;
58 import org.openecomp.sdc.be.model.InputDefinition;
59 import org.openecomp.sdc.be.model.LifecycleStateEnum;
60 import org.openecomp.sdc.be.model.PropertyConstraint;
61 import org.openecomp.sdc.be.model.PropertyDefinition;
62 import org.openecomp.sdc.be.model.heat.HeatParameterType;
63 import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
64 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
65 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
66 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType;
67 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
68 import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException;
69 import org.openecomp.sdc.be.utils.TypeUtils;
70 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
71 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
72 import org.openecomp.sdc.common.log.wrappers.Logger;
73 import org.openecomp.sdc.exception.ResponseFormat;
74 import org.springframework.beans.factory.annotation.Autowired;
75 import org.springframework.beans.factory.config.YamlProcessor;
76 import org.springframework.stereotype.Component;
77 import org.yaml.snakeyaml.DumperOptions;
78 import org.yaml.snakeyaml.Yaml;
79 import org.yaml.snakeyaml.constructor.Constructor;
80 import org.yaml.snakeyaml.nodes.Tag;
81 import org.yaml.snakeyaml.representer.Representer;
82 import org.yaml.snakeyaml.resolver.Resolver;
85 public final class ImportUtils {
87 private static final CustomResolver customResolver = new CustomResolver();
88 private static final Yaml strictYamlLoader = new YamlLoader().getStrictYamlLoader();
90 private static ComponentsUtils componentsUtils;
92 private static final Logger log = Logger.getLogger(ImportUtils.class);
94 private ImportUtils() {
98 public static void setComponentsUtils(ComponentsUtils componentsUtils) {
99 componentsUtils = componentsUtils;
102 private static class CustomResolver extends Resolver {
105 protected void addImplicitResolvers() {
106 // avoid implicit resolvers for strings that can be interpreted as boolean values
107 addImplicitResolver(Tag.STR, EMPTY, "");
108 addImplicitResolver(Tag.STR, NULL, null);
109 addImplicitResolver(Tag.NULL, NULL, "~nN\0");
110 addImplicitResolver(Tag.NULL, EMPTY, null);
111 addImplicitResolver(Tag.INT, INT, "-+0123456789");
112 addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
113 addImplicitResolver(Tag.YAML, YAML, "!&*");
117 private static void buildMap(Map<String, Object> output, Map<String, Object> map) {
118 for (Entry<String, Object> entry : map.entrySet()) {
119 String key = entry.getKey();
120 Object value = entry.getValue();
121 if (value instanceof Map) {
122 Map<String, Object> result = new LinkedHashMap<>();
123 buildMap(result, (Map) value);
124 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()));
133 output.put(key, value);
138 public static Map<String, Object> loadYamlAsStrictMap(String content) {
139 Map<String, Object> result = new LinkedHashMap<>();
140 Object map = strictYamlLoader.load(content);
141 buildMap(result, (Map<String, Object>) map);
145 private static class YamlLoader extends YamlProcessor {
147 public Yaml getStrictYamlLoader() {
152 @SuppressWarnings("unchecked")
153 public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParamsWithoutImplicitTypes(
154 String heatDecodedPayload, String artifactType) {
155 Map<String, Object> heatData = (Map<String, Object>) new Yaml(new Constructor(), new Representer(),
156 new DumperOptions(), customResolver).load(heatDecodedPayload);
157 return getHeatParameters(heatData, artifactType);
160 public static class Constants {
162 public static final String FIRST_NON_CERTIFIED_VERSION = "0.1";
163 public static final String VENDOR_NAME = "ONAP (Tosca)";
164 public static final String VENDOR_RELEASE = "1.0.0.wd03";
165 public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE = LifecycleStateEnum.CERTIFIED;
166 public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT;
167 public static final boolean NORMATIVE_TYPE_HIGHEST_VERSION = true;
168 public static final String ABSTRACT_CATEGORY_NAME = "Generic";
169 public static final String ABSTRACT_SUBCATEGORY = "Abstract";
170 public static final String DEFAULT_ICON = "defaulticon";
171 public static final String INNER_VFC_DESCRIPTION = "Not reusable inner VFC";
172 public static final String USER_DEFINED_RESOURCE_NAMESPACE_PREFIX = "org.openecomp.resource.";
173 public static final String UI_JSON_PAYLOAD_NAME = "payloadName";
174 public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF";
175 public static final String ESCAPED_DOUBLE_QUOTE = "\"";
176 public static final String QUOTE = "'";
177 public static final String VF_DESCRIPTION = "Nested VF in service";
179 private Constants() {
183 public enum ResultStatusEnum {
184 ELEMENT_NOT_FOUND, GENERAL_ERROR, OK, INVALID_PROPERTY_DEFAULT_VALUE, INVALID_PROPERTY_TYPE, INVALID_PROPERTY_VALUE, MISSING_ENTRY_SCHEMA_TYPE, INVALID_PROPERTY_NAME
187 public enum ToscaElementTypeEnum {
188 BOOLEAN, STRING, MAP, LIST, ALL
191 @SuppressWarnings("unchecked")
192 private static void handleElementNameNotFound(String elementName, Object elementValue,
193 ToscaElementTypeEnum elementType, List<Object> returnedList) {
194 if (elementValue instanceof Map) {
195 findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
196 } else if (elementValue instanceof List) {
197 findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
201 @SuppressWarnings("unchecked")
202 private static void addFoundElementAccordingToItsType(String elementName, ToscaElementTypeEnum elementType,
203 List<Object> returnedList, Object elementValue) {
205 if (elementValue instanceof Boolean) {
206 if (elementType == ToscaElementTypeEnum.BOOLEAN || elementType == ToscaElementTypeEnum.ALL) {
207 returnedList.add(elementValue);
209 } else if (elementValue instanceof String) {
210 if (elementType == ToscaElementTypeEnum.STRING || elementType == ToscaElementTypeEnum.ALL) {
211 returnedList.add(elementValue);
213 } else if (elementValue instanceof Map) {
214 if (elementType == ToscaElementTypeEnum.MAP || elementType == ToscaElementTypeEnum.ALL) {
215 returnedList.add(elementValue);
217 findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
219 } else if (elementValue instanceof List) {
220 if (elementType == ToscaElementTypeEnum.LIST || elementType == ToscaElementTypeEnum.ALL) {
221 returnedList.add(elementValue);
223 findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
226 // For Integer, Double etc...
227 else if (elementType == ToscaElementTypeEnum.ALL && elementValue != null) {
228 returnedList.add(String.valueOf(elementValue));
232 private static void findAllToscaElementsInList(List<Object> list, String elementName,
233 ToscaElementTypeEnum elementType, List<Object> returnedList) {
234 list.forEach(elementValue -> handleElementNameNotFound(elementName, elementValue, elementType, returnedList));
237 public static Either<Object, ResultStatusEnum> findToscaElement(Map<String, Object> toscaJson,
238 TypeUtils.ToscaTagNamesEnum elementName,
239 ToscaElementTypeEnum elementType) {
240 List<Object> foundElements = new ArrayList<>();
241 findToscaElements(toscaJson, elementName.getElementName(), elementType, foundElements);
242 if (!isEmpty(foundElements)) {
243 return Either.left(foundElements.get(0));
245 return Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
249 * Recursively searches for all tosca elements with key equals to elementName and value equals to elementType. <br>
250 * Returns Either element with:<br> List with all value if values found<br> Or ELEMENT_NOT_FOUND ActionStatus
255 public static Either<List<Object>, ResultStatusEnum> findToscaElements(Map<String, Object> toscaJson,
257 ToscaElementTypeEnum elementType,
258 List<Object> returnedList) {
259 Either<List<Object>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
260 String skipKey = null;
261 if (toscaJson.containsKey(elementName)) {
262 skipKey = handleFoundElement(toscaJson, elementName, elementType, returnedList);
265 Iterator<Entry<String, Object>> keyValItr = toscaJson.entrySet().iterator();
266 while (keyValItr.hasNext()) {
267 Entry<String, Object> keyValEntry = keyValItr.next();
268 if (!String.valueOf(keyValEntry.getKey()).equals(skipKey)) {
269 handleElementNameNotFound(elementName, keyValEntry.getValue(), elementType, returnedList);
273 if (!isEmpty(returnedList)) {
274 returnedElement = Either.left(returnedList);
277 return returnedElement;
280 private static String handleFoundElement(Map<String, Object> toscaJson, String elementName,
281 ToscaElementTypeEnum elementType, List<Object> returnedList) {
282 Object elementValue = toscaJson.get(elementName);
283 addFoundElementAccordingToItsType(elementName, elementType, returnedList, elementValue);
288 @SuppressWarnings("unchecked")
289 public static <T> Either<List<T>, ResultStatusEnum> findFirstToscaListElement(Map<String, Object> toscaJson,
290 TypeUtils.ToscaTagNamesEnum toscaTagName) {
291 Either<List<T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
292 Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName,
293 ToscaElementTypeEnum.LIST);
294 if (findFirstToscaElement.isLeft()) {
295 returnedElement = Either.left((List<T>) findFirstToscaElement.left().value());
297 return returnedElement;
301 @SuppressWarnings("unchecked")
302 public static <T> Either<Map<String, T>, ResultStatusEnum> findFirstToscaMapElement(Map<String, Object> toscaJson,
303 TypeUtils.ToscaTagNamesEnum toscaTagName) {
304 Either<Map<String, T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
305 Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName,
306 ToscaElementTypeEnum.MAP);
307 if (findFirstToscaElement.isLeft()) {
308 returnedElement = Either.left((Map<String, T>) findFirstToscaElement.left().value());
310 return returnedElement;
314 public static Either<String, ResultStatusEnum> findFirstToscaStringElement(Map<String, Object> toscaJson,
315 TypeUtils.ToscaTagNamesEnum toscaTagName) {
316 Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
317 Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName,
318 ToscaElementTypeEnum.STRING);
319 if (findFirstToscaElements.isLeft()) {
320 returnedElement = Either.left((String) findFirstToscaElements.left().value());
322 return returnedElement;
326 * searches for first Tosca in Json map (toscaJson) boolean element by name (toscaTagName) returns found element or
327 * ELEMENT_NOT_FOUND status
330 * @param toscaTagName
333 public static Either<String, ResultStatusEnum> findFirstToscaBooleanElement(Map<String, Object> toscaJson,
334 TypeUtils.ToscaTagNamesEnum toscaTagName) {
335 Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
336 Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName,
337 ToscaElementTypeEnum.BOOLEAN);
338 if (findFirstToscaElements.isLeft()) {
339 returnedElement = Either.left(String.valueOf(findFirstToscaElements.left().value()));
341 return returnedElement;
344 private static void setPropertyConstraints(Map<String, Object> propertyValue, PropertyDefinition property) {
345 List<PropertyConstraint> constraints = getPropertyConstraints(propertyValue, property.getType());
346 if (CollectionUtils.isNotEmpty(constraints)) {
347 property.setConstraints(constraints);
351 private static List<PropertyConstraint> getPropertyConstraints(Map<String, Object> propertyValue,
352 String propertyType) {
353 List<Object> propertyFieldConstraints = findCurrentLevelConstraintsElement(propertyValue);
354 if (CollectionUtils.isNotEmpty(propertyFieldConstraints)) {
355 List<PropertyConstraint> constraintList = new ArrayList<>();
356 Type constraintType = new TypeToken<PropertyConstraint>() {
358 Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser())
361 for (Object constraintJson : propertyFieldConstraints) {
362 PropertyConstraint propertyConstraint = validateAndGetPropertyConstraint(propertyType, constraintType,
363 gson, constraintJson);
364 constraintList.add(propertyConstraint);
366 return constraintList;
371 private static List<Object> findCurrentLevelConstraintsElement(Map<String, Object> toscaJson) {
372 List<Object> constraints = null;
373 if (toscaJson.containsKey(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName())) {
375 constraints = (List<Object>) toscaJson.get(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName());
376 } catch (ClassCastException e) {
377 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS_FORMAT,
378 toscaJson.get(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName()).toString());
385 private static PropertyConstraint validateAndGetPropertyConstraint(String propertyType, Type constraintType,
386 Gson gson, Object constraintJson) {
387 PropertyConstraint propertyConstraint;
389 propertyConstraint = gson.fromJson(gson.toJson(constraintJson), constraintType);
390 } catch (ClassCastException | JsonParseException e) {
391 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS_FORMAT,
392 constraintJson.toString());
394 if (propertyConstraint != null && propertyConstraint instanceof ValidValuesConstraint) {
396 ((ValidValuesConstraint) propertyConstraint).validateType(propertyType);
397 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
398 BeEcompErrorManager.getInstance().logInternalFlowError("GetInitializedPropertyConstraint",
399 e.getMessage(), BeEcompErrorManager.ErrorSeverity.ERROR);
400 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS,
401 ConstraintType.VALID_VALUES.name(),
402 ((ValidValuesConstraint) propertyConstraint).getValidValues().toString(), propertyType);
405 return propertyConstraint;
408 public static PropertyDefinition createModuleProperty(Map<String, Object> propertyValue) {
410 PropertyDefinition propertyDef = new PropertyDefinition();
411 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE, propertyDef::setType);
412 setFieldBoolean(propertyValue, ToscaTagNamesEnum.REQUIRED,
413 req -> propertyDef.setRequired(Boolean.parseBoolean(req)));
414 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, propertyDef::setDescription);
416 setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, propertyDef.getType(),
417 propertyDef::setDefaultValue);
418 setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.VALUE, propertyDef.getType(),
419 propertyDef::setValue);
421 setFieldBoolean(propertyValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD,
422 pass -> propertyDef.setPassword(Boolean.parseBoolean(pass)));
423 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.STATUS, propertyDef::setStatus);
424 setScheme(propertyValue, propertyDef);
425 setPropertyConstraints(propertyValue, propertyDef);
430 private static void setJsonStringField(Map<String, Object> propertyValue, ToscaTagNamesEnum elementName,
431 String type, Consumer<String> setter) {
432 Either<Object, ResultStatusEnum> eitherValue = findToscaElement(propertyValue, elementName,
433 ToscaElementTypeEnum.ALL);
434 if (eitherValue.isLeft()) {
435 String propertyJsonStringValue = getPropertyJsonStringValue(eitherValue.left().value(), type);
436 setter.accept(propertyJsonStringValue);
440 public static Annotation createModuleAnnotation(Map<String, Object> annotationMap,
441 AnnotationTypeOperations annotationTypeOperations) {
442 String parsedAnnotationType = findFirstToscaStringElement(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE)
444 AnnotationTypeDefinition annotationTypeObject = annotationTypeOperations.getLatestType(parsedAnnotationType);
445 if (annotationTypeObject != null) {
446 Annotation annotation = new Annotation();
447 setField(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE, annotation::setType);
448 setField(annotationMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotation::setDescription);
449 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = getProperties(annotationMap);
450 modifyPropertiesKeysToProperForm(properties, annotation);
456 private static Either<Boolean, ResponseFormat> modifyPropertiesKeysToProperForm(
457 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties, Annotation annotation) {
458 Either<Boolean, ResponseFormat> result = Either.left(true);
459 if (properties.isLeft()) {
460 List<PropertyDataDefinition> propertiesList = new ArrayList<>();
461 Map<String, PropertyDefinition> value = properties.left().value();
463 for (Entry<String, PropertyDefinition> entry : value.entrySet()) {
464 String name = entry.getKey();
465 if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
466 log.debug("The property with invalid name {} occurred upon import resource {}. ", name,
467 annotation.getName());
468 result = Either.right(componentsUtils.getResponseFormat(componentsUtils
469 .convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME,
470 JsonPresentationFields.PROPERTY)));
472 PropertyDefinition propertyDefinition = entry.getValue();
473 propertyDefinition.setValue(propertyDefinition.getName());
474 propertyDefinition.setName(name);
475 propertiesList.add(propertyDefinition);
478 annotation.setProperties(propertiesList);
479 } else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) {
481 .right(componentsUtils.getResponseFormat(componentsUtils.convertFromResultStatusEnum(properties
483 .value(), JsonPresentationFields.PROPERTY)));
488 public static InputDefinition createModuleInput(Map<String, Object> inputValue,
489 AnnotationTypeOperations annotationTypeOperations) {
491 InputDefinition inputDef = new InputDefinition();
492 setField(inputValue, TypeUtils.ToscaTagNamesEnum.TYPE, inputDef::setType);
493 setFieldBoolean(inputValue, ToscaTagNamesEnum.REQUIRED, req -> inputDef.setRequired(Boolean.parseBoolean(req)));
494 setField(inputValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, inputDef::setDescription);
496 setJsonStringField(inputValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, inputDef.getType(),
497 inputDef::setDefaultValue);
499 setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> inputDef.setPassword(Boolean.parseBoolean(pass)));
500 setField(inputValue, TypeUtils.ToscaTagNamesEnum.STATUS, inputDef::setStatus);
501 setField(inputValue, TypeUtils.ToscaTagNamesEnum.LABEL, inputDef::setLabel);
502 setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.HIDDEN, hidden -> inputDef.setHidden(Boolean.parseBoolean(hidden)));
503 setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IMMUTABLE, immutable -> inputDef.setImmutable(Boolean.parseBoolean(immutable)));
505 setScheme(inputValue, inputDef);
506 setPropertyConstraints(inputValue, inputDef);
508 return parseAnnotationsAndAddItToInput(inputDef, inputValue, annotationTypeOperations);
512 public static InputDefinition parseAnnotationsAndAddItToInput(InputDefinition inputDef,
513 Map<String, Object> inputValue,
514 AnnotationTypeOperations annotationTypeOperations) {
515 Function<String, Annotation> elementGenByName = ImportUtils::createAnnotation;
516 Function<Map<String, Object>, Annotation> func = annotation -> createModuleAnnotation(annotation,
517 annotationTypeOperations);
518 return getElements(inputValue, TypeUtils.ToscaTagNamesEnum.ANNOTATIONS, elementGenByName, func).
519 left().map(annotations -> modifyInputWithAnnotations(inputDef, annotations)).
521 log.error("Parsing annotations or adding them to the PropertyDataDefinition object failed");
526 private static InputDefinition modifyInputWithAnnotations(InputDefinition inputDef,
527 Map<String, Annotation> annotationsMap) {
528 setAnnotationsName(annotationsMap);
529 inputDef.setAnnotationsToInput(annotationsMap.values());
533 public static AttributeDefinition createModuleAttribute(Map<String, Object> attributeMap) {
535 AttributeDefinition attributeDef = new AttributeDefinition();
536 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.TYPE, attributeDef::setType);
537 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, attributeDef::setDescription);
538 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.STATUS, attributeDef::setStatus);
540 setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, attributeDef.getType(),
541 attributeDef::set_default);
543 setScheme(attributeMap, attributeDef);
547 private static void setScheme(Map<String, Object> propertyValue,
548 ToscaDataDefinition toscaDataDefinition) {
549 Either<Object, ResultStatusEnum> schemaElementRes = findSchemaElement(propertyValue);
550 if (schemaElementRes.isLeft()) {
551 SchemaDefinition schemaDef = getSchema(schemaElementRes.left().value());
552 toscaDataDefinition.setSchema(schemaDef);
556 private static Either<Object, ResultStatusEnum> findSchemaElement(Map<String, Object> propertyValue) {
557 return findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA, ToscaElementTypeEnum.ALL);
560 private static SchemaDefinition getSchema(Object propertyFieldEntryScheme) {
561 SchemaDefinition schema = new SchemaDefinition();
562 if (propertyFieldEntryScheme instanceof String) {
563 String schemaType = (String) propertyFieldEntryScheme;
564 PropertyDefinition schemeProperty = new PropertyDefinition();
565 schemeProperty.setType(schemaType);
566 schema.setProperty(schemeProperty);
567 } else if (propertyFieldEntryScheme instanceof Map) {
568 PropertyDefinition schemeProperty = createModuleProperty((Map<String, Object>) propertyFieldEntryScheme);
569 schema.setProperty(schemeProperty);
574 private static void setField(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName,
575 Consumer<String> setter) {
576 Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaStringElement(toscaJson, tagName);
577 if (fieldStringValue.isLeft()) {
578 setter.accept(fieldStringValue.left().value());
583 public static void setFieldBoolean(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName,
584 Consumer<String> setter) {
585 Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaBooleanElement(toscaJson, tagName);
586 if (fieldStringValue.isLeft()) {
587 setter.accept(fieldStringValue.left().value());
592 public static Either<Map<String, PropertyDefinition>, ResultStatusEnum> getProperties(
593 Map<String, Object> toscaJson) {
594 Function<String, PropertyDefinition> elementGenByName = ImportUtils::createProperties;
595 Function<Map<String, Object>, PropertyDefinition> func = ImportUtils::createModuleProperty;
597 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.PROPERTIES, elementGenByName, func);
601 public static Either<Map<String, InputDefinition>, ResultStatusEnum> getInputs(Map<String, Object> toscaJson,
602 AnnotationTypeOperations annotationTypeOperations) {
603 Function<String, InputDefinition> elementGenByName = ImportUtils::createInputs;
604 Function<Map<String, Object>, InputDefinition> func = object -> createModuleInput(object,
605 annotationTypeOperations);
607 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.INPUTS, elementGenByName, func);
611 public static <T> Either<Map<String, T>, ResultStatusEnum> getElements(Map<String, Object> toscaJson,
612 TypeUtils.ToscaTagNamesEnum elementTagName,
613 Function<String, T> elementGenByName,
614 Function<Map<String, Object>, T> func) {
615 Either<Map<String, T>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
616 Either<Map<String, Object>, ResultStatusEnum> toscaAttributes = findFirstToscaMapElement(toscaJson,
618 if (toscaAttributes.isLeft()) {
619 Map<String, Object> jsonAttributes = toscaAttributes.left().value();
620 Map<String, T> moduleAttributes = new HashMap<>();
621 Iterator<Entry<String, Object>> propertiesNameValue = jsonAttributes.entrySet().iterator();
622 while (propertiesNameValue.hasNext()) {
623 Entry<String, Object> attributeNameValue = propertiesNameValue.next();
624 if (attributeNameValue.getValue() instanceof Map) {
625 @SuppressWarnings("unchecked")
626 T attribute = func.apply((Map<String, Object>) attributeNameValue.getValue());
627 if (attribute != null) {
628 moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), attribute);
631 T element = elementGenByName.apply(String.valueOf(attributeNameValue.getValue()));
632 moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), element);
635 if (moduleAttributes.size() > 0) {
636 eitherResult = Either.left(moduleAttributes);
644 private static AttributeDefinition createAttribute(String name) {
645 AttributeDefinition attribute = new AttributeDefinition();
647 attribute.setName(name);
651 private static PropertyDefinition createProperties(String name) {
652 PropertyDefinition property = new PropertyDefinition();
653 property.setDefaultValue(name);
654 property.setName(name);
658 private static InputDefinition createInputs(String name) {
659 InputDefinition input = new InputDefinition();
665 private static Annotation createAnnotation(String name) {
666 Annotation annotation = new Annotation();
667 annotation.setName(name);
671 public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParameters(Map<String, Object> heatData, String artifactType) {
673 Either<List<HeatParameterDefinition>, ResultStatusEnum> eitherResult = Either
674 .right(ResultStatusEnum.ELEMENT_NOT_FOUND);
675 Either<Map<String, Object>, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(heatData,
676 TypeUtils.ToscaTagNamesEnum.PARAMETERS);
677 if (toscaProperties.isLeft()) {
678 Map<String, Object> jsonProperties = toscaProperties.left().value();
679 List<HeatParameterDefinition> moduleProperties = new ArrayList<>();
680 Iterator<Entry<String, Object>> propertiesNameValue = jsonProperties.entrySet().iterator();
681 while (propertiesNameValue.hasNext()) {
682 Entry<String, Object> propertyNameValue = propertiesNameValue.next();
683 if (propertyNameValue.getValue() instanceof Map || propertyNameValue.getValue() instanceof List) {
684 if (!artifactType.equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
685 @SuppressWarnings("unchecked")
686 Either<HeatParameterDefinition, ResultStatusEnum> propertyStatus = createModuleHeatParameter(
687 (Map<String, Object>) propertyNameValue.getValue());
688 if (propertyStatus.isRight()) {
689 return Either.right(propertyStatus.right().value());
691 HeatParameterDefinition property = propertyStatus.left().value();
692 property.setName(String.valueOf(propertyNameValue.getKey()));
693 moduleProperties.add(property);
695 addHeatParamDefinition(moduleProperties, propertyNameValue, true);
698 addHeatParamDefinition(moduleProperties, propertyNameValue, false);
703 if (!isEmpty(moduleProperties)) {
704 eitherResult = Either.left(moduleProperties);
712 private static void addHeatParamDefinition(List<HeatParameterDefinition> moduleProperties,
713 Entry<String, Object> propertyNameValue, boolean isJson) {
714 HeatParameterDefinition property = new HeatParameterDefinition();
715 Object value = propertyNameValue.getValue();
717 property.setDefaultValue(
718 isJson ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value)));
720 property.setName(String.valueOf(propertyNameValue.getKey()));
721 moduleProperties.add(property);
724 private static Either<HeatParameterDefinition, ResultStatusEnum> createModuleHeatParameter(
725 Map<String, Object> propertyValue) {
726 HeatParameterDefinition propertyDef = new HeatParameterDefinition();
728 Either<String, ResultStatusEnum> propertyFieldType = findFirstToscaStringElement(propertyValue,
729 TypeUtils.ToscaTagNamesEnum.TYPE);
730 if (propertyFieldType.isLeft()) {
731 type = propertyFieldType.left().value();
732 propertyDef.setType(type);
734 return Either.right(ResultStatusEnum.INVALID_PROPERTY_TYPE);
736 Either<String, ResultStatusEnum> propertyFieldDescription = findFirstToscaStringElement(propertyValue,
737 TypeUtils.ToscaTagNamesEnum.DESCRIPTION);
738 if (propertyFieldDescription.isLeft()) {
739 propertyDef.setDescription(propertyFieldDescription.left().value());
742 Either<Object, ResultStatusEnum> propertyFieldDefaultVal = findToscaElement(propertyValue,
743 TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, ToscaElementTypeEnum.ALL);
744 if (propertyFieldDefaultVal.isLeft()) {
745 if (propertyFieldDefaultVal.left().value() == null) {
746 return Either.right(ResultStatusEnum.INVALID_PROPERTY_VALUE);
748 Object value = propertyFieldDefaultVal.left().value();
749 String defaultValue = type.equals(HeatParameterType.JSON.getType()) ? new Gson().toJson(value)
750 : StringEscapeUtils.escapeJava(String.valueOf(value));
751 propertyDef.setDefaultValue(defaultValue);
752 propertyDef.setCurrentValue(defaultValue);
755 return Either.left(propertyDef);
758 public static boolean containsGetInput(Object propValue) {
759 String value = getPropertyJsonStringValue(propValue, ToscaPropertyType.MAP.getType());
760 return value != null && value.contains(TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName());
763 public static String getPropertyJsonStringValue(Object value, String type) {
764 Gson gson = new Gson();
768 ToscaPropertyType validType = ToscaPropertyType.isValidType(type);
769 if (validType == null || validType == ToscaPropertyType.JSON || validType == ToscaPropertyType.MAP
770 || validType == ToscaPropertyType.LIST) {
771 return gson.toJson(value);
773 return value.toString();
777 * removes from Json map (toscaJson) first element found by name (elementName) note that this method could update
778 * the received argument toscaJson
783 public static void removeElementFromJsonMap(Map<String, Object> toscaJson, String elementName) {
784 for (Entry<String, Object> entry : toscaJson.entrySet()) {
785 String key = entry.getKey();
786 Object value = entry.getValue();
787 if (key.equals(elementName)) {
788 toscaJson.remove(elementName);
790 } else if (value instanceof Map) {
791 removeElementFromJsonMap((Map<String, Object>) value, elementName);