Configuration types without explicit registration

This commit is contained in:
Adam Juraszek committed 2019-05-14 18:47:07 +02:00
1 parent 4ea4b8d27b
commit 399c516bd3
4 files changed
+116 -30

No files matched your search

@@ -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);
}
}
}
@@ -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 {
}
@@ -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();
}
}
@@ -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();
}
}