diff options
4 files changed, 116 insertions, 30 deletions
diff --git a/src/core/lombok/core/configuration/ConfigurationDataType.java b/src/core/lombok/core/configuration/ConfigurationDataType.java index 40de65cf..7dc77301 100644 --- a/src/core/lombok/core/configuration/ConfigurationDataType.java +++ b/src/core/lombok/core/configuration/ConfigurationDataType.java @@ -21,6 +21,8 @@ */ package lombok.core.configuration; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; @@ -97,36 +99,10 @@ public final class ConfigurationDataType { return "[false | true]"; } }); - map.put(TypeName.class, new ConfigurationValueParser() { - @Override public Object parse(String value) { - return TypeName.valueOf(value); - } - - @Override public String description() { - return "type-name"; - } - - @Override public String exampleValue() { - return "<fully.qualified.Type>"; - } - }); - map.put(IdentifierName.class, new ConfigurationValueParser() { - @Override public Object parse(String value) { - return IdentifierName.valueOf(value); - } - - @Override public String description() { - return "identifier-name"; - } - - @Override public String exampleValue() { - return "<javaIdentifier>"; - } - }); SIMPLE_TYPES = map; } - private static ConfigurationValueParser enumParser(Object enumType) { + private static ConfigurationValueParser enumParser(Type enumType) { final Class<?> type = (Class<?>) enumType; @SuppressWarnings("rawtypes") final Class rawType = type; @@ -158,6 +134,38 @@ public final class ConfigurationDataType { }; } + private static ConfigurationValueParser valueTypeParser(Type argumentType) { + final Class<?> type = (Class<?>) argumentType; + final Method valueOfMethod = getMethod(type, "valueOf", String.class); + final Method descriptionMethod = getMethod(type, "description"); + final Method exampleValueMethod = getMethod(type, "exampleValue"); + return new ConfigurationValueParser() { + @Override public Object parse(String value) { + return invokeStaticMethod(valueOfMethod, value); + } + + @Override public String description() { + return invokeStaticMethod(descriptionMethod); + } + + @Override public String exampleValue() { + return invokeStaticMethod(exampleValueMethod); + } + + @SuppressWarnings("unchecked") + private <R> R invokeStaticMethod(Method method, Object... arguments) { + try { + return (R) method.invoke(null, arguments); + } catch (IllegalAccessException e) { + throw new IllegalStateException("The method " + method.getName() + " ", e); + } catch (InvocationTargetException e) { + // There shouldn't be any checked Exception, only IllegalArgumentException is expected + throw (RuntimeException) e.getTargetException(); + } + } + }; + } + private final boolean isList; private final ConfigurationValueParser parser; @@ -168,7 +176,7 @@ public final class ConfigurationDataType { Type type = keyClass.getGenericSuperclass(); if (!(type instanceof ParameterizedType)) { - throw new IllegalArgumentException("Missing type parameter in "+ type); + throw new IllegalArgumentException("Missing type parameter in " + type); } ParameterizedType parameterized = (ParameterizedType) type; @@ -191,6 +199,10 @@ public final class ConfigurationDataType { return new ConfigurationDataType(isList, enumParser(argumentType)); } + if (isConfigurationValueType(argumentType)) { + return new ConfigurationDataType(isList, valueTypeParser(argumentType)); + } + throw new IllegalArgumentException("Unsupported type parameter in " + type); } @@ -216,4 +228,18 @@ public final class ConfigurationDataType { private static boolean isEnum(Type argumentType) { return argumentType instanceof Class && ((Class<?>) argumentType).isEnum(); } + + private static boolean isConfigurationValueType(Type argumentType) { + return argumentType instanceof Class && ConfigurationValueType.class.isAssignableFrom((Class<?>) argumentType); + } + + private static Method getMethod(Class<?> argumentType, String name, Class<?>... parameterTypes) { + try { + return argumentType.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Method " + name + " with parameters " + Arrays.toString(parameterTypes) + "was not found.", e); + } catch (SecurityException e) { + throw new IllegalStateException("Cannot inspect methods of type " + argumentType, e); + } + } }
\ No newline at end of file diff --git a/src/core/lombok/core/configuration/ConfigurationValueType.java b/src/core/lombok/core/configuration/ConfigurationValueType.java new file mode 100644 index 00000000..f287f62a --- /dev/null +++ b/src/core/lombok/core/configuration/ConfigurationValueType.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.core.configuration; + +/** + * If a type used in {@link ConfigurationKey} type argument implements this interface, + * it is expected to provide the following three static methods: + * <ul> + * <li><code>public static SELF valueOf(String value)</code> + * <li><code>public static String description()</code> + * <li><code>public static String exampleValue()</code> + * </ul> + * Based on these methods, an instance of {@link ConfigurationValueParser} is created + * and used by the configuration system. + */ +public interface ConfigurationValueType { +} diff --git a/src/core/lombok/core/configuration/IdentifierName.java b/src/core/lombok/core/configuration/IdentifierName.java index fa8e03af..52e51bd7 100644 --- a/src/core/lombok/core/configuration/IdentifierName.java +++ b/src/core/lombok/core/configuration/IdentifierName.java @@ -23,7 +23,7 @@ package lombok.core.configuration; import lombok.core.JavaIdentifiers; -public final class IdentifierName { +public final class IdentifierName implements ConfigurationValueType { private final String name; private IdentifierName(String name) { @@ -41,6 +41,14 @@ public final class IdentifierName { return new IdentifierName(trimmedName); } + public static String description() { + return "identifier-name"; + } + + public static String exampleValue() { + return "<javaIdentifier>"; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof IdentifierName)) return false; return name.equals(((IdentifierName) obj).name); @@ -57,4 +65,8 @@ public final class IdentifierName { public String getName() { return name; } + + public char[] getCharArray() { + return name.toCharArray(); + } } diff --git a/src/core/lombok/core/configuration/TypeName.java b/src/core/lombok/core/configuration/TypeName.java index 8bcb2e5a..a3128527 100644 --- a/src/core/lombok/core/configuration/TypeName.java +++ b/src/core/lombok/core/configuration/TypeName.java @@ -23,7 +23,7 @@ package lombok.core.configuration; import lombok.core.JavaIdentifiers; -public final class TypeName { +public final class TypeName implements ConfigurationValueType { private final String name; private TypeName(String name) { @@ -43,6 +43,14 @@ public final class TypeName { return new TypeName(trimmedName); } + public static String description() { + return "type-name"; + } + + public static String exampleValue() { + return "<fully.qualified.Type>"; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof TypeName)) return false; return name.equals(((TypeName) obj).name); @@ -59,4 +67,8 @@ public final class TypeName { public String getName() { return name; } + + public char[] getCharArray() { + return name.toCharArray(); + } } |