From 5357edd8fb443613f4be4e8a30b03f2a7134e61d Mon Sep 17 00:00:00 2001 From: vasraz Date: Thu, 15 Dec 2022 12:55:10 +0000 Subject: [PATCH] Improve message for constraints different errors Signed-off-by: Vasyl Razinkov Change-Id: I8babb10de4f0f25a49998fda077a7bb2554f86ba Issue-ID: SDC-4305 --- .../PropertyValueConstraintValidationUtil.java | 33 ++- .../openecomp/sdc/be/model/tosca/ToscaType.java | 275 ++++++++++++--------- .../AbstractComparablePropertyConstraint.java | 3 +- .../constraints/AbstractPropertyConstraint.java | 5 +- .../execute/sanity/ModelToscaTypeImportTest.java | 47 ++-- .../sanity/ServiceTemplateDesignUiTests.java | 67 ++--- 6 files changed, 256 insertions(+), 174 deletions(-) diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtil.java b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtil.java index 0c8a20c36f..6aa59e4844 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtil.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtil.java @@ -22,7 +22,6 @@ import fj.data.Either; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -91,7 +90,8 @@ public class PropertyValueConstraintValidationUtil { } private void evaluatePropertyTypeForConstraintValidation(PropertyDefinition propertyDefinition) { - if (propertyDefinition == null || propertyDefinition.getType() == null || !dataTypeDefinitionCache.containsKey(propertyDefinition.getType())) { + if (propertyDefinition == null || propertyDefinition.getType() == null || !dataTypeDefinitionCache.containsKey( + propertyDefinition.getType())) { errorMessages.add("\nUnsupported datatype found for property " + getCompletePropertyName(propertyDefinition)); return; } @@ -140,13 +140,14 @@ public class PropertyValueConstraintValidationUtil { propertyConstraint.validate(toscaType, propertyDefinition.getValue()); } catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) { errorMessages.add(propertyConstraint.getErrorMessage(toscaType, exception, getCompletePropertyName(propertyDefinition))); + } catch (IllegalArgumentException ie) { + errorMessages.add(ie.getMessage()); } } } else if (isPropertyNotMappedAsInput(propertyDefinition) && ToscaType.isPrimitiveType(propertyDefinition.getType()) && !toscaType .isValidValue(propertyDefinition.getValue())) { - errorMessages.add(String - .format("\nUnsupported value provided for %s property supported value " + "type is %s.", getCompletePropertyName(propertyDefinition), - toscaType.getType())); + errorMessages.add(String.format("Unsupported value provided for %s property supported value type is %s.", + getCompletePropertyName(propertyDefinition), toscaType.getType())); } } @@ -184,7 +185,7 @@ public class PropertyValueConstraintValidationUtil { private void evaluateRegularComplexType(PropertyDefinition propertyDefinition, PropertyDefinition prop, Map valueMap) { try { PropertyDefinition newPropertyWithValue; - if (valueMap.containsKey(prop.getName()) ) { + if (valueMap.containsKey(prop.getName())) { if (ToscaType.isPrimitiveType(prop.getType())) { newPropertyWithValue = copyPropertyWithNewValue(prop, String.valueOf(valueMap.get(prop.getName()))); if (isPropertyToEvaluate(newPropertyWithValue)) { @@ -218,7 +219,8 @@ public class PropertyValueConstraintValidationUtil { return StringUtils.isNotEmpty(propertyDefinition.getValue()) && !"null".equals(propertyDefinition.getValue()); } else if (ToscaType.LIST == ToscaType.isValidType(propertyDefinition.getType())) { - Collection list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {}); + Collection list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() { + }); return CollectionUtils.isNotEmpty(list); } else { Map valueMap = MapUtils @@ -265,10 +267,12 @@ public class PropertyValueConstraintValidationUtil { .forEach(propertyConstraint -> { try { if (ToscaType.LIST == toscaPropertyType1) { - Collection list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {}); + Collection list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() { + }); propertyConstraint.validate(list); } else if (ToscaType.MAP == toscaPropertyType1) { - final Map map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {}); + final Map map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() { + }); propertyConstraint.validate(map); } } catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) { @@ -279,7 +283,7 @@ public class PropertyValueConstraintValidationUtil { } private boolean isACollectionConstraint(PropertyConstraint constraint) { - if (constraint instanceof MaxLengthConstraint){ + if (constraint instanceof MaxLengthConstraint) { return true; } if (constraint instanceof MinLengthConstraint) { @@ -293,7 +297,8 @@ public class PropertyValueConstraintValidationUtil { if (propertyDefinition.getSchemaType() == null) { propertyDefinition.setSchema(createStringSchema()); } - Collection list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {}); + Collection list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() { + }); evaluateCollectionType(propertyDefinition, list); } catch (ConstraintValueDoNotMatchPropertyTypeException e) { logger.debug(e.getMessage(), e); @@ -314,7 +319,8 @@ public class PropertyValueConstraintValidationUtil { if (propertyDefinition.getSchemaType() == null) { propertyDefinition.setSchema(createStringSchema()); } - final Map map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() {}); + final Map map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), new TypeReference<>() { + }); evaluateCollectionType(propertyDefinition, map.values()); } catch (ConstraintValueDoNotMatchPropertyTypeException e) { logger.debug(e.getMessage(), e); @@ -336,7 +342,8 @@ public class PropertyValueConstraintValidationUtil { final String schemaType = propertyDefinition.getSchemaType(); for (final Object value : valueList) { try { - final PropertyDefinition propertyCopyWithNewValue = copyPropertyWithNewValue(propertyDefinition, objectMapper.writeValueAsString(value)); + final PropertyDefinition propertyCopyWithNewValue = copyPropertyWithNewValue(propertyDefinition, + objectMapper.writeValueAsString(value)); if (ToscaType.isPrimitiveType(schemaType)) { evaluateCollectionPrimitiveSchemaType(propertyCopyWithNewValue, schemaType); } else if (ToscaType.isCollectionType(schemaType)) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java index a3daaa0381..1f942a9352 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java @@ -24,11 +24,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import lombok.AllArgsConstructor; import lombok.Getter; import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil; @@ -58,11 +60,19 @@ public enum ToscaType { SCALAR_UNIT_BITRATE("scalar-unit.bitrate"), SCALAR_UNIT_FREQUENCY("scalar-unit.frequency"); // @formatter:on + @Getter + private final String type; - private static final String SCALAR_UNIT_BITRATE_PATTERN = "(^[0-9]+\\.?[0-9]*) ?([TtGgMmKk]?i?[Bb]ps)$"; - private static final String SCALAR_UNIT_TIME_PATTERN = "(^[0-9]+\\.?[0-9]*) ?([mun]?[dhms])$"; - private static final String SCALAR_UNIT_SIZE_PATTERN = "(^[0-9]+\\.?[0-9]*) ?([TtGgMmKk]?i?[Bb])$"; - private static final String SCALAR_UNIT_FREQUENCY_PATTERN = "(^[0-9]+\\.?[0-9]*) ?([kMG]?Hz)$"; + // @formatter:off + private static final List SCALAR_UNIT_BITRATE_VALID_UNITS = Arrays.asList("TiBps", "TBps", "GiBps", "GBps", "MiBps", "MBps", "KiBps", "KBps", "Bps", "Tibps", "Tbps", "Gibps", "Gbps", "Mibps", "Mbps", "Kibps", "Kbps", "bps"); + private static final String SCALAR_UNIT_BITRATE_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_BITRATE_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$"; + private static final List SCALAR_UNIT_TIME_VALID_UNITS = Arrays.asList("d", "h", "m", "s", "ms", "us", "ns"); + private static final String SCALAR_UNIT_TIME_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_TIME_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$"; + private static final List SCALAR_UNIT_SIZE_VALID_UNITS = Arrays.asList("TiB", "TB", "GiB", "GB", "MiB", "MB", "KiB", "kB", "B"); + private static final String SCALAR_UNIT_SIZE_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_SIZE_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$"; + private static final List SCALAR_UNIT_FREQUENCY_VALID_UNITS = Arrays.asList("GHz", "MHz", "kHz", "Hz"); + private static final String SCALAR_UNIT_FREQUENCY_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_FREQUENCY_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$"; + // @formatter:on private static final double B_IN_TiB = Math.pow(1024, 4); private static final double B_IN_GiB = Math.pow(1024, 3); private static final double B_IN_MiB = Math.pow(1024, 2); @@ -72,9 +82,6 @@ public enum ToscaType { private static final double B_IN_MB = Math.pow(1000, 2); private static final double B_IN_KB = Math.pow(1000, 1); - @Getter - private final String type; - public static ToscaType getToscaType(String typeName) { if (typeName == null) { return null; @@ -208,6 +215,18 @@ public enum ToscaType { return true; } + public boolean isScalarUnit() { + switch (this) { + case SCALAR_UNIT_TIME: + case SCALAR_UNIT_SIZE: + case SCALAR_UNIT_BITRATE: + case SCALAR_UNIT_FREQUENCY: + return true; + default: + return false; + } + } + public Object convert(String value) { switch (this) { case STRING: @@ -256,143 +275,177 @@ public enum ToscaType { } private Long convertScalarUnitSize(final String value) { - final Matcher matcher = Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim()); - if (matcher.find()) { - switch (matcher.group(2)) { - case "TiB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TiB); - case "TB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TB); - case "GiB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GiB); - case "GB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GB); - case "MiB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MiB); - case "MB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MB); - case "KiB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KiB); - case "kB": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KB); - case "B": - return (long) (Double.parseDouble(matcher.group(1))); - default: - throw new IllegalArgumentException("Value must be a valid scalar-unit.size"); + if (isScalarUnitSize(value)) { + final Matcher matcher = Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim()); + if (matcher.find()) { + switch (matcher.group(2)) { + case "TiB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TiB); + case "TB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TB); + case "GiB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GiB); + case "GB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GB); + case "MiB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MiB); + case "MB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MB); + case "KiB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KiB); + case "kB": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KB); + case "B": + return (long) (Double.parseDouble(matcher.group(1))); + default: + throw new IllegalArgumentException("Value must be a valid scalar-unit.size"); + } + } else { + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.size': " + SCALAR_UNIT_SIZE_VALID_UNITS); } } else { - throw new IllegalArgumentException("Value must be a valid scalar-unit.size"); + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.size': " + SCALAR_UNIT_SIZE_VALID_UNITS); } } private Long convertScalarUnitTime(final String value) { - final Matcher matcher = Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim()); - if (matcher.find()) { - switch (matcher.group(2)) { - case "d": - return (long) (Double.parseDouble(matcher.group(1)) * 24 * 60 * 60 * 1_000_000_000L); // 24hours * 60minutes * 60seconds - case "h": - return (long) (Double.parseDouble(matcher.group(1)) * 60 * 60 * 1_000_000_000L); // 60minutes * 60seconds - case "m": - return (long) (Double.parseDouble(matcher.group(1)) * 60 * 1_000_000_000L); // 60seconds - case "s": - return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000_000L); - case "ms": - return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000L); - case "us": - return (long) (Double.parseDouble(matcher.group(1)) * 1_000L); - case "ns": - return (long) (Double.parseDouble(matcher.group(1))); - default: - throw new IllegalArgumentException("Value must be a valid scalar-unit.time"); + if (isScalarUnitTime(value)) { + final Matcher matcher = Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim()); + if (matcher.find()) { + switch (matcher.group(2)) { + case "d": + return (long) (Double.parseDouble(matcher.group(1)) * 24 * 60 * 60 * 1_000_000_000L); // 24hours * 60minutes * 60seconds + case "h": + return (long) (Double.parseDouble(matcher.group(1)) * 60 * 60 * 1_000_000_000L); // 60minutes * 60seconds + case "m": + return (long) (Double.parseDouble(matcher.group(1)) * 60 * 1_000_000_000L); // 60seconds + case "s": + return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000_000L); + case "ms": + return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000L); + case "us": + return (long) (Double.parseDouble(matcher.group(1)) * 1_000L); + case "ns": + return (long) (Double.parseDouble(matcher.group(1))); + default: + throw new IllegalArgumentException("Value must be a valid scalar-unit.time"); + } + } else { + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.time':" + SCALAR_UNIT_TIME_VALID_UNITS); } } else { - throw new IllegalArgumentException("Value must be a valid scalar-unit.time"); + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.time':" + SCALAR_UNIT_TIME_VALID_UNITS); } } private Long convertScalarUnitFrequency(final String value) { - final Matcher matcher = Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim()); - if (matcher.find()) { - switch (matcher.group(2)) { - case "GHz": - return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000_000L); - case "MHz": - return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000L); - case "kHz": - return (long) (Double.parseDouble(matcher.group(1)) * 1_000L); - case "Hz": - return (long) (Double.parseDouble(matcher.group(1))); - default: - throw new IllegalArgumentException("Value must be a valid scalar-unit.frequency"); + if (isScalarUnitFrequency(value)) { + final Matcher matcher = Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim()); + if (matcher.find()) { + switch (matcher.group(2)) { + case "GHz": + return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000_000L); + case "MHz": + return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000L); + case "kHz": + return (long) (Double.parseDouble(matcher.group(1)) * 1_000L); + case "Hz": + return (long) (Double.parseDouble(matcher.group(1))); + default: + throw new IllegalArgumentException("Value must be a valid scalar-unit.frequency"); + } + } else { + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.frequency':" + SCALAR_UNIT_FREQUENCY_VALID_UNITS); } } else { - throw new IllegalArgumentException("Value must be a valid scalar-unit.frequency"); + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.frequency':" + SCALAR_UNIT_FREQUENCY_VALID_UNITS); } } private Long convertScalarUnitBitrate(final String value) { - final Matcher matcher = Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim()); - if (matcher.find()) { - switch (matcher.group(2)) { - case "TiBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_TiB); - case "TBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_TB); - case "GiBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_GiB); - case "GBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_GB); - case "MiBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_MiB); - case "MBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_MB); - case "KiBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_KiB); - case "KBps": - return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_KB); - case "Bps": - return (long) (Double.parseDouble(matcher.group(1)) * 8); - case "Tibps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TiB); - case "Tbps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TB); - case "Gibps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GiB); - case "Gbps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GB); - case "Mibps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MiB); - case "Mbps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MB); - case "Kibps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KiB); - case "Kbps": - return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KB); - case "bps": - return (long) (Double.parseDouble(matcher.group(1))); - default: - throw new IllegalArgumentException("Value must be a valid scalar-unit.bitrate"); + if (isScalarUnitBitrate(value)) { + final Matcher matcher = Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim()); + if (matcher.find()) { + switch (matcher.group(2)) { + case "TiBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_TiB); + case "TBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_TB); + case "GiBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_GiB); + case "GBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_GB); + case "MiBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_MiB); + case "MBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_MB); + case "KiBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_KiB); + case "KBps": + return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_KB); + case "Bps": + return (long) (Double.parseDouble(matcher.group(1)) * 8); + case "Tibps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TiB); + case "Tbps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TB); + case "Gibps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GiB); + case "Gbps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GB); + case "Mibps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MiB); + case "Mbps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MB); + case "Kibps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KiB); + case "Kbps": + return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KB); + case "bps": + return (long) (Double.parseDouble(matcher.group(1))); + default: + throw new IllegalArgumentException("Value must be a valid scalar-unit.bitrate"); + } + } else { + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.bitrate':" + SCALAR_UNIT_BITRATE_VALID_UNITS); } } else { - throw new IllegalArgumentException("Value must be a valid scalar-unit.bitrate"); + throw new IllegalArgumentException("Value must be a valid 'scalar-unit.bitrate':" + SCALAR_UNIT_BITRATE_VALID_UNITS); } } private boolean isScalarUnitBitrate(final String value) { - return Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim()).find(); + final Matcher matcher = Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim()); + return matcher.find() && SCALAR_UNIT_BITRATE_VALID_UNITS.contains(matcher.group(2)); } private boolean isScalarUnitSize(final String value) { - return Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim()).find(); + final Matcher matcher = Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim()); + return matcher.find() && SCALAR_UNIT_SIZE_VALID_UNITS.contains(matcher.group(2)); } private boolean isScalarUnitTime(final String value) { - return Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim()).find(); + final Matcher matcher = Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim()); + return matcher.find() && SCALAR_UNIT_TIME_VALID_UNITS.contains(matcher.group(2)); } private boolean isScalarUnitFrequency(final String value) { - return Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim()).find(); + final Matcher matcher = Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim()); + return matcher.find() && SCALAR_UNIT_FREQUENCY_VALID_UNITS.contains(matcher.group(2)); } + public String getValidValues() { + switch (this) { + case SCALAR_UNIT_TIME: + return String.valueOf(SCALAR_UNIT_TIME_VALID_UNITS); + case SCALAR_UNIT_SIZE: + return String.valueOf(SCALAR_UNIT_SIZE_VALID_UNITS); + case SCALAR_UNIT_BITRATE: + return String.valueOf(SCALAR_UNIT_BITRATE_VALID_UNITS); + case SCALAR_UNIT_FREQUENCY: + return String.valueOf(SCALAR_UNIT_FREQUENCY_VALID_UNITS); + default: + return ""; + } + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractComparablePropertyConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractComparablePropertyConstraint.java index 4a8c742de9..6182eeb3b1 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractComparablePropertyConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractComparablePropertyConstraint.java @@ -42,7 +42,8 @@ public abstract class AbstractComparablePropertyConstraint extends AbstractPrope } else { // Invalid value throw exception throw new ConstraintValueDoNotMatchPropertyTypeException( - "The value [" + rawTextValue + "] is not valid for the type [" + propertyType + "]"); + "The value [" + rawTextValue + "] is not valid for the type [" + propertyType + "]." + + (propertyType.isScalarUnit() ? " Valid values are " + propertyType.getValidValues() : "")); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java index ef94baf33b..43bed0af67 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java @@ -35,7 +35,7 @@ public abstract class AbstractPropertyConstraint implements PropertyConstraint { public void validate(ToscaType toscaType, String propertyTextValue) throws ConstraintViolationException { try { validate(toscaType.convert(propertyTextValue)); - } catch (IllegalArgumentException | ApplicationVersionException e) { + } catch (ApplicationVersionException e) { throw new ConstraintViolationException("String value [" + propertyTextValue + "] is not valid for type [" + toscaType + "]", e); } } @@ -45,6 +45,9 @@ public abstract class AbstractPropertyConstraint implements PropertyConstraint { if (e instanceof ConstraintViolationException) { return String.format(errorMessage, propertyName, propertyValue.length == 1 ? propertyValue[0] : Arrays.toString(propertyValue)); } + if (e instanceof ConstraintValueDoNotMatchPropertyTypeException) { + return e.getMessage(); + } return String.format(INVALID_VALUE_ERROR_MESSAGE, propertyName, toscaType.getType()); } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ModelToscaTypeImportTest.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ModelToscaTypeImportTest.java index a07c5835e0..ed6fed81d7 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ModelToscaTypeImportTest.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ModelToscaTypeImportTest.java @@ -57,6 +57,9 @@ import org.onap.sdc.frontend.ci.tests.flow.DownloadCsarArtifactFlow; import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException; import org.onap.sdc.frontend.ci.tests.pages.ComponentPage; import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage; +import org.onap.sdc.frontend.ci.tests.pages.ServiceComponentPage; +import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage; +import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage; import org.onap.sdc.frontend.ci.tests.pages.home.HomePage; import org.onap.sdc.frontend.ci.tests.utilities.FileHandling; import org.openqa.selenium.WebDriver; @@ -101,51 +104,44 @@ public class ModelToscaTypeImportTest extends SetupCDTest { @Test(dependsOnMethods = "addNodeType") public void verifyToscaTypesIncludedInCsar() throws Exception { - final var vf = new ResourceCreateData(); - vf.setRandomName(ElementFactory.getResourcePrefix() + "-VF"); - vf.setCategory(ResourceCategoryEnum.GENERIC_ABSTRACT.getSubCategory()); - vf.setTagList(Arrays.asList(vf.getName())); - vf.setDescription("Test"); - vf.setVendorName("EST"); - vf.setVendorRelease("2.5.1"); - vf.setVendorModelNumber("0001"); - vf.setModel(ModelName.ETSI_SOL001_v2_5_1.getName()); + final ResourceCreateData vf = new ResourceCreateData(); + fillVfMetaData(vf); - final var createVfFlow = new CreateVfFlow(webDriver, vf); + final CreateVfFlow createVfFlow = new CreateVfFlow(webDriver, vf); createVfFlow.run(homePage); - ComponentPage resourceCreatePage = createVfFlow.getLandedPage() - .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ResourceCreatePage")); + ComponentPage resourceCreatePage = + createVfFlow.getLandedPage().orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ResourceCreatePage")); resourceCreatePage.isLoaded(); - final var parentComponent = new ComponentData(); + final ComponentData parentComponent = new ComponentData(); parentComponent.setName(vf.getName()); parentComponent.setVersion("0.1"); parentComponent.setComponentType(ComponentType.RESOURCE); - final var addComponent = new ComponentData(); + final ComponentData addComponent = new ComponentData(); addComponent.setName("Network"); addComponent.setVersion("1.0"); addComponent.setComponentType(ComponentType.RESOURCE); - final var compositionPage = resourceCreatePage.goToComposition(); + final CompositionPage compositionPage = resourceCreatePage.goToComposition(); compositionPage.isLoaded(); - final var addNodeToCompositionFlow = new AddNodeToCompositionFlow(webDriver, parentComponent, addComponent); + final AddNodeToCompositionFlow addNodeToCompositionFlow = new AddNodeToCompositionFlow(webDriver, parentComponent, addComponent); addNodeToCompositionFlow.run(compositionPage); compositionPage.isLoaded(); - final var serviceComponentPage = compositionPage.goToServiceGeneral(); + final ServiceComponentPage serviceComponentPage = compositionPage.goToServiceGeneral(); final Map propertyMap = new HashMap<>(); propertyMap.put("AdditionalServiceData", ADDITIONAL_SERVICE_DATA); resourceCreatePage = addProperty(serviceComponentPage, propertyMap); - final var downloadCsarArtifactFlow = new DownloadCsarArtifactFlow(webDriver); + final DownloadCsarArtifactFlow downloadCsarArtifactFlow = new DownloadCsarArtifactFlow(webDriver); downloadCsarArtifactFlow.setWaitBeforeGetTheFile(5L); downloadCsarArtifactFlow.run(resourceCreatePage); - final var toscaArtifactsPage = downloadCsarArtifactFlow.getLandedPage() + final ToscaArtifactsPage toscaArtifactsPage = downloadCsarArtifactFlow.getLandedPage() .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ToscaArtifactsPage")); assertTrue(toscaArtifactsPage.getDownloadedArtifactList().size() > 0, "No artifact download was found"); toscaArtifactsPage.getDownloadedArtifactList().get(0); - final var downloadFolderPath = getConfig().getDownloadAutomationFolder(); + final String downloadFolderPath = getConfig().getDownloadAutomationFolder(); final Map csarFiles = FileHandling.getFilesFromZip(downloadFolderPath, toscaArtifactsPage.getDownloadedArtifactList().get(0)); assertEquals(8, csarFiles.size()); @@ -158,6 +154,17 @@ public class ModelToscaTypeImportTest extends SetupCDTest { assertTrue(csarFiles.values().stream().filter(bytes -> new String(bytes).contains(ADDITIONAL_SERVICE_DATA)).findAny().isPresent()); } + private void fillVfMetaData(final ResourceCreateData vf) { + vf.setRandomName(ElementFactory.getResourcePrefix() + "-VF"); + vf.setCategory(ResourceCategoryEnum.GENERIC_ABSTRACT.getSubCategory()); + vf.setTagList(Arrays.asList(vf.getName())); + vf.setDescription("Test"); + vf.setVendorName("EST"); + vf.setVendorRelease("2.5.1"); + vf.setVendorModelNumber("0001"); + vf.setModel(ModelName.ETSI_SOL001_v2_5_1.getName()); + } + private ComponentPage addProperty(ComponentPage serviceComponentPage, final Map propertyMap) { final AddComponentPropertyFlow addComponentPropertyFlow = new AddComponentPropertyFlow(webDriver, propertyMap); serviceComponentPage.isLoaded(); diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java index 706a6663d8..3294523de1 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ServiceTemplateDesignUiTests.java @@ -34,6 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import com.aventstack.extentreports.Status; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -43,7 +44,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.stream.Collectors; - import org.onap.sdc.backend.ci.tests.data.providers.OnboardingDataProviders; import org.onap.sdc.backend.ci.tests.datatypes.enums.ComponentType; import org.onap.sdc.backend.ci.tests.datatypes.enums.ResourceCategoryEnum; @@ -65,8 +65,8 @@ import org.onap.sdc.frontend.ci.tests.flow.CreateDirectiveNodeFilterFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateSubstitutionFilterFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateVfFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateVfcFlow; -import org.onap.sdc.frontend.ci.tests.flow.DownloadToscaTemplateFlow; import org.onap.sdc.frontend.ci.tests.flow.DownloadCsarArtifactFlow; +import org.onap.sdc.frontend.ci.tests.flow.DownloadToscaTemplateFlow; import org.onap.sdc.frontend.ci.tests.flow.EditComponentPropertiesFlow; import org.onap.sdc.frontend.ci.tests.flow.composition.CreateRelationshipFlow; import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException; @@ -78,9 +78,9 @@ import org.onap.sdc.frontend.ci.tests.pages.ResourcePropertiesPage; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionDetailSideBarComponent; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionDetailSideBarComponent.CompositionDetailTabName; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionInformationTab; -import org.onap.sdc.frontend.ci.tests.pages.component.workspace.InterfaceDefinitionOperationsModal; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionInterfaceOperationsTab; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage; +import org.onap.sdc.frontend.ci.tests.pages.component.workspace.InterfaceDefinitionOperationsModal; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.InterfaceDefinitionOperationsModal.InterfaceOperationsData.InputData; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.RelationshipWizardInterfaceOperation.InterfaceOperationsData; import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage; @@ -94,8 +94,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.yaml.snakeyaml.Yaml; -import com.aventstack.extentreports.Status; - public class ServiceTemplateDesignUiTests extends SetupCDTest { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTemplateDesignUiTests.class); @@ -142,7 +140,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { @Test(dependsOnMethods = "importAndCertifyVfc") public void createBaseService() { final CreateVfFlow createVfFlow = createVF(); - resourceCreatePage = createVfFlow.getLandedPage() + resourceCreatePage = createVfFlow.getLandedPage() .orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a ResourceCreatePage")); resourceCreatePage.isLoaded(); } @@ -291,7 +289,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { final Map propertyNamesAndTypes = vfcPropertiesPage.getPropertyNamesAndTypes(); final List propertyNames = propertyNamesAndTypes.keySet().stream().collect(Collectors.toList()); final ServiceDependencyProperty serviceDependencyProperty = - new ServiceDependencyProperty(propertyNames.get(0), propertyNamesAndTypes.get(propertyNames.get(0)), value, operator); + new ServiceDependencyProperty(propertyNames.get(0), propertyNamesAndTypes.get(propertyNames.get(0)), value, operator); homePage.getTopNavComponent().clickOnHome(); homePage.isLoaded(); @@ -303,7 +301,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { compositionPage.selectNode(vfcNameInComposition); final CreateDirectiveNodeFilterFlow createDirectiveNodeFilterFlow = - new CreateDirectiveNodeFilterFlow(webDriver, 2, serviceDependencyProperty); + new CreateDirectiveNodeFilterFlow(webDriver, 2, serviceDependencyProperty); createDirectiveNodeFilterFlow.run(componentPage); verifyAvailableDirectiveTypes(createDirectiveNodeFilterFlow.getDirectiveOptions()); @@ -373,12 +371,14 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Updates an Interface operation from a selected Node (VFC) - * @param compositionPage the composition page + * + * @param compositionPage the composition page * @param interfaceOperationsData the interface definition * @throws IOException */ private void updateInterfaceOperation(final CompositionPage compositionPage, - final InterfaceDefinitionOperationsModal.InterfaceOperationsData interfaceOperationsData) throws IOException { + final InterfaceDefinitionOperationsModal.InterfaceOperationsData interfaceOperationsData) + throws IOException { final CompositionDetailSideBarComponent detailSideBar = compositionPage.getDetailSideBar(); detailSideBar.isLoaded(); final CompositionInterfaceOperationsTab compositionInterfaceOperationsTab = @@ -404,7 +404,8 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Validates if the Updated Interface Operation has the expected values - * @param detailSideBar The composition Page + * + * @param detailSideBar The composition Page * @param interfaceOperationsData The Updated Interface Definition */ private void validateUpdatedInterfaceOperation(final CompositionDetailSideBarComponent detailSideBar, @@ -431,7 +432,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { } private void verifyToscaTemplateHasUpdatedInterfaceOperation(final Map toscaTemplateYaml, - final InterfaceDefinitionOperationsModal.InterfaceOperationsData interfaceOperationsData) { + final InterfaceDefinitionOperationsModal.InterfaceOperationsData interfaceOperationsData) { assertNotNull(toscaTemplateYaml, "No contents in TOSCA Template"); final Map topologyTemplateTosca = getMapEntry((Map) toscaTemplateYaml, "topology_template"); @@ -482,14 +483,14 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { return loadYamlObject(filesFromZip.get(resourceEntryOpt.get())); } - private void declareInputToBaseService(ResourcePropertiesAssignmentPage propertiesAssignmentPage, String propertyName){ + private void declareInputToBaseService(ResourcePropertiesAssignmentPage propertiesAssignmentPage, String propertyName) { propertiesAssignmentPage.selectProperty(propertyName); propertiesAssignmentPage.clickOnDeclareInput(); propertiesAssignmentPage.clickInputTab(propertyName); propertiesAssignmentPage.isInputPresent(vfResourceCreateData.getName() + "_" + propertyName); } - private void declareInputToInstanceProperties(ResourcePropertiesAssignmentPage propertiesAssignmentPage, String propertyName){ + private void declareInputToInstanceProperties(ResourcePropertiesAssignmentPage propertiesAssignmentPage, String propertyName) { propertiesAssignmentPage.selectPropertiesTab(); propertiesAssignmentPage.loadCompositionTab(); propertiesAssignmentPage.loadComponentInstanceProperties(vfcs.get(0).getName().concat(" 0")); @@ -588,11 +589,12 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Creates a DependsOn relationship between the imported VFCs - * @param compositionPage Composition Page + * + * @param compositionPage Composition Page * @param fromComponentInstanceName VFC - Network Function - * @param fromCapability Node Capability - * @param toComponentInstanceName VFC - Network Service - * @param toRequirement Node Requirement + * @param fromCapability Node Capability + * @param toComponentInstanceName VFC - Network Service + * @param toRequirement Node Requirement */ private void createRelationship(final CompositionPage compositionPage, final String fromComponentInstanceName, final String fromCapability, final String toComponentInstanceName, final String toRequirement) { @@ -608,6 +610,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Adds a property to the base service + * * @param propertyMap map of properties to be added */ private void addProperty(final Map propertyMap) { @@ -619,6 +622,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Adds a input to the base service + * * @param inputMap map of inputs to be added */ private void addInput(final Map inputMap) { @@ -630,6 +634,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Edits a property to add a value + * * @param propertyMap map of properties to be edited */ private ComponentPage addValueToProperty(final Map propertyMap) { @@ -639,6 +644,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Downloads and verifies the generated tosca templates. + * * @param componentPage the component page * @throws UnzipException */ @@ -648,8 +654,9 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Downloads and verifies if the generated Tosca template contains the expected properties. - * @throws UnzipException + * * @param componentPage + * @throws UnzipException */ private void downloadAndVerifyCsarPackageAfterAddProperty(final ComponentPage componentPage) throws UnzipException { verifyPropertiesOnGeneratedTemplate(downloadCsarPackage(componentPage)); @@ -665,6 +672,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Downloads the generated CSAR package. + * * @param componentPage the component page * @return the Downloaded Tosca CSAR file */ @@ -677,6 +685,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Verifies if the generated Tosca template contains the expected properties. + * * @param downloadedCsarName the downloaded csar file name * @throws UnzipException */ @@ -867,7 +876,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { stringMap.put("PropMapKey2", "PropMapValue2"); stringMap.put("PropMapKey3", "PropMapValue3"); propertyMap.put("property5", stringMap); - propertyMap.put("property6", "500 GB"); + propertyMap.put("property6", "500GB"); return propertyMap; } @@ -912,6 +921,7 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { /** * Downloads Tosca Template file + * * @return the tosca template yaml file * @throws Exception */ @@ -954,8 +964,8 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { assertNotNull(availableDirectiveTypes, "Expected list of available Directive Types, but recieved null"); Arrays.asList(DirectiveType.values()).forEach(directiveType -> { assertTrue(availableDirectiveTypes.contains(directiveType.getName()) - , String.format("Expected directive %s to be availabe in UI options %s" - , directiveType.getName(), availableDirectiveTypes.toString())); + , String.format("Expected directive %s to be availabe in UI options %s" + , directiveType.getName(), availableDirectiveTypes.toString())); }); ExtentTestActions.log(Status.PASS, "All expected directive types are available for selection"); } @@ -964,26 +974,27 @@ public class ServiceTemplateDesignUiTests extends SetupCDTest { assertEquals(propertyNameOptions.size(), propertyNames.size(), "Mismatch in the number of properties available for selection"); propertyNames.forEach(name -> { assertNotEquals(false, propertyNameOptions.remove(name) - , String.format("Expected property %s not found in UI Select element", name)); + , String.format("Expected property %s not found in UI Select element", name)); }); ExtentTestActions.log(Status.PASS, "All expected properties are available for selection"); } - private void verifyToscaTemplateHasDirectiveNodeFilter(final Map yaml, ServiceDependencyProperty nodeFilterProperty, String nodeTemplateName) { + private void verifyToscaTemplateHasDirectiveNodeFilter(final Map yaml, ServiceDependencyProperty nodeFilterProperty, + String nodeTemplateName) { assertNotNull(yaml, "Tosca Template Yaml is not expected to be empty"); final List nodeFilters = (List) getDirectiveNodeFilterFromYaml(yaml, nodeTemplateName).get("properties"); final Map nodeFilter = (Map) nodeFilters.stream() - .filter(yamlNodeFilter -> ((Map) yamlNodeFilter).containsKey(nodeFilterProperty.getName())).findAny().get(); + .filter(yamlNodeFilter -> ((Map) yamlNodeFilter).containsKey(nodeFilterProperty.getName())).findAny().get(); assertNotNull(nodeFilter, "Added directive node filter not found in TOSCA Template"); final Map nodeFilterValue = (Map) ((List) nodeFilter.get(nodeFilterProperty.getName())).get(0); assertTrue(nodeFilterValue.containsValue(nodeFilterProperty.getValue()) - , "Invalid value for added directive node filter found in TOSCA Template"); + , "Invalid value for added directive node filter found in TOSCA Template"); assertTrue(nodeFilterValue.containsKey(nodeFilterProperty.getLogicalOperator().getName()) - , "Invalid logical operator for added directive node filter found in TOSCA Template"); + , "Invalid logical operator for added directive node filter found in TOSCA Template"); } - private Map getDirectiveNodeFilterFromYaml(final Map yaml, String nodeTemplateName) { + private Map getDirectiveNodeFilterFromYaml(final Map yaml, String nodeTemplateName) { final Map topology = (Map) yaml.get("topology_template"); final Map nodeTemplates = (Map) topology.get("node_templates"); final Map resourceNode = (Map) nodeTemplates.get(nodeTemplateName); -- 2.16.6