mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 08:18:29 +00:00
[configuration] Implemented the StringResolver
This commit is contained in:
1 parent
43ead7d65f
commit
a23f56c21b
4 files changed
+258
-44
No files matched your search
@@ -23,15 +23,85 @@ package lombok.core.configuration;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ConfigurationDataType {
|
||||
private static final List<Class<?>> SIMPLE_TYPES = Arrays.<Class<?>>asList(String.class, Integer.class, Boolean.class, Long.class, Byte.class, Short.class, Character.class, Float.class, Double.class);
|
||||
private static final Map<Class<?>, ConfigurationValueParser> SIMPLE_TYPES;
|
||||
static {
|
||||
Map<Class<?>, ConfigurationValueParser> map = new HashMap<Class<?>, ConfigurationValueParser>();
|
||||
map.put(String.class, new ConfigurationValueParser() {
|
||||
@Override public Object parse(String value) {
|
||||
return value;
|
||||
}
|
||||
@Override public String description() {
|
||||
return "String";
|
||||
}
|
||||
});
|
||||
map.put(Integer.class, new ConfigurationValueParser() {
|
||||
@Override public Object parse(String value) {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
@Override public String description() {
|
||||
return "Integer";
|
||||
}
|
||||
});
|
||||
map.put(Long.class, new ConfigurationValueParser() {
|
||||
@Override public Object parse(String value) {
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
@Override public String description() {
|
||||
return "Long";
|
||||
}
|
||||
});
|
||||
map.put(Double.class, new ConfigurationValueParser() {
|
||||
@Override public Object parse(String value) {
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
@Override public String description() {
|
||||
return "Double";
|
||||
}
|
||||
});
|
||||
map.put(Boolean.class, new ConfigurationValueParser() {
|
||||
@Override public Object parse(String value) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
@Override public String description() {
|
||||
return "Boolean";
|
||||
}
|
||||
});
|
||||
map.put(TypeName.class, new ConfigurationValueParser() {
|
||||
@Override public Object parse(String value) {
|
||||
return TypeName.valueOf(value);
|
||||
}
|
||||
@Override public String description() {
|
||||
return "TypeName";
|
||||
}
|
||||
});
|
||||
SIMPLE_TYPES = map;
|
||||
}
|
||||
|
||||
|
||||
private static ConfigurationValueParser enumParser(Object enumType) {
|
||||
@SuppressWarnings("rawtypes") final Class rawType = (Class)enumType;
|
||||
return new ConfigurationValueParser(){
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override public Object parse(String value) {
|
||||
try {
|
||||
return Enum.valueOf(rawType, value);
|
||||
} catch (Exception e) {
|
||||
return Enum.valueOf(rawType, value.toUpperCase());
|
||||
}
|
||||
}
|
||||
@Override public String description() {
|
||||
return rawType.getName();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final boolean isList;
|
||||
private final Class<?> elementType;
|
||||
private final ConfigurationValueParser parser;
|
||||
|
||||
public static ConfigurationDataType toDataType(Class<? extends ConfigurationKey<?>> keyClass) {
|
||||
if (keyClass.getSuperclass() != ConfigurationKey.class) {
|
||||
@@ -55,61 +125,46 @@ public final class ConfigurationDataType {
|
||||
}
|
||||
}
|
||||
|
||||
if (SIMPLE_TYPES.contains(argumentType) || isEnum(argumentType)) {
|
||||
return new ConfigurationDataType(isList, (Class<?>)argumentType);
|
||||
if (SIMPLE_TYPES.containsKey(argumentType)) {
|
||||
return new ConfigurationDataType(isList, SIMPLE_TYPES.get(argumentType));
|
||||
}
|
||||
|
||||
if (argumentType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedArgument = (ParameterizedType) argumentType;
|
||||
if (parameterizedArgument.getRawType() == Class.class) {
|
||||
Type classType = parameterizedArgument.getActualTypeArguments()[0];
|
||||
if (!(classType instanceof WildcardType)) {
|
||||
throw new IllegalArgumentException("Illegal specific Class type parameter in " + type);
|
||||
}
|
||||
WildcardType wildcard = (WildcardType) classType;
|
||||
if (wildcard.getLowerBounds().length != 0 || wildcard.getUpperBounds().length != 1 || wildcard.getUpperBounds()[0] != Object.class) {
|
||||
throw new IllegalArgumentException("Illegal bound wildcard Class type parameter in " + type);
|
||||
}
|
||||
return new ConfigurationDataType(isList, Class.class);
|
||||
}
|
||||
}
|
||||
|
||||
if (argumentType == Class.class) {
|
||||
return new ConfigurationDataType(isList, Class.class);
|
||||
if (isEnum(argumentType)) {
|
||||
return new ConfigurationDataType(isList, enumParser(argumentType));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported type parameter in " + type);
|
||||
}
|
||||
|
||||
private ConfigurationDataType(boolean isList, Class<?> elementType) {
|
||||
private ConfigurationDataType(boolean isList, ConfigurationValueParser parser) {
|
||||
this.isList = isList;
|
||||
this.elementType = elementType;
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
public boolean isList() {
|
||||
boolean isList() {
|
||||
return isList;
|
||||
}
|
||||
|
||||
public Class<?> getElementType() {
|
||||
return elementType;
|
||||
ConfigurationValueParser getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (isList ? 1231 : 1237) + elementType.hashCode();
|
||||
return (isList ? 1231 : 1237) + parser.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ConfigurationDataType)) return false;
|
||||
ConfigurationDataType other = (ConfigurationDataType) obj;
|
||||
return isList == other.isList && elementType == other.elementType;
|
||||
return isList == other.isList && parser.equals(other.parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isList) return "java.util.List<" + elementType.getName() + ">";
|
||||
return elementType.getName();
|
||||
if (isList) return "List<" + parser.description() + ">";
|
||||
return parser.description();
|
||||
}
|
||||
|
||||
private static boolean isEnum(Type argumentType) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
interface ConfigurationValueParser {
|
||||
Object parse(String value);
|
||||
String description();
|
||||
}
|
||||
@@ -21,8 +21,11 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -30,16 +33,31 @@ public class StringResolver implements ConfigurationResolver {
|
||||
|
||||
private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))");
|
||||
|
||||
private final Map<String, Result> values = new TreeMap<String, Result>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
private static class Result {
|
||||
Object value;
|
||||
boolean owned;
|
||||
|
||||
public Result(Object value, boolean owned) {
|
||||
this.value = value;
|
||||
this.owned = owned;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return String.valueOf(value) + (owned ? " (set)" : " (delta)");
|
||||
}
|
||||
}
|
||||
|
||||
public StringResolver(String content) {
|
||||
Map<String, ConfigurationDataType> registeredKeys = ConfigurationKey.registeredKeys();
|
||||
for (String line : content.trim().split("\\s*\\n\\s*")) {
|
||||
if (line.isEmpty() || line.startsWith("#")) continue;
|
||||
Matcher matcher = LINE.matcher(line);
|
||||
System.out.println("\nLINE: " + line);
|
||||
|
||||
String operator = null;
|
||||
String keyName = null;
|
||||
String value = null;
|
||||
String value;
|
||||
|
||||
if (matcher.matches()) {
|
||||
if (matcher.group(1) == null) {
|
||||
@@ -61,24 +79,91 @@ public class StringResolver implements ConfigurationResolver {
|
||||
} else if (operator.equals("=") && type.isList()) {
|
||||
System.out.println(keyName + " IS a list");
|
||||
} else {
|
||||
System.out.printf("!! %s %s %s", keyName, operator, value);
|
||||
processResult(keyName, operator, value, type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("no match:" + line);
|
||||
}
|
||||
}
|
||||
for (Result r : values.values()) {
|
||||
if (r.value instanceof List<?>) {
|
||||
r.value = Collections.unmodifiableList(((List<?>) r.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public <T> T resolve(ConfigurationKey<T> key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConfigurationKey<String> AAP = new ConfigurationKey<String>("aap") {};
|
||||
ConfigurationKey<List<String>> NOOT = new ConfigurationKey<List<String>>("noot") {};
|
||||
private void processResult(String keyName, String operator, String value, ConfigurationDataType type) {
|
||||
Object element = null;
|
||||
if (value != null) try {
|
||||
element = type.getParser().parse(value);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// log the wrong value
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationResolver resolver = new StringResolver(" aap = 3 \naap += 4\n\r noot+=mies\nnoot=wim\nclear noot\nclear aap\r\n#foo-= bar\nblablabla\na=b=c\n\n\nclear test\n\nclear \nclear test=");
|
||||
String aapValue = resolver.resolve(AAP);
|
||||
if (operator.equals("clear") || operator.equals("=")) {
|
||||
if (element == null && type.isList()) {
|
||||
element = new ArrayList<Object>();
|
||||
}
|
||||
values.put(keyName, new Result(element, true));
|
||||
} else {
|
||||
Result result = values.get(keyName);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> list = result == null ? new ArrayList<Object>() : (List<Object>) result.value;
|
||||
if (result == null) values.put(keyName, new Result(list, false));
|
||||
list.remove(element);
|
||||
if (operator.equals("+=")) list.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override public <T> T resolve(ConfigurationKey<T> key) {
|
||||
Result result = values.get(key.getKeyName());
|
||||
T value = result == null ? null: (T)result.value;
|
||||
if (value == null && key.getType().isList()) {
|
||||
value = (T)Collections.emptyList();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
enum Flag {
|
||||
WARNING, ERROR
|
||||
}
|
||||
|
||||
private static final ConfigurationKey<String> AAP = new ConfigurationKey<String>("aap") {};
|
||||
private static final ConfigurationKey<List<String>> NOOT = new ConfigurationKey<List<String>>("noot") {};
|
||||
private static final ConfigurationKey<Integer> MIES = new ConfigurationKey<Integer>("mies") {};
|
||||
private static final ConfigurationKey<Boolean> WIM = new ConfigurationKey<Boolean>("wim") {};
|
||||
private static final ConfigurationKey<TypeName> ZUS = new ConfigurationKey<TypeName>("zus") {};
|
||||
private static final ConfigurationKey<Flag> JET = new ConfigurationKey<Flag>("jet") {};
|
||||
|
||||
public static void main(String[] args) {
|
||||
print("aap=text\nnoot+=first\nmies=5\nwim=true\nzus=foo.bar.Baz\njet=error");
|
||||
print("noot+=first\nnoot+=second\n");
|
||||
print("clear noot");
|
||||
print("noot+=before-clear\nclear noot\nnoot+=first\nnoot+=second\nnoot+=third\nnoot+=first\nnoot-=second\n");
|
||||
}
|
||||
|
||||
private static void print(String content) {
|
||||
StringResolver resolver = new StringResolver(content);
|
||||
System.out.println("\n\n================================================");
|
||||
System.out.println(content);
|
||||
System.out.println("================================================\n");
|
||||
System.out.println(resolver.values);
|
||||
System.out.println("================================================\n");
|
||||
String aap = resolver.resolve(AAP);
|
||||
System.out.println("aap: "+ aap);
|
||||
List<String> noot = resolver.resolve(NOOT);
|
||||
System.out.println("noot: "+ noot);
|
||||
Integer mies = resolver.resolve(MIES);
|
||||
System.out.println("mies: "+ mies);
|
||||
Boolean wim = resolver.resolve(WIM);
|
||||
System.out.println("wim: "+ wim);
|
||||
TypeName zus = resolver.resolve(ZUS);
|
||||
System.out.println("zus: "+ zus);
|
||||
Flag jet = resolver.resolve(JET);
|
||||
System.out.println("jet: "+ jet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public final class TypeName {
|
||||
private final String name;
|
||||
|
||||
private TypeName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static TypeName valueOf(String name) {
|
||||
return new TypeName(name);
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object obj) {
|
||||
if (!(obj instanceof TypeName)) return false;
|
||||
return name.equals(((TypeName) obj).name);
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user