diff --git a/core/src/main/java/io/github/mmm/base/lang/ValueType.java b/core/src/main/java/io/github/mmm/base/lang/ValueType.java new file mode 100644 index 0000000..c673d3c --- /dev/null +++ b/core/src/main/java/io/github/mmm/base/lang/ValueType.java @@ -0,0 +1,119 @@ +/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0 */ +package io.github.mmm.base.lang; + +import java.util.Objects; + +import io.github.mmm.base.number.NumberType; + +/** + * Interface for generic support of a {@link #getType() value type}. It does not represent a value itself but only its + * type with ability to {@link #format(Object) format} and {@link #parse(String) parse} values of the represented type. + * + * @param the {@link #getType() type type}. + * @since 1.0.0 + * @see io.github.mmm.base.number.NumberType + * @see io.github.mmm.base.temporal.TemporalType + */ +public abstract class ValueType { + + /** {@link ValueType} for {@link String}. */ + public static final ValueType STRING = new ValueType<>(String.class, null) { + @Override + public String parse(String value) { + + return value; + } + }; + + /** {@link ValueType} for {@link String}. */ + public static final ValueType BOOLEAN = new ValueType<>(Boolean.class, boolean.class) { + @Override + public Boolean parse(String value) { + + if (value == null) { + return null; + } + if ("true".equals(value)) { + return Boolean.TRUE; + } else if ("false".equals(value)) { + return Boolean.FALSE; + } + throw new IllegalArgumentException(value); + } + }; + + /** @see #getType() */ + protected final Class type; + + /** @see #getType() */ + protected final Class primitiveType; + + /** + * The constructor. + * + * @param type the {@link #getType() value type}. + */ + public ValueType(Class type) { + + this(type, null); + } + + /** + * The constructor. + * + * @param type the {@link #getType() value type}. + * @param primitiveType the {@link #getPrimitiveType() primitive type}. + */ + public ValueType(Class type, Class primitiveType) { + + super(); + Objects.requireNonNull(type); + this.type = type; + this.primitiveType = primitiveType; + } + + /** + * @return the {@link Class} reflecting the {@link Number} represented by this {@link NumberType}. + */ + public Class getType() { + + return this.type; + } + + /** + * @return the primitive type corresponding to the {@link #getType() value type} or {@code null} if not available. + */ + public Class getPrimitiveType() { + + return this.primitiveType; + } + + /** + * @param value the value as {@link String}. + * @return the parsed value as its {@link #getType() value type}. + */ + public abstract V parse(String value); + + /** + * @param value the value to format. + * @return the {@link Object#toString() string representation} of the given {@code value}. + */ + public String format(V value) { + + if (value == null) { + return null; + } + return value.toString(); + } + + @Override + public String toString() { + + String name = this.type.getName(); + if (name.startsWith("java.")) { + return this.type.getSimpleName(); + } + return name; + } +} diff --git a/core/src/main/java/io/github/mmm/base/number/NumberType.java b/core/src/main/java/io/github/mmm/base/number/NumberType.java index 25b250b..31b9ead 100644 --- a/core/src/main/java/io/github/mmm/base/number/NumberType.java +++ b/core/src/main/java/io/github/mmm/base/number/NumberType.java @@ -5,21 +5,23 @@ import java.math.BigDecimal; import java.math.BigInteger; +import io.github.mmm.base.lang.ValueType; + /** * A {@link NumberType} represents a specific {@link Number} {@link Class}. It allows to check attributes like * {@link #isDecimal()} or {@link #getExactness()}.
- * Further it acts as factory to create according numbers {@link #valueOf(String) from string} or - * {@link #valueOf(Number) from number}.
+ * Further it acts as factory to create according numbers {@link #parse(String) from string} or {@link #valueOf(Number) + * from number}.
* This is a class and NOT an {@link Enum} to be extensible. * * @param type of the {@link #getType() represented number-class}. * * @since 1.0.0 */ -public abstract class NumberType { +public abstract class NumberType extends ValueType { /** The {@link NumberType} for {@link Byte}. */ - public static final NumberType BYTE = new NumberType<>(Byte.class, 1, Byte.valueOf(Byte.MIN_VALUE), + public static final NumberType BYTE = new NumberType<>(Byte.class, byte.class, 1, Byte.valueOf(Byte.MIN_VALUE), Byte.valueOf(Byte.MAX_VALUE)) { @Override @@ -35,7 +37,7 @@ protected Byte convert(Number number, boolean exact) { } @Override - public Byte valueOf(String number, int radix) { + public Byte parse(String number, int radix) { return Byte.valueOf(number, radix); } @@ -43,8 +45,8 @@ public Byte valueOf(String number, int radix) { }; /** The {@link NumberType} for {@link Short}. */ - public static final NumberType SHORT = new NumberType<>(Short.class, 2, Short.valueOf(Short.MIN_VALUE), - Short.valueOf(Short.MAX_VALUE)) { + public static final NumberType SHORT = new NumberType<>(Short.class, short.class, 2, + Short.valueOf(Short.MIN_VALUE), Short.valueOf(Short.MAX_VALUE)) { @Override protected Short convert(Number number, boolean exact) { @@ -59,7 +61,7 @@ protected Short convert(Number number, boolean exact) { } @Override - public Short valueOf(String number, int radix) { + public Short parse(String number, int radix) { return Short.valueOf(number, radix); } @@ -67,7 +69,7 @@ public Short valueOf(String number, int radix) { }; /** The {@link NumberType} for {@link Integer}. */ - public static final NumberType INTEGER = new NumberType<>(Integer.class, 3, + public static final NumberType INTEGER = new NumberType<>(Integer.class, int.class, 3, Integer.valueOf(Integer.MIN_VALUE), Integer.valueOf(Integer.MAX_VALUE)) { @Override @@ -83,7 +85,7 @@ protected Integer convert(Number number, boolean exact) { } @Override - public Integer valueOf(String number, int radix) { + public Integer parse(String number, int radix) { return Integer.valueOf(number, radix); } @@ -91,7 +93,7 @@ public Integer valueOf(String number, int radix) { }; /** The {@link NumberType} for {@link Long}. */ - public static final NumberType LONG = new NumberType<>(Long.class, 4, Long.valueOf(Long.MIN_VALUE), + public static final NumberType LONG = new NumberType<>(Long.class, long.class, 4, Long.valueOf(Long.MIN_VALUE), Long.valueOf(Long.MAX_VALUE)) { @Override @@ -107,7 +109,7 @@ protected Long convert(Number number, boolean exact) { } @Override - public Long valueOf(String number, int radix) { + public Long parse(String number, int radix) { return Long.valueOf(number, radix); } @@ -123,9 +125,9 @@ public String format(Long number, int radix) { }; /** The {@link NumberType} for {@link Float}. */ - public static final NumberType FLOAT = new NumberType<>(Float.class, 5, Float.valueOf(-Float.MAX_VALUE), - Float.valueOf(Float.MAX_VALUE), Float.valueOf(Float.NaN), Float.valueOf(Float.POSITIVE_INFINITY), - Float.valueOf(Float.NEGATIVE_INFINITY)) { + public static final NumberType FLOAT = new NumberType<>(Float.class, float.class, 5, + Float.valueOf(-Float.MAX_VALUE), Float.valueOf(Float.MAX_VALUE), Float.valueOf(Float.NaN), + Float.valueOf(Float.POSITIVE_INFINITY), Float.valueOf(Float.NEGATIVE_INFINITY)) { @Override protected Float convert(Number number, boolean exact) { @@ -140,7 +142,7 @@ protected Float convert(Number number, boolean exact) { } @Override - public Float valueOf(String number, int radix) { + public Float parse(String number, int radix) { if (radix == 16) { number = "0x" + number; @@ -167,9 +169,9 @@ public String format(Float number, int radix) { }; /** The {@link NumberType} for {@link Double}. */ - public static final NumberType DOUBLE = new NumberType<>(Double.class, 6, Double.valueOf(-Double.MAX_VALUE), - Double.valueOf(Double.MAX_VALUE), Double.valueOf(Double.NaN), Double.valueOf(Double.POSITIVE_INFINITY), - Double.valueOf(Double.NEGATIVE_INFINITY)) { + public static final NumberType DOUBLE = new NumberType<>(Double.class, double.class, 6, + Double.valueOf(-Double.MAX_VALUE), Double.valueOf(Double.MAX_VALUE), Double.valueOf(Double.NaN), + Double.valueOf(Double.POSITIVE_INFINITY), Double.valueOf(Double.NEGATIVE_INFINITY)) { @Override protected Double convert(Number number, boolean exact) { @@ -201,7 +203,7 @@ protected Double convert(Number number, boolean exact) { } @Override - public Double valueOf(String number, int radix) { + public Double parse(String number, int radix) { if (radix == 16) { number = "0x" + number; @@ -228,7 +230,7 @@ public String format(Double number, int radix) { }; /** The {@link NumberType} for {@link BigInteger}. */ - public static final NumberType BIG_INTEGER = new NumberType<>(BigInteger.class, 7, null, null) { + public static final NumberType BIG_INTEGER = new NumberType<>(BigInteger.class, null, 7, null, null) { @Override protected BigInteger convert(Number number, boolean exact) { @@ -244,7 +246,7 @@ protected BigInteger convert(Number number, boolean exact) { } @Override - public BigInteger valueOf(String number, int radix) { + public BigInteger parse(String number, int radix) { return new BigInteger(number, radix); } @@ -280,7 +282,7 @@ public String format(BigInteger number, int radix) { }; /** The {@link NumberType} for {@link BigDecimal}. */ - public static final NumberType BIG_DECIMAL = new NumberType<>(BigDecimal.class, 8, null, null) { + public static final NumberType BIG_DECIMAL = new NumberType<>(BigDecimal.class, null, 8, null, null) { @Override protected BigDecimal convert(Number number, boolean exact) { @@ -289,7 +291,7 @@ protected BigDecimal convert(Number number, boolean exact) { } @Override - public BigDecimal valueOf(String number, int radix) { + public BigDecimal parse(String number, int radix) { if (radix != 10) { throw illegalRadixException(radix); @@ -332,8 +334,6 @@ public String format(BigDecimal number, int radix) { private static final NumberType[] TYPES = { null, BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, BIG_INTEGER, BIG_DECIMAL }; - private final Class type; - final int exactness; private final N min; @@ -354,19 +354,21 @@ public String format(BigDecimal number, int radix) { * The constructor. * * @param type the {@link #getType() type}. + * @param primitiveType the {@link #getPrimitiveType() primitive type}. * @param exactness the {@link #getExactness() exactness}. * @param min the {@link #getMin() minimum value}. * @param max the {@link #getMax() maximum value}. */ - protected NumberType(Class type, int exactness, N min, N max) { + protected NumberType(Class type, Class primitiveType, int exactness, N min, N max) { - this(type, exactness, min, max, null, null, null); + this(type, primitiveType, exactness, min, max, null, null, null); } /** * The constructor. * * @param type the {@link #getType() type}. + * @param primitiveType the {@link #getPrimitiveType() primitive type}. * @param exactness the {@link #getExactness() exactness}. * @param min the {@link #getMin() minimum value}. * @param max the {@link #getMax() maximum value}. @@ -374,10 +376,10 @@ protected NumberType(Class type, int exactness, N min, N max) { * @param positiveInfinity the {@link #getPositiveInfinity() positive infinity value}. * @param negativeInfinity the {@link #getNegativeInfinity() negative infinity value}. */ - protected NumberType(Class type, int exactness, N min, N max, N nan, N positiveInfinity, N negativeInfinity) { + protected NumberType(Class type, Class primitiveType, int exactness, N min, N max, N nan, N positiveInfinity, + N negativeInfinity) { - super(); - this.type = type; + super(type, primitiveType); this.exactness = exactness; this.min = min; this.max = max; @@ -388,14 +390,6 @@ protected NumberType(Class type, int exactness, N min, N max, N nan, N positi this.negativeInfinity = negativeInfinity; } - /** - * @return the {@link Class} reflecting the {@link Number} represented by this {@link NumberType}. - */ - public Class getType() { - - return this.type; - } - /** * @param number is the number to convert. * @param exact {@code true} if {@code null} shall be returned in case the conversion looses precision, {@code false} @@ -492,9 +486,10 @@ public N valueOf(Number number, boolean exact) { * @return the parsed number of the according {@link #getType() type}. * @throws NumberFormatException if the given {@link String} has an invalid format for this {@link #getType() type}. */ - public N valueOf(String number) throws NumberFormatException { + @Override + public N parse(String number) throws NumberFormatException { - return valueOf(number, 10); + return parse(number, 10); } /** @@ -505,7 +500,7 @@ public N valueOf(String number) throws NumberFormatException { * @throws IllegalArgumentException if the given {@code radix} is not supported. The radix {@code 10} is always * supported, and {@code 16} is supported for types other than {@link #BIG_DECIMAL}. */ - public abstract N valueOf(String number, int radix) throws NumberFormatException; + public abstract N parse(String number, int radix) throws NumberFormatException; /** * @param number the {@link Number} to format a {@link String}. @@ -523,6 +518,7 @@ public String format(N number, int radix) throws IllegalArgumentException { if (number == null) { return null; } + // overridden for Long, BigInteger and decimal types return Integer.toString(number.intValue(), radix); } diff --git a/core/src/main/java/io/github/mmm/base/temporal/TemporalType.java b/core/src/main/java/io/github/mmm/base/temporal/TemporalType.java new file mode 100644 index 0000000..d699d54 --- /dev/null +++ b/core/src/main/java/io/github/mmm/base/temporal/TemporalType.java @@ -0,0 +1,144 @@ +/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0 */ +package io.github.mmm.base.temporal; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.MonthDay; +import java.time.OffsetDateTime; +import java.time.Period; +import java.time.ZonedDateTime; +import java.time.temporal.Temporal; + +import io.github.mmm.base.lang.ValueType; + +/** + * Extends {@link ValueType} for {@link Temporal} types. + * + * @param the {@link #getType() type type}. + * @since 1.0.0 + */ +public abstract class TemporalType extends ValueType { + + /** {@link TemporalType} for {@link Instant}. */ + public static final TemporalType INSTANT = new TemporalType<>(Instant.class) { + @Override + public Instant parse(String value) { + + if (value == null) { + return null; + } + return Instant.parse(value); + } + }; + + /** {@link TemporalType} for {@link LocalDate}. */ + public static final TemporalType LOCAL_DATE = new TemporalType<>(LocalDate.class) { + @Override + public LocalDate parse(String value) { + + if (value == null) { + return null; + } + return LocalDate.parse(value); + } + }; + + /** {@link TemporalType} for {@link LocalTime}. */ + public static final TemporalType LOCAL_TIME = new TemporalType<>(LocalTime.class) { + @Override + public LocalTime parse(String value) { + + if (value == null) { + return null; + } + return LocalTime.parse(value); + } + }; + + /** {@link TemporalType} for {@link LocalDateTime}. */ + public static final TemporalType LOCAL_DATE_TIME = new TemporalType<>(LocalDateTime.class) { + @Override + public LocalDateTime parse(String value) { + + if (value == null) { + return null; + } + return LocalDateTime.parse(value); + } + }; + + /** {@link TemporalType} for {@link ZonedDateTime}. */ + public static final TemporalType ZONED_DATE_TIME = new TemporalType<>(ZonedDateTime.class) { + @Override + public ZonedDateTime parse(String value) { + + if (value == null) { + return null; + } + return ZonedDateTime.parse(value); + } + }; + + /** {@link TemporalType} for {@link OffsetDateTime}. */ + public static final TemporalType OFFSET_DATE_TIME = new TemporalType<>(OffsetDateTime.class) { + @Override + public OffsetDateTime parse(String value) { + + if (value == null) { + return null; + } + return OffsetDateTime.parse(value); + } + }; + + /** {@link TemporalType} for {@link Duration}. */ + public static final TemporalType DURATION = new TemporalType<>(Duration.class) { + @Override + public Duration parse(String value) { + + if (value == null) { + return null; + } + return Duration.parse(value); + } + }; + + /** {@link TemporalType} for {@link Period}. */ + public static final TemporalType PERIOD = new TemporalType<>(Period.class) { + @Override + public Period parse(String value) { + + if (value == null) { + return null; + } + return Period.parse(value); + } + }; + + /** {@link TemporalType} for {@link MonthDay}. */ + public static final TemporalType MONTH_DAY = new TemporalType<>(MonthDay.class) { + @Override + public MonthDay parse(String value) { + + if (value == null) { + return null; + } + return MonthDay.parse(value); + } + }; + + /** + * The constructor. + * + * @param type the {@link #getType() value type}. + */ + public TemporalType(Class type) { + + super(type); + } + +} diff --git a/core/src/test/java/io/github/mmm/base/number/NumberTypeTest.java b/core/src/test/java/io/github/mmm/base/number/NumberTypeTest.java index 8ea154f..ca1c871 100644 --- a/core/src/test/java/io/github/mmm/base/number/NumberTypeTest.java +++ b/core/src/test/java/io/github/mmm/base/number/NumberTypeTest.java @@ -22,14 +22,14 @@ protected void check(NumberType type, N value) { assertThat(type.getType()).isEqualTo(value.getClass()); assertThat(type).isSameAs(NumberType.ofExactness(type.getExactness())); - assertThat(type.valueOf(value.toString())).isEqualTo(value); + assertThat(type.parse(value.toString())).isEqualTo(value); if (type.getExactness() < 7) { Double d = Double.valueOf(value.doubleValue()); assertThat(type.valueOf(d)).isEqualTo(value); } assertThat(type.valueOf(value)).isSameAs(value); try { - type.valueOf("illegal number"); + type.parse("illegal number"); failBecauseExceptionWasNotThrown(NumberFormatException.class); } catch (NumberFormatException e) { } diff --git a/metainfo/src/main/java/io/github/mmm/base/metainfo/MetaInfo.java b/metainfo/src/main/java/io/github/mmm/base/metainfo/MetaInfo.java index ccecd44..0bb21e2 100644 --- a/metainfo/src/main/java/io/github/mmm/base/metainfo/MetaInfo.java +++ b/metainfo/src/main/java/io/github/mmm/base/metainfo/MetaInfo.java @@ -6,10 +6,13 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.function.Function; import io.github.mmm.base.exception.ObjectNotFoundException; +import io.github.mmm.base.lang.ValueType; import io.github.mmm.base.metainfo.impl.MetaInfoEmpty; import io.github.mmm.base.metainfo.impl.MetaInfoValues; +import io.github.mmm.base.number.NumberType; /** * Interface for meta-information similar to {@link java.util.Properties} but more sophisticated. Implements @@ -118,38 +121,109 @@ default String get(boolean inherit, String key, String defaultValue) { String get(boolean inherit, boolean required, String key); /** + * @param type of the requested value. + * @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to + * only return plain meta-information defined in this {@link MetaInfo} itself. + * @param required - {@code true} if the requested value is required and an exception shall be raised if it is + * undefined, {@code false} otherwise (return {@code null} if undefined). + * @param key the key of the requested meta-information. + * @param type the {@link Class} reflecting the requested value. + * @param parser the {@link Function} to {@link Function#apply(Object) parse} the value from a {@link String} to the + * expected value type. + * @return the value of the meta-information for the given {@code key}. Will be {@code null} if no value is defined + * for the given {@code key}. + * @throws ObjectNotFoundException if the specified value is undefined and {@code required} was {@code true}. + */ + T getGeneric(boolean inherit, boolean required, String key, ValueType type); + + /** + * @param key the key of the requested meta-information. + * @return the value of the meta-information for the given {@code key} parsed as {@link Integer}. Will be {@code null} + * if no value is defined for the given {@code key}. + * @throws IllegalArgumentException if the value cannot be parsed as {@link Integer}. + */ + default Integer getAsInteger(String key) { + + return getAsInteger(true, false, key); + } + + /** + * @param key the key of the requested meta-information. + * @return the value of the meta-information for the given {@code key} parsed as {@link Integer}. + * @throws ObjectNotFoundException if the specified value is undefined. + * @throws IllegalArgumentException if the value cannot be parsed as {@link Integer}. + */ + default int getAsIntegerRequired(String key) { + + return getAsInteger(true, true, key).intValue(); + } + + /** + * @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to + * only return plain meta-information defined in this {@link MetaInfo} itself. + * @param required - {@code true} if the requested value is required and an exception shall be raised if it is + * undefined, {@code false} otherwise (return {@code null} if undefined). * @param key the key of the requested meta-information. * @return the value of the meta-information for the given {@code key} parsed as {@link Long}. Will be {@code null} if * no value is defined for the given {@code key}. - * @throws IllegalArgumentException if the value cannot be parsed as {@link Long}. + * @throws ObjectNotFoundException if the specified value is undefined and {@code required} was {@code true}. + * @throws IllegalArgumentException if the value cannot be parsed as {@link Integer}. */ - default Long getAsLong(String key) { + default Integer getAsInteger(boolean inherit, boolean required, String key) { - return getAsLong(true, key); + return getGeneric(inherit, required, key, NumberType.INTEGER); } /** * @param key the key of the requested meta-information. - * @return the value of the meta-information for the given {@code key} parsed as {@link Long}. - * @throws ObjectNotFoundException if the specified value is undefined. - * @throws IllegalArgumentException if the value cannot be parsed as {@link Long}. + * @param defaultValue the default value returned if the actual value is undefined. + * @return the value of the meta-information for the given {@code key} parsed as {@link int}. If the actual value is + * undefined, the given {@code defaultValue} will be returned. + * @throws IllegalArgumentException if the value cannot be parsed as {@link int}. */ - default long getAsLongRequired(String key) { + default int getAsInteger(String key, int defaultValue) { - return getAsLong(true, true, key).longValue(); + return getAsInteger(true, key, defaultValue); } /** * @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to * only return plain meta-information defined in this {@link MetaInfo} itself. + * @param key the key of the requested meta-information. + * @param defaultValue the default value returned if the actual value is undefined. + * @return the value of the meta-information for the given {@code key} parsed as {@link int}. If the actual value is + * undefined, the given {@code defaultValue} will be returned. + * @throws IllegalArgumentException if the value cannot be parsed as {@link int}. + */ + default int getAsInteger(boolean inherit, String key, int defaultValue) { + + Integer value = getAsInteger(inherit, false, key); + if (value == null) { + return defaultValue; + } + return value.intValue(); + } + + /** * @param key the key of the requested meta-information. * @return the value of the meta-information for the given {@code key} parsed as {@link Long}. Will be {@code null} if * no value is defined for the given {@code key}. * @throws IllegalArgumentException if the value cannot be parsed as {@link Long}. */ - default Long getAsLong(boolean inherit, String key) { + default Long getAsLong(String key) { + + return getAsLong(true, false, key); + } + + /** + * @param key the key of the requested meta-information. + * @return the value of the meta-information for the given {@code key} parsed as {@link Long}. + * @throws ObjectNotFoundException if the specified value is undefined. + * @throws IllegalArgumentException if the value cannot be parsed as {@link Long}. + */ + default long getAsLongRequired(String key) { - return getAsLong(inherit, false, key); + return getAsLong(true, true, key).longValue(); } /** @@ -165,15 +239,7 @@ default Long getAsLong(boolean inherit, String key) { */ default Long getAsLong(boolean inherit, boolean required, String key) { - String value = get(inherit, required, key); - if (value == null) { - return null; - } - try { - return Long.valueOf(value); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Meta-info for key '" + key + "' is no long value", e); - } + return getGeneric(inherit, required, key, NumberType.LONG); } /** @@ -199,7 +265,7 @@ default long getAsLong(String key, long defaultValue) { */ default long getAsLong(boolean inherit, String key, long defaultValue) { - Long value = getAsLong(inherit, key); + Long value = getAsLong(inherit, false, key); if (value == null) { return defaultValue; } @@ -214,7 +280,7 @@ default long getAsLong(boolean inherit, String key, long defaultValue) { */ default Boolean getAsBoolean(String key) { - return getAsBoolean(true, key); + return getAsBoolean(true, false, key); } /** @@ -228,19 +294,6 @@ default boolean getAsBooleanRequired(String key) { return getAsBoolean(true, true, key).booleanValue(); } - /** - * @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to - * only return plain meta-information defined in this {@link MetaInfo} itself. - * @param key the key of the requested meta-information. - * @return the value of the meta-information for the given {@code key} parsed as {@link Boolean}. Will be {@code null} - * if no value is defined for the given {@code key}. - * @throws IllegalArgumentException if the value cannot be parsed as {@link Boolean}. - */ - default Boolean getAsBoolean(boolean inherit, String key) { - - return getAsBoolean(inherit, false, key); - } - /** * @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to * only return plain meta-information defined in this {@link MetaInfo} itself. @@ -254,16 +307,7 @@ default Boolean getAsBoolean(boolean inherit, String key) { */ default Boolean getAsBoolean(boolean inherit, boolean required, String key) { - String value = get(inherit, key); - if (value == null) { - return null; - } - if ("true".equals(value)) { - return Boolean.TRUE; - } else if ("false".equals(value)) { - return Boolean.FALSE; - } - throw new IllegalArgumentException("Meta-info for key '" + key + "' is no boolean value: " + value); + return getGeneric(inherit, required, key, ValueType.BOOLEAN); } /** @@ -289,7 +333,7 @@ default boolean getAsBoolean(String key, boolean defaultValue) { */ default boolean getAsBoolean(boolean inherit, String key, boolean defaultValue) { - Boolean value = getAsBoolean(inherit, key); + Boolean value = getAsBoolean(inherit, false, key); if (value == null) { return defaultValue; } diff --git a/metainfo/src/main/java/io/github/mmm/base/metainfo/impl/AbstractMetaInfo.java b/metainfo/src/main/java/io/github/mmm/base/metainfo/impl/AbstractMetaInfo.java index bffce7b..ae290bf 100644 --- a/metainfo/src/main/java/io/github/mmm/base/metainfo/impl/AbstractMetaInfo.java +++ b/metainfo/src/main/java/io/github/mmm/base/metainfo/impl/AbstractMetaInfo.java @@ -7,7 +7,9 @@ import java.util.Set; import java.util.TreeSet; +import io.github.mmm.base.exception.ObjectMismatchException; import io.github.mmm.base.exception.ObjectNotFoundException; +import io.github.mmm.base.lang.ValueType; import io.github.mmm.base.metainfo.MetaInfo; import io.github.mmm.base.metainfo.MetaInfos; @@ -53,12 +55,27 @@ public String get(boolean inherit, String key) { public String get(boolean inherit, boolean required, String key) { String value = get(inherit, key); - if (value == null) { + if ((value == null) && required) { throw new ObjectNotFoundException("MetaInfo-value", qualifyKey(key)); } return value; } + @Override + public T getGeneric(boolean inherit, boolean required, String key, ValueType type) { + + String value = get(inherit, required, key); + if (value == null) { + return null; + } + try { + return type.parse(value); + } catch (Exception e) { + String expected = type.toString() + " for " + qualifyKey(key); + throw new ObjectMismatchException(value, expected, e); + } + } + /** * @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to * only return plain meta-information defined in this {@link MetaInfo} itself.