From f995db01ee95606b6cded82822a73435ebc190c8 Mon Sep 17 00:00:00 2001 From: vasraz Date: Fri, 9 Dec 2022 12:36:05 +0000 Subject: Add support comparable type constraints for scalar values Signed-off-by: Vasyl Razinkov Change-Id: I57234399f23721506d308dfb8351067845ebe892 Issue-ID: SDC-4305 --- .../sdc/be/model/tosca/ToscaPropertyType.java | 19 +-- .../openecomp/sdc/be/model/tosca/ToscaType.java | 183 +++++++++++++++++++-- .../be/model/tosca/constraints/ConstraintUtil.java | 42 ++--- 3 files changed, 197 insertions(+), 47 deletions(-) (limited to 'catalog-model/src/main') diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaPropertyType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaPropertyType.java index 364dfd33fb..ef08e4d107 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaPropertyType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaPropertyType.java @@ -19,6 +19,7 @@ */ package org.openecomp.sdc.be.model.tosca; +import lombok.Getter; import org.openecomp.sdc.be.model.tosca.converters.BooleanConverter; import org.openecomp.sdc.be.model.tosca.converters.DefaultConverter; import org.openecomp.sdc.be.model.tosca.converters.FloatConverter; @@ -51,6 +52,7 @@ import org.openecomp.sdc.be.model.tosca.validators.StringValidator; * * @author esofer */ +@Getter public enum ToscaPropertyType { // @formatter:off ROOT("tosca.datatypes.Root", null, null, null, true), @@ -62,6 +64,7 @@ public enum ToscaPropertyType { SCALAR_UNIT_SIZE("scalar-unit.size", StringValidator.getInstance(), DefaultConverter.getInstance(), ToscaValueDefaultConverter.getInstance()), SCALAR_UNIT_TIME("scalar-unit.time", StringValidator.getInstance(), DefaultConverter.getInstance(), ToscaValueDefaultConverter.getInstance()), SCALAR_UNIT_FREQUENCY("scalar-unit.frequency", StringValidator.getInstance(), DefaultConverter.getInstance(), ToscaValueDefaultConverter.getInstance()), + SCALAR_UNIT_BITRATE("scalar-unit.bitrate", StringValidator.getInstance(), DefaultConverter.getInstance(), ToscaValueDefaultConverter.getInstance()), RANGE("range", StringValidator.getInstance(), DefaultConverter.getInstance(), ToscaValueDefaultConverter.getInstance()), TIMESTAMP("timestamp", StringValidator.getInstance(), DefaultConverter.getInstance(), ToscaValueDefaultConverter.getInstance()), MAP("map", MapValidator.getInstance(), MapConverter.getInstance(), ToscaMapValueConverter.getInstance()), @@ -123,26 +126,10 @@ public enum ToscaPropertyType { } } - public String getType() { - return type; - } - - public PropertyTypeValidator getValidator() { - return validator; - } - - public PropertyValueConverter getConverter() { - return converter; - } - public boolean isAbstract() { return isAbstract; } - public ToscaValueConverter getValueConverter() { - return valueConverter; - } - @Override public String toString() { return name().toLowerCase(); 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 f59ebe6922..a3daaa0381 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 @@ -27,6 +27,8 @@ import java.text.SimpleDateFormat; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import lombok.AllArgsConstructor; import lombok.Getter; import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil; @@ -53,9 +55,23 @@ public enum ToscaType { SCALAR_UNIT("scalar-unit"), SCALAR_UNIT_SIZE("scalar-unit.size"), SCALAR_UNIT_TIME("scalar-unit.time"), + SCALAR_UNIT_BITRATE("scalar-unit.bitrate"), SCALAR_UNIT_FREQUENCY("scalar-unit.frequency"); // @formatter:on + 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)$"; + 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); + private static final double B_IN_KiB = Math.pow(1024, 1); + private static final double B_IN_TB = Math.pow(1000, 4); + private static final double B_IN_GB = Math.pow(1000, 3); + 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; @@ -94,7 +110,7 @@ public enum ToscaType { return ToscaPropertyType.MAP.getType().equals(type) || ToscaPropertyType.LIST.getType().equals(type); } - public Boolean isValueTypeValid(Object value) { + public boolean isValueTypeValid(Object value) { switch (this) { case BOOLEAN: return value.equals(true) || value.equals(false); @@ -104,9 +120,9 @@ public enum ToscaType { case RANGE: return value instanceof Integer; case STRING: - case SCALAR_UNIT: case SCALAR_UNIT_SIZE: case SCALAR_UNIT_TIME: + case SCALAR_UNIT_BITRATE: case SCALAR_UNIT_FREQUENCY: case TIMESTAMP: case VERSION: @@ -114,6 +130,7 @@ public enum ToscaType { case LIST: case MAP: return true; + case SCALAR_UNIT: default: return false; } @@ -127,11 +144,15 @@ public enum ToscaType { return isFloat(value); case INTEGER: return isInteger(value); - case STRING: - case SCALAR_UNIT: case SCALAR_UNIT_SIZE: + return isScalarUnitSize(value); case SCALAR_UNIT_TIME: + return isScalarUnitTime(value); + case SCALAR_UNIT_BITRATE: + return isScalarUnitBitrate(value); case SCALAR_UNIT_FREQUENCY: + return isScalarUnitFrequency(value); + case STRING: return true; case TIMESTAMP: return TimestampValidator.getInstance().isValid(value, null); @@ -141,6 +162,7 @@ public enum ToscaType { return isList(value); case MAP: return isMap(value); + case SCALAR_UNIT: default: return false; } @@ -189,11 +211,15 @@ public enum ToscaType { public Object convert(String value) { switch (this) { case STRING: - case SCALAR_UNIT: - case SCALAR_UNIT_SIZE: + return value; case SCALAR_UNIT_TIME: + return convertScalarUnitTime(value); + case SCALAR_UNIT_BITRATE: + return convertScalarUnitBitrate(value); + case SCALAR_UNIT_SIZE: + return convertScalarUnitSize(value); case SCALAR_UNIT_FREQUENCY: - return value; + return convertScalarUnitFrequency(value); case BOOLEAN: return Boolean.valueOf(value); case FLOAT: @@ -223,13 +249,150 @@ public enum ToscaType { } catch (ConstraintValueDoNotMatchPropertyTypeException e) { throw new IllegalArgumentException("Value must be a valid Map", e); } + case SCALAR_UNIT: default: return null; } } - @Override - public String toString() { - return name().toLowerCase(); + 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"); + } + } else { + throw new IllegalArgumentException("Value must be a valid scalar-unit.size"); + } + } + + 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"); + } + } else { + throw new IllegalArgumentException("Value must be a valid scalar-unit.time"); + } + } + + 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"); + } + } else { + throw new IllegalArgumentException("Value must be a valid scalar-unit.frequency"); + } + } + + 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"); + } + } else { + throw new IllegalArgumentException("Value must be a valid scalar-unit.bitrate"); + } + } + + private boolean isScalarUnitBitrate(final String value) { + return Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim()).find(); } + + private boolean isScalarUnitSize(final String value) { + return Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim()).find(); + } + + private boolean isScalarUnitTime(final String value) { + return Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim()).find(); + } + + private boolean isScalarUnitFrequency(final String value) { + return Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim()).find(); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java index 1b9b94eb61..61f069a45f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java @@ -26,6 +26,9 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; import org.openecomp.sdc.be.model.tosca.ToscaType; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.slf4j.Logger; @@ -34,13 +37,11 @@ import org.slf4j.LoggerFactory; /** * Utility class to validate constraints types. */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class ConstraintUtil { private static final Logger logger = LoggerFactory.getLogger(ConstraintUtil.class); - private ConstraintUtil() { - } - /** * Validates that the {@link ToscaType} specified is a {@link ToscaType#STRING}. * @@ -59,20 +60,26 @@ public final class ConstraintUtil { * @param propertyType the tosca type to check * @throws ConstraintValueDoNotMatchPropertyTypeException if the property type cannot be compared */ - public static void checkComparableType(ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { + public static void checkComparableType(final ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { // The validity of the value is already assured by us with our ToscaType.convert() method // here we just want to check that the constraint is not used on unsupported type as boolean - switch (propertyType) { + final ToscaType toscaType = ToscaType.getToscaType(propertyType.getType()); + switch (toscaType) { case FLOAT: case INTEGER: case TIMESTAMP: case VERSION: case STRING: + case SCALAR_UNIT_SIZE: + case SCALAR_UNIT_TIME: + case SCALAR_UNIT_BITRATE: + case SCALAR_UNIT_FREQUENCY: break; case BOOLEAN: - throw new ConstraintValueDoNotMatchPropertyTypeException("Constraint is invalid for property type <" + propertyType.toString() + ">"); + case SCALAR_UNIT: + throw new ConstraintValueDoNotMatchPropertyTypeException("Constraint is invalid for property type <" + propertyType.getType() + ">"); default: - throw new ConstraintValueDoNotMatchPropertyTypeException("Invalid property type <" + propertyType.toString() + ">"); + throw new ConstraintValueDoNotMatchPropertyTypeException("Invalid property type <" + propertyType.getType() + ">"); } } @@ -86,7 +93,7 @@ public final class ConstraintUtil { */ @SuppressWarnings("rawtypes") public static Comparable convertToComparable(ToscaType propertyType, String value) { - Object comparableObj = propertyType.convert(value); + final Object comparableObj = propertyType.convert(value); if (!(comparableObj instanceof Comparable)) { throw new IllegalArgumentException("Try to convert a value of a type which is not comparable [" + propertyType + "] to Comparable"); } else { @@ -95,9 +102,8 @@ public final class ConstraintUtil { } public static ConstraintInformation getConstraintInformation(Object constraint) throws IntrospectionException { - PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(constraint.getClass()).getPropertyDescriptors(); PropertyDescriptor firstDescriptor = null; - for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { + for (final PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(constraint.getClass()).getPropertyDescriptors()) { if (propertyDescriptor.getReadMethod() != null && propertyDescriptor.getWriteMethod() != null) { firstDescriptor = propertyDescriptor; break; @@ -125,18 +131,12 @@ public final class ConstraintUtil { return objectMap; } + @AllArgsConstructor public static class ConstraintInformation { - private String name; - private Object reference; - private String value; - private String type; - - public ConstraintInformation(String name, Object reference, String value, String type) { - this.name = name; - this.reference = reference; - this.value = value; - this.type = type; - } + private final String name; + private final Object reference; + private final String value; + private final String type; } } -- cgit 1.2.3-korg