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=========================================================
20 package org.openecomp.sdc.be.components.impl;
22 import static org.apache.commons.collections.CollectionUtils.isEmpty;
23 import static org.openecomp.sdc.be.components.impl.ResourceImportManager.PROPERTY_NAME_PATTERN_IGNORE_LENGTH;
24 import static org.openecomp.sdc.be.datatypes.elements.Annotation.setAnnotationsName;
26 import com.google.gson.Gson;
27 import com.google.gson.GsonBuilder;
28 import com.google.gson.JsonParseException;
29 import com.google.gson.reflect.TypeToken;
30 import fj.data.Either;
31 import java.lang.reflect.Type;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.LinkedHashMap;
38 import java.util.List;
40 import java.util.Map.Entry;
41 import java.util.function.Consumer;
42 import java.util.function.Function;
43 import org.apache.commons.collections.CollectionUtils;
44 import org.apache.commons.text.StringEscapeUtils;
45 import org.onap.sdc.tosca.datatypes.model.EntrySchema;
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.ConstraintType;
53 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
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.OutputDefinition;
61 import org.openecomp.sdc.be.model.PropertyConstraint;
62 import org.openecomp.sdc.be.model.PropertyDefinition;
63 import org.openecomp.sdc.be.model.heat.HeatParameterType;
64 import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
65 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
66 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
67 import org.openecomp.sdc.be.model.tosca.constraints.AbstractComparablePropertyConstraint;
68 import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
69 import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
70 import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException;
71 import org.openecomp.sdc.be.utils.TypeUtils;
72 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
73 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
74 import org.openecomp.sdc.common.log.wrappers.Logger;
75 import org.openecomp.sdc.exception.ResponseFormat;
76 import org.springframework.beans.factory.annotation.Autowired;
77 import org.springframework.beans.factory.config.YamlProcessor;
78 import org.springframework.stereotype.Component;
79 import org.yaml.snakeyaml.DumperOptions;
80 import org.yaml.snakeyaml.Yaml;
81 import org.yaml.snakeyaml.constructor.Constructor;
82 import org.yaml.snakeyaml.nodes.Tag;
83 import org.yaml.snakeyaml.representer.Representer;
84 import org.yaml.snakeyaml.resolver.Resolver;
87 public final class ImportUtils {
89 private static final CustomResolver customResolver = new CustomResolver();
90 private static final Yaml strictYamlLoader = new YamlLoader().getStrictYamlLoader();
91 private static final Logger log = Logger.getLogger(ImportUtils.class);
92 private static ComponentsUtils componentsUtils;
94 private ImportUtils() {
98 public static void setComponentsUtils(ComponentsUtils cu) {
102 private static void buildMap(Map<String, Object> output, Map<String, Object> map) {
103 for (Entry<String, Object> entry : map.entrySet()) {
104 String key = entry.getKey();
105 Object value = entry.getValue();
106 if (value instanceof Map) {
107 Map<String, Object> result = new LinkedHashMap<>();
108 buildMap(result, (Map) value);
109 output.put(key, result);
110 } else if (value instanceof Collection) {
111 Map<String, Object> result = new LinkedHashMap<>();
113 for (Object item : (Collection<Object>) value) {
114 buildMap(result, Collections.singletonMap("[" + (i++) + "]", item));
116 output.put(key, new ArrayList<>(result.values()));
118 output.put(key, value);
123 public static Map<String, Object> loadYamlAsStrictMap(String content) {
124 Map<String, Object> result = new LinkedHashMap<>();
125 Object map = strictYamlLoader.load(content);
126 buildMap(result, (Map<String, Object>) map);
130 @SuppressWarnings("unchecked")
131 public static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParamsWithoutImplicitTypes(String heatDecodedPayload,
132 String artifactType) {
133 Map<String, Object> heatData = (Map<String, Object>) new Yaml(new Constructor(), new Representer(), new DumperOptions(), customResolver)
134 .load(heatDecodedPayload);
135 return getHeatParameters(heatData, artifactType);
138 @SuppressWarnings("unchecked")
139 private static void handleElementNameNotFound(String elementName, Object elementValue, ToscaElementTypeEnum elementType,
140 List<Object> returnedList) {
141 if (elementValue instanceof Map) {
142 findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
143 } else if (elementValue instanceof List) {
144 findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
148 @SuppressWarnings("unchecked")
149 private static void addFoundElementAccordingToItsType(String elementName, ToscaElementTypeEnum elementType, List<Object> returnedList,
150 Object elementValue) {
151 if (elementValue instanceof Boolean) {
152 if (elementType == ToscaElementTypeEnum.BOOLEAN || elementType == ToscaElementTypeEnum.ALL) {
153 returnedList.add(elementValue);
155 } else if (elementValue instanceof String) {
156 if (elementType == ToscaElementTypeEnum.STRING || elementType == ToscaElementTypeEnum.ALL) {
157 returnedList.add(elementValue);
159 } else if (elementValue instanceof Map) {
160 if (elementType == ToscaElementTypeEnum.MAP || elementType == ToscaElementTypeEnum.ALL) {
161 returnedList.add(elementValue);
163 findToscaElements((Map<String, Object>) elementValue, elementName, elementType, returnedList);
164 } else if (elementValue instanceof List) {
165 if (elementType == ToscaElementTypeEnum.LIST || elementType == ToscaElementTypeEnum.ALL) {
166 returnedList.add(elementValue);
168 findAllToscaElementsInList((List<Object>) elementValue, elementName, elementType, returnedList);
170 // For Integer, Double etc...
171 else if (elementType == ToscaElementTypeEnum.ALL && elementValue != null) {
172 returnedList.add(String.valueOf(elementValue));
176 private static void findAllToscaElementsInList(List<Object> list, String elementName, ToscaElementTypeEnum elementType,
177 List<Object> returnedList) {
178 list.forEach(elementValue -> handleElementNameNotFound(elementName, elementValue, elementType, returnedList));
181 public static Either<Object, ResultStatusEnum> findToscaElement(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum elementName,
182 ToscaElementTypeEnum elementType) {
183 final var toscaElements = findToscaElements(toscaJson, elementName.getElementName(), elementType, new ArrayList<>());
184 if (toscaElements.isLeft() && CollectionUtils.isNotEmpty(toscaElements.left().value())) {
185 return Either.left(toscaElements.left().value().get(0));
187 return Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
191 * Recursively searches for all tosca elements with key equals to elementName and value equals to elementType. <br> Returns Either element
192 * with:<br> List with all value if values found<br> Or ELEMENT_NOT_FOUND ActionStatus
197 public static Either<List<Object>, ResultStatusEnum> findToscaElements(Map<String, Object> toscaJson, String elementName,
198 ToscaElementTypeEnum elementType, List<Object> returnedList) {
199 Either<List<Object>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
200 String skipKey = null;
201 if (toscaJson.containsKey(elementName)) {
202 skipKey = handleFoundElement(toscaJson, elementName, elementType, returnedList);
204 Iterator<Entry<String, Object>> keyValItr = toscaJson.entrySet().iterator();
205 while (keyValItr.hasNext()) {
206 Entry<String, Object> keyValEntry = keyValItr.next();
207 if (!String.valueOf(keyValEntry.getKey()).equals(skipKey)) {
208 handleElementNameNotFound(elementName, keyValEntry.getValue(), elementType, returnedList);
211 if (!isEmpty(returnedList)) {
212 returnedElement = Either.left(returnedList);
214 return returnedElement;
217 private static String handleFoundElement(Map<String, Object> toscaJson, String elementName, ToscaElementTypeEnum elementType,
218 List<Object> returnedList) {
219 Object elementValue = toscaJson.get(elementName);
220 addFoundElementAccordingToItsType(elementName, elementType, returnedList, elementValue);
224 @SuppressWarnings("unchecked")
225 public static <T> Either<List<T>, ResultStatusEnum> findFirstToscaListElement(Map<String, Object> toscaJson,
226 TypeUtils.ToscaTagNamesEnum toscaTagName) {
227 Either<List<T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
228 Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.LIST);
229 if (findFirstToscaElement.isLeft()) {
230 returnedElement = Either.left((List<T>) findFirstToscaElement.left().value());
232 return returnedElement;
235 @SuppressWarnings("unchecked")
236 public static <T> Either<Map<String, T>, ResultStatusEnum> findFirstToscaMapElement(Map<String, Object> toscaJson,
237 TypeUtils.ToscaTagNamesEnum toscaTagName) {
238 Either<Map<String, T>, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
239 Either<Object, ResultStatusEnum> findFirstToscaElement = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.MAP);
240 if (findFirstToscaElement.isLeft()) {
241 returnedElement = Either.left((Map<String, T>) findFirstToscaElement.left().value());
243 return returnedElement;
246 public static Either<String, ResultStatusEnum> findFirstToscaStringElement(Map<String, Object> toscaJson,
247 TypeUtils.ToscaTagNamesEnum toscaTagName) {
248 Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
249 Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.STRING);
250 if (findFirstToscaElements.isLeft()) {
251 returnedElement = Either.left((String) findFirstToscaElements.left().value());
253 return returnedElement;
257 * searches for first Tosca in Json map (toscaJson) boolean element by name (toscaTagName) returns found element or ELEMENT_NOT_FOUND status
260 * @param toscaTagName
263 private static Either<String, ResultStatusEnum> findFirstToscaBooleanElement(Map<String, Object> toscaJson,
264 TypeUtils.ToscaTagNamesEnum toscaTagName) {
265 Either<String, ResultStatusEnum> returnedElement = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
266 Either<Object, ResultStatusEnum> findFirstToscaElements = findToscaElement(toscaJson, toscaTagName, ToscaElementTypeEnum.BOOLEAN);
267 if (findFirstToscaElements.isLeft()) {
268 returnedElement = Either.left(String.valueOf(findFirstToscaElements.left().value()));
270 return returnedElement;
273 private static void setPropertyConstraints(Map<String, Object> propertyValue, PropertyDefinition property) {
274 List<PropertyConstraint> constraints = getPropertyConstraints(propertyValue, property.getType(), property.getSchema());
275 if (CollectionUtils.isNotEmpty(constraints)) {
276 property.setConstraints(constraints);
280 private static List<PropertyConstraint> getPropertyConstraints(final Map<String, Object> propertyValue, final String propertyType, final SchemaDefinition schema) {
281 final List<Object> propertyFieldConstraints = findCurrentLevelConstraintsElement(propertyValue);
282 if (CollectionUtils.isEmpty(propertyFieldConstraints)) {
283 return Collections.emptyList();
285 final List<PropertyConstraint> constraintList = new ArrayList<>();
286 final Type constraintType = new TypeToken<PropertyConstraint>() {
288 final Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create();
289 for (final Object constraintJson : propertyFieldConstraints) {
290 final PropertyConstraint propertyConstraint = validateAndGetPropertyConstraint(propertyType, constraintType, gson, constraintJson, schema);
291 if (propertyConstraint != null) {
292 constraintList.add(propertyConstraint);
295 return constraintList;
298 private static List<Object> findCurrentLevelConstraintsElement(Map<String, Object> toscaJson) {
299 List<Object> constraints = null;
300 if (toscaJson.containsKey(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName())) {
302 constraints = (List<Object>) toscaJson.get(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName());
303 } catch (ClassCastException e) {
304 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS_FORMAT,
305 toscaJson.get(TypeUtils.ToscaTagNamesEnum.CONSTRAINTS.getElementName()).toString());
311 private static PropertyConstraint validateAndGetPropertyConstraint(String propertyType, Type constraintType, Gson gson, Object constraintJson, SchemaDefinition schema) {
312 PropertyConstraint propertyConstraint;
314 propertyConstraint = gson.fromJson(gson.toJson(constraintJson), constraintType);
315 } catch (ClassCastException | JsonParseException e) {
316 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS_FORMAT, constraintJson.toString());
318 if (propertyConstraint instanceof ValidValuesConstraint) {
320 ((ValidValuesConstraint) propertyConstraint).validateType(propertyType, schema);
321 boolean valid = ((ValidValuesConstraint) propertyConstraint).validateValueType(propertyType);
323 ((ValidValuesConstraint) propertyConstraint).changeConstraintValueTypeTo(propertyType);
325 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
326 BeEcompErrorManager.getInstance()
327 .logInternalFlowError("GetInitializedPropertyConstraint", e.getMessage(), BeEcompErrorManager.ErrorSeverity.ERROR);
328 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS, ConstraintType.VALID_VALUES.name(),
329 ((ValidValuesConstraint) propertyConstraint).getValidValues().toString(), propertyType);
331 } else if (propertyConstraint instanceof AbstractComparablePropertyConstraint) {
333 boolean valid = ((AbstractComparablePropertyConstraint) propertyConstraint).validateValueType(propertyType);
335 ((AbstractComparablePropertyConstraint) propertyConstraint).changeConstraintValueTypeTo(propertyType);
337 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
338 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS, propertyConstraint.getConstraintType().name(),
339 propertyConstraint.toString(), propertyType);
341 } else if (propertyConstraint instanceof InRangeConstraint) {
343 boolean valid = ((InRangeConstraint) propertyConstraint).validateValueType(propertyType);
345 ((InRangeConstraint) propertyConstraint).changeConstraintValueTypeTo(propertyType);
347 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
348 throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY_CONSTRAINTS, ConstraintType.IN_RANGE.name(),
349 String.valueOf(((InRangeConstraint) propertyConstraint).getInRange()), propertyType);
352 return propertyConstraint;
355 static PropertyDefinition createModuleProperty(Map<String, Object> propertyValue) {
356 PropertyDefinition propertyDef = new PropertyDefinition();
357 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE, propertyDef::setType);
358 setFieldBoolean(propertyValue, ToscaTagNamesEnum.REQUIRED, req -> propertyDef.setRequired(Boolean.parseBoolean(req)));
359 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, propertyDef::setDescription);
360 setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, propertyDef.getType(), propertyDef::setDefaultValue);
361 setJsonStringField(propertyValue, TypeUtils.ToscaTagNamesEnum.VALUE, propertyDef.getType(), propertyDef::setValue);
362 setFieldBoolean(propertyValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> propertyDef.setPassword(Boolean.parseBoolean(pass)));
363 setField(propertyValue, TypeUtils.ToscaTagNamesEnum.STATUS, propertyDef::setStatus);
364 setSchema(propertyValue, propertyDef);
365 setPropertyConstraints(propertyValue, propertyDef);
369 private static void setJsonStringField(Map<String, Object> propertyValue, ToscaTagNamesEnum elementName, String type, Consumer<String> setter) {
370 Either<Object, ResultStatusEnum> eitherValue = findToscaElement(propertyValue, elementName, ToscaElementTypeEnum.ALL);
371 if (eitherValue.isLeft()) {
372 setter.accept(getPropertyJsonStringValue(eitherValue.left().value(), type));
376 private static Annotation createModuleAnnotation(Map<String, Object> annotationMap, AnnotationTypeOperations annotationTypeOperations) {
377 String parsedAnnotationType = findFirstToscaStringElement(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE).left().value();
378 AnnotationTypeDefinition annotationTypeObject = annotationTypeOperations.getLatestType(parsedAnnotationType);
379 if (annotationTypeObject != null) {
380 Annotation annotation = new Annotation();
381 setField(annotationMap, TypeUtils.ToscaTagNamesEnum.TYPE, annotation::setType);
382 setField(annotationMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotation::setDescription);
383 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = getProperties(annotationMap);
384 modifyPropertiesKeysToProperForm(properties, annotation);
390 private static Either<Boolean, ResponseFormat> modifyPropertiesKeysToProperForm(
391 Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties, Annotation annotation) {
392 Either<Boolean, ResponseFormat> result = Either.left(true);
393 if (properties.isLeft()) {
394 List<PropertyDataDefinition> propertiesList = new ArrayList<>();
395 Map<String, PropertyDefinition> value = properties.left().value();
397 for (Entry<String, PropertyDefinition> entry : value.entrySet()) {
398 String name = entry.getKey();
399 if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
400 log.debug("The property with invalid name {} occurred upon import resource {}. ", name, annotation.getName());
401 result = Either.right(componentsUtils.getResponseFormat(
402 componentsUtils.convertFromResultStatusEnum(ResultStatusEnum.INVALID_PROPERTY_NAME, JsonPresentationFields.PROPERTY)));
404 PropertyDefinition propertyDefinition = entry.getValue();
405 propertyDefinition.setValue(propertyDefinition.getName());
406 propertyDefinition.setName(name);
407 propertiesList.add(propertyDefinition);
410 annotation.setProperties(propertiesList);
411 } else if (properties.right().value() != ResultStatusEnum.ELEMENT_NOT_FOUND) {
412 result = Either.right(componentsUtils
413 .getResponseFormat(componentsUtils.convertFromResultStatusEnum(properties.right().value(), JsonPresentationFields.PROPERTY)));
418 private static InputDefinition createModuleInput(final Map<String, Object> inputValue, final AnnotationTypeOperations annotationTypeOperations) {
419 return parseAnnotationsAndAddItToInput(createModuleInput(inputValue), inputValue, annotationTypeOperations);
422 private static InputDefinition createModuleInput(final Map<String, Object> inputValue) {
423 final InputDefinition inputDef = new InputDefinition();
424 setField(inputValue, TypeUtils.ToscaTagNamesEnum.TYPE, inputDef::setType);
425 setFieldBoolean(inputValue, ToscaTagNamesEnum.REQUIRED, req -> inputDef.setRequired(Boolean.parseBoolean(req)));
426 setField(inputValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, inputDef::setDescription);
427 setJsonStringField(inputValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, inputDef.getType(), inputDef::setDefaultValue);
428 setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD, pass -> inputDef.setPassword(Boolean.parseBoolean(pass)));
429 setField(inputValue, TypeUtils.ToscaTagNamesEnum.STATUS, inputDef::setStatus);
430 setField(inputValue, TypeUtils.ToscaTagNamesEnum.LABEL, inputDef::setLabel);
431 setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.HIDDEN, hidden -> inputDef.setHidden(Boolean.parseBoolean(hidden)));
432 setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IMMUTABLE, immutable -> inputDef.setImmutable(Boolean.parseBoolean(immutable)));
433 setFieldMap(inputValue, ToscaTagNamesEnum.METADATA, inputDef::setMetadata);
434 setSchema(inputValue, inputDef);
435 setPropertyConstraints(inputValue, inputDef);
439 private static OutputDefinition createModuleOutput(final Map<String, Object> outputValue) {
440 final OutputDefinition outputDef = new OutputDefinition();
441 setField(outputValue, TypeUtils.ToscaTagNamesEnum.TYPE, outputDef::setType);
442 setField(outputValue, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, outputDef::setDescription);
443 setJsonStringField(outputValue, TypeUtils.ToscaTagNamesEnum.VALUE, outputDef.getType(), outputDef::setValue);
444 setField(outputValue, TypeUtils.ToscaTagNamesEnum.STATUS, outputDef::setStatus);
448 private static InputDefinition parseAnnotationsAndAddItToInput(InputDefinition inputDef, Map<String, Object> inputValue,
449 AnnotationTypeOperations annotationTypeOperations) {
450 Function<String, Annotation> elementGenByName = ImportUtils::createAnnotation;
451 Function<Map<String, Object>, Annotation> func = annotation -> createModuleAnnotation(annotation, annotationTypeOperations);
452 return getElements(inputValue, TypeUtils.ToscaTagNamesEnum.ANNOTATIONS, elementGenByName, func).left()
453 .map(annotations -> modifyInputWithAnnotations(inputDef, annotations)).left().on(err -> {
454 log.error("Parsing annotations or adding them to the PropertyDataDefinition object failed");
459 private static InputDefinition modifyInputWithAnnotations(InputDefinition inputDef, Map<String, Annotation> annotationsMap) {
460 setAnnotationsName(annotationsMap);
461 inputDef.setAnnotationsToInput(annotationsMap.values());
465 static AttributeDefinition createModuleAttribute(Map<String, Object> attributeMap) {
466 AttributeDefinition attributeDef = new AttributeDefinition();
467 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.TYPE, attributeDef::setType);
468 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, attributeDef::setDescription);
469 setField(attributeMap, TypeUtils.ToscaTagNamesEnum.STATUS, attributeDef::setStatus);
470 setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, attributeDef.getType(), attributeDef::set_default);
471 setEntrySchema(attributeMap, attributeDef);
475 private static void setSchema(final Map<String, Object> propertyValue, final PropertyDefinition propertyDefinition) {
476 final Either<Object, ResultStatusEnum> schemaElementRes = findEntrySchemaElement(propertyValue);
477 if (schemaElementRes.isLeft()) {
478 propertyDefinition.setSchema(getSchema(schemaElementRes.left().value()));
482 private static void setEntrySchema(final Map<String, Object> toscaJsonMap, final AttributeDefinition attributeDefinition) {
483 final Either<Object, ResultStatusEnum> schemaElementRes = findEntrySchemaElement(toscaJsonMap);
484 if (schemaElementRes.isLeft()) {
485 attributeDefinition.setEntry_schema(createEntrySchema(schemaElementRes.left().value()));
489 private static Either<Object, ResultStatusEnum> findEntrySchemaElement(final Map<String, Object> propertyValue) {
490 return findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA, ToscaElementTypeEnum.ALL);
493 private static SchemaDefinition getSchema(Object propertyFieldEntryScheme) {
494 SchemaDefinition schema = new SchemaDefinition();
495 if (propertyFieldEntryScheme instanceof String) {
496 String schemaType = (String) propertyFieldEntryScheme;
497 PropertyDefinition schemeProperty = new PropertyDefinition();
498 schemeProperty.setType(schemaType);
499 schema.setProperty(schemeProperty);
500 } else if (propertyFieldEntryScheme instanceof Map) {
501 PropertyDefinition schemeProperty = createModuleProperty((Map<String, Object>) propertyFieldEntryScheme);
502 schema.setProperty(schemeProperty);
507 private static EntrySchema createEntrySchema(final Object toscaEntrySchemaObj) {
508 final EntrySchema entrySchema = new EntrySchema();
509 if (toscaEntrySchemaObj instanceof String) {
510 entrySchema.setType((String) toscaEntrySchemaObj);
511 } else if (toscaEntrySchemaObj instanceof Map) {
512 final PropertyDefinition schemeProperty = createModuleProperty((Map<String, Object>) toscaEntrySchemaObj);
513 entrySchema.setType(schemeProperty.getType());
514 entrySchema.setDescription(schemeProperty.getDescription());
519 private static void setField(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName, Consumer<String> setter) {
520 Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaStringElement(toscaJson, tagName);
521 if (fieldStringValue.isLeft()) {
522 setter.accept(fieldStringValue.left().value());
526 private static void setFieldBoolean(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName, Consumer<String> setter) {
527 Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaBooleanElement(toscaJson, tagName);
528 if (fieldStringValue.isLeft()) {
529 setter.accept(fieldStringValue.left().value());
533 private static void setFieldMap(final Map<String, Object> toscaJson, final ToscaTagNamesEnum tagName,
534 final Consumer<Map<String, String>> setter) {
535 final Either<Map<String, String>, ResultStatusEnum> toscaMapElement = findFirstToscaMapElement(toscaJson, tagName);
536 if (toscaMapElement.isLeft()) {
537 setter.accept(toscaMapElement.left().value());
541 public static Either<Map<String, PropertyDefinition>, ResultStatusEnum> getProperties(Map<String, Object> toscaJson) {
542 Function<String, PropertyDefinition> elementGenByName = ImportUtils::createProperties;
543 Function<Map<String, Object>, PropertyDefinition> func = ImportUtils::createModuleProperty;
544 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.PROPERTIES, elementGenByName, func);
547 public static Either<Map<String, AttributeDefinition>, ResultStatusEnum> getAttributes(final Map<String, Object> toscaJson) {
548 final Function<String, AttributeDefinition> elementGenByName = ImportUtils::createAttribute;
549 final Function<Map<String, Object>, AttributeDefinition> func = ImportUtils::createModuleAttribute;
550 return getElements(toscaJson, ToscaTagNamesEnum.ATTRIBUTES, elementGenByName, func);
553 public static Either<Map<String, InputDefinition>, ResultStatusEnum> getInputs(Map<String, Object> toscaJson,
554 AnnotationTypeOperations annotationTypeOperations) {
555 Function<String, InputDefinition> elementGenByName = ImportUtils::createInputs;
556 Function<Map<String, Object>, InputDefinition> func = object -> createModuleInput(object, annotationTypeOperations);
557 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.INPUTS, elementGenByName, func);
560 public static Either<Map<String, OutputDefinition>, ResultStatusEnum> getOutputs(Map<String, Object> toscaJson) {
561 final Function<String, OutputDefinition> elementGenByName = ImportUtils::createOutputs;
562 final Function<Map<String, Object>, OutputDefinition> func = ImportUtils::createModuleOutput;
563 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.OUTPUTS, elementGenByName, func);
566 public static Either<Map<String, InputDefinition>, ResultStatusEnum> getInputs(final Map<String, Object> toscaJson) {
567 return getElements(toscaJson, TypeUtils.ToscaTagNamesEnum.INPUTS, ImportUtils::createInputs, ImportUtils::createModuleInput);
570 private static <T> Either<Map<String, T>, ResultStatusEnum> getElements(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum elementTagName,
571 Function<String, T> elementGenByName,
572 Function<Map<String, Object>, T> func) {
573 Either<Map<String, T>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
574 Either<Map<String, Object>, ResultStatusEnum> toscaAttributes = findFirstToscaMapElement(toscaJson, elementTagName);
575 if (toscaAttributes.isLeft()) {
576 Map<String, Object> jsonAttributes = toscaAttributes.left().value();
577 Map<String, T> moduleAttributes = new HashMap<>();
578 Iterator<Entry<String, Object>> propertiesNameValue = jsonAttributes.entrySet().iterator();
579 while (propertiesNameValue.hasNext()) {
580 Entry<String, Object> attributeNameValue = propertiesNameValue.next();
581 if (attributeNameValue.getValue() instanceof Map) {
582 @SuppressWarnings("unchecked") T attribute = func.apply((Map<String, Object>) attributeNameValue.getValue());
583 if (attribute != null) {
584 moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), attribute);
587 T element = elementGenByName.apply(String.valueOf(attributeNameValue.getValue()));
588 moduleAttributes.put(String.valueOf(attributeNameValue.getKey()), element);
591 if (moduleAttributes.size() > 0) {
592 eitherResult = Either.left(moduleAttributes);
598 private static AttributeDefinition createAttribute(String name) {
599 AttributeDefinition attribute = new AttributeDefinition();
600 attribute.setName(name);
604 private static PropertyDefinition createProperties(String name) {
605 PropertyDefinition property = new PropertyDefinition();
606 property.setDefaultValue(name);
607 property.setName(name);
611 private static InputDefinition createInputs(String name) {
612 InputDefinition input = new InputDefinition();
617 private static OutputDefinition createOutputs(final String name) {
618 final OutputDefinition output = new OutputDefinition();
619 output.setName(name);
623 private static Annotation createAnnotation(String name) {
624 Annotation annotation = new Annotation();
625 annotation.setName(name);
629 static Either<List<HeatParameterDefinition>, ResultStatusEnum> getHeatParameters(Map<String, Object> heatData, String artifactType) {
630 Either<List<HeatParameterDefinition>, ResultStatusEnum> eitherResult = Either.right(ResultStatusEnum.ELEMENT_NOT_FOUND);
631 Either<Map<String, Object>, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(heatData, TypeUtils.ToscaTagNamesEnum.PARAMETERS);
632 if (toscaProperties.isLeft()) {
633 Map<String, Object> jsonProperties = toscaProperties.left().value();
634 List<HeatParameterDefinition> moduleProperties = new ArrayList<>();
635 Iterator<Entry<String, Object>> propertiesNameValue = jsonProperties.entrySet().iterator();
636 while (propertiesNameValue.hasNext()) {
637 Entry<String, Object> propertyNameValue = propertiesNameValue.next();
638 if (propertyNameValue.getValue() instanceof Map || propertyNameValue.getValue() instanceof List) {
639 if (!artifactType.equals(ArtifactTypeEnum.HEAT_ENV.getType())) {
640 @SuppressWarnings("unchecked") Either<HeatParameterDefinition, ResultStatusEnum> propertyStatus = createModuleHeatParameter(
641 (Map<String, Object>) propertyNameValue.getValue());
642 if (propertyStatus.isRight()) {
643 return Either.right(propertyStatus.right().value());
645 HeatParameterDefinition property = propertyStatus.left().value();
646 property.setName(String.valueOf(propertyNameValue.getKey()));
647 moduleProperties.add(property);
649 addHeatParamDefinition(moduleProperties, propertyNameValue, true);
652 addHeatParamDefinition(moduleProperties, propertyNameValue, false);
655 if (!isEmpty(moduleProperties)) {
656 eitherResult = Either.left(moduleProperties);
662 private static void addHeatParamDefinition(List<HeatParameterDefinition> moduleProperties, Entry<String, Object> propertyNameValue,
664 HeatParameterDefinition property = new HeatParameterDefinition();
665 Object value = propertyNameValue.getValue();
667 property.setDefaultValue(isJson ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value)));
669 property.setName(String.valueOf(propertyNameValue.getKey()));
670 moduleProperties.add(property);
673 private static Either<HeatParameterDefinition, ResultStatusEnum> createModuleHeatParameter(Map<String, Object> propertyValue) {
674 HeatParameterDefinition propertyDef = new HeatParameterDefinition();
676 Either<String, ResultStatusEnum> propertyFieldType = findFirstToscaStringElement(propertyValue, TypeUtils.ToscaTagNamesEnum.TYPE);
677 if (propertyFieldType.isLeft()) {
678 type = propertyFieldType.left().value();
679 propertyDef.setType(type);
681 return Either.right(ResultStatusEnum.INVALID_PROPERTY_TYPE);
683 Either<String, ResultStatusEnum> propertyFieldDescription = findFirstToscaStringElement(propertyValue,
684 TypeUtils.ToscaTagNamesEnum.DESCRIPTION);
685 if (propertyFieldDescription.isLeft()) {
686 propertyDef.setDescription(propertyFieldDescription.left().value());
688 Either<Object, ResultStatusEnum> propertyFieldDefaultVal = findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE,
689 ToscaElementTypeEnum.ALL);
690 if (propertyFieldDefaultVal.isLeft()) {
691 if (propertyFieldDefaultVal.left().value() == null) {
692 return Either.right(ResultStatusEnum.INVALID_PROPERTY_VALUE);
694 Object value = propertyFieldDefaultVal.left().value();
695 String defaultValue =
696 type.equals(HeatParameterType.JSON.getType()) ? new Gson().toJson(value) : StringEscapeUtils.escapeJava(String.valueOf(value));
697 propertyDef.setDefaultValue(defaultValue);
698 propertyDef.setCurrentValue(defaultValue);
700 return Either.left(propertyDef);
703 public static boolean containsGetInput(Object propValue) {
704 String value = getPropertyJsonStringValue(propValue, ToscaPropertyType.MAP.getType());
705 return value != null && value.contains(TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()) && !value.contains(
706 TypeUtils.ToscaTagNamesEnum.CONCAT.getElementName());
709 public static String getPropertyJsonStringValue(Object value, String type) {
713 ToscaPropertyType validType = ToscaPropertyType.isValidType(type);
714 if (validType == null
715 || validType == ToscaPropertyType.JSON
716 || validType == ToscaPropertyType.MAP
717 || validType == ToscaPropertyType.LIST
718 || value instanceof Map) {
719 return (new Gson()).toJson(value);
721 return value.toString();
725 * removes from Json map (toscaJson) first element found by name (elementName) note that this method could update the received argument toscaJson
730 public static void removeElementFromJsonMap(Map<String, Object> toscaJson, String elementName) {
731 for (Entry<String, Object> entry : toscaJson.entrySet()) {
732 String key = entry.getKey();
733 Object value = entry.getValue();
734 if (key.equals(elementName)) {
735 toscaJson.remove(elementName);
737 } else if (value instanceof Map) {
738 removeElementFromJsonMap((Map<String, Object>) value, elementName);
743 public enum ResultStatusEnum {
744 ELEMENT_NOT_FOUND, GENERAL_ERROR, OK, INVALID_PROPERTY_DEFAULT_VALUE, INVALID_PROPERTY_TYPE, INVALID_PROPERTY_VALUE, MISSING_ENTRY_SCHEMA_TYPE, INVALID_PROPERTY_NAME, INVALID_ATTRIBUTE_NAME
747 public enum ToscaElementTypeEnum {
748 BOOLEAN, STRING, MAP, LIST, ALL
751 private static class CustomResolver extends Resolver {
754 protected void addImplicitResolvers() {
755 // avoid implicit resolvers for strings that can be interpreted as boolean values
756 addImplicitResolver(Tag.STR, EMPTY, "");
757 addImplicitResolver(Tag.STR, NULL, null);
758 addImplicitResolver(Tag.NULL, NULL, "~nN\0");
759 addImplicitResolver(Tag.NULL, EMPTY, null);
760 addImplicitResolver(Tag.INT, INT, "-+0123456789");
761 addImplicitResolver(Tag.FLOAT, FLOAT, "-+0123456789.");
762 addImplicitResolver(Tag.YAML, YAML, "!&*");
766 private static class YamlLoader extends YamlProcessor {
768 public Yaml getStrictYamlLoader() {
773 public static class Constants {
775 public static final String FIRST_NON_CERTIFIED_VERSION = "0.1";
776 public static final String VENDOR_NAME = "ONAP (Tosca)";
777 public static final String VENDOR_RELEASE = "1.0.0.wd03";
778 public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE = LifecycleStateEnum.CERTIFIED;
779 public static final LifecycleStateEnum NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT = LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT;
780 public static final boolean NORMATIVE_TYPE_HIGHEST_VERSION = true;
781 public static final String ABSTRACT_CATEGORY_NAME = "Generic";
782 public static final String ABSTRACT_SUBCATEGORY = "Abstract";
783 public static final String DEFAULT_ICON = "defaulticon";
784 public static final String INNER_VFC_DESCRIPTION = "Not reusable inner VFC";
785 public static final String USER_DEFINED_RESOURCE_NAMESPACE_PREFIX = "org.openecomp.resource.";
786 public static final String UI_JSON_PAYLOAD_NAME = "payloadName";
787 public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF";
788 public static final String ESCAPED_DOUBLE_QUOTE = "\"";
789 public static final String QUOTE = "'";
790 public static final String VF_DESCRIPTION = "Nested VF in service";
791 public static final String TENANT = "tenant";
793 private Constants() {