aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/core/configuration/BubblingConfigurationResolver.java76
-rw-r--r--src/core/lombok/core/configuration/ConfigurationDataType.java1
-rw-r--r--src/core/lombok/core/configuration/ConfigurationErrorReporter.java32
-rw-r--r--src/core/lombok/core/configuration/ConfigurationKey.java11
-rw-r--r--src/core/lombok/core/configuration/ConfigurationSource.java67
-rw-r--r--src/core/lombok/core/configuration/StringConfigurationSource.java128
-rw-r--r--src/core/lombok/core/configuration/StringResolver.java169
7 files changed, 309 insertions, 175 deletions
diff --git a/src/core/lombok/core/configuration/BubblingConfigurationResolver.java b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
new file mode 100644
index 00000000..5673d9a8
--- /dev/null
+++ b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.core.configuration.ConfigurationSource.ListModification;
+import lombok.core.configuration.ConfigurationSource.Result;
+
+public class BubblingConfigurationResolver implements ConfigurationResolver {
+
+ private final List<ConfigurationSource> sources;
+
+ public BubblingConfigurationResolver(List<ConfigurationSource> sources) {
+ this.sources = sources;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T resolve(ConfigurationKey<T> key) {
+ boolean isList = key.getType().isList();
+ List<ListModification> listModifications = null;
+ for (ConfigurationSource source : sources) {
+ Result<T> result = source.resolve(key);
+ if (result == null) continue;
+ if (isList) {
+ if (listModifications == null) {
+ listModifications = new ArrayList<ListModification>((List<ListModification>)result.getValue());
+ } else {
+ listModifications.addAll(0, (List<ListModification>)result.getValue());
+ }
+ }
+ if (result.isAuthoritative()) {
+ if (isList) {
+ break;
+ }
+ return result.getValue();
+ }
+ }
+ if (!isList) {
+ return null;
+ }
+ if (listModifications == null) {
+ return (T) Collections.emptyList();
+ }
+ List<Object> listValues = new ArrayList<Object>();
+ for (ListModification modification : listModifications) {
+ listValues.remove(modification.getValue());
+ if (modification.isAdded()) {
+ listValues.add(modification.getValue());
+ }
+ }
+ return (T) listValues;
+ }
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationDataType.java b/src/core/lombok/core/configuration/ConfigurationDataType.java
index d33de9e4..72aff88a 100644
--- a/src/core/lombok/core/configuration/ConfigurationDataType.java
+++ b/src/core/lombok/core/configuration/ConfigurationDataType.java
@@ -82,7 +82,6 @@ public final class ConfigurationDataType {
SIMPLE_TYPES = map;
}
-
private static ConfigurationValueParser enumParser(Object enumType) {
@SuppressWarnings("rawtypes") final Class rawType = (Class)enumType;
return new ConfigurationValueParser(){
diff --git a/src/core/lombok/core/configuration/ConfigurationErrorReporter.java b/src/core/lombok/core/configuration/ConfigurationErrorReporter.java
new file mode 100644
index 00000000..26fa9cc2
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationErrorReporter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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 interface ConfigurationErrorReporter {
+ ConfigurationErrorReporter CONSOLE = new ConfigurationErrorReporter() {
+ @Override public void report(String error) {
+ System.err.println(error);
+ }
+ };
+
+ void report(String error);
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/ConfigurationKey.java b/src/core/lombok/core/configuration/ConfigurationKey.java
index aaa673af..81a5dfaa 100644
--- a/src/core/lombok/core/configuration/ConfigurationKey.java
+++ b/src/core/lombok/core/configuration/ConfigurationKey.java
@@ -22,8 +22,8 @@
package lombok.core.configuration;
import java.util.Collections;
-import java.util.HashMap;
import java.util.Map;
+import java.util.TreeMap;
/**
* Describes a configuration key and its type.
@@ -34,7 +34,7 @@ import java.util.Map;
* </pre>
*/
public abstract class ConfigurationKey<T> {
- private static final Map<String, ConfigurationDataType> registeredKeys = new HashMap<String, ConfigurationDataType>();
+ private static final TreeMap<String, ConfigurationDataType> registeredKeys = new TreeMap<String, ConfigurationDataType>(String.CASE_INSENSITIVE_ORDER);
private static Map<String, ConfigurationDataType> copy;
private final String keyName;
@@ -57,7 +57,7 @@ public abstract class ConfigurationKey<T> {
return type;
}
- @Override
+ @Override
public final int hashCode() {
final int prime = 31;
int result = 1;
@@ -69,7 +69,7 @@ public abstract class ConfigurationKey<T> {
/**
* Two configuration are considered equal if and only if their {@code keyName} and {@code type} are equal.
*/
- @Override
+ @Override
public final boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ConfigurationKey)) return false;
@@ -86,9 +86,10 @@ public abstract class ConfigurationKey<T> {
/**
* Returns a copy of the currently registered keys.
*/
+ @SuppressWarnings("unchecked")
public static Map<String, ConfigurationDataType> registeredKeys() {
synchronized (registeredKeys) {
- if (copy == null) copy = Collections.unmodifiableMap(new HashMap<String, ConfigurationDataType>(registeredKeys));
+ if (copy == null) copy = Collections.unmodifiableMap((Map<String, ConfigurationDataType>) registeredKeys.clone());
return copy;
}
}
diff --git a/src/core/lombok/core/configuration/ConfigurationSource.java b/src/core/lombok/core/configuration/ConfigurationSource.java
new file mode 100644
index 00000000..03c73674
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationSource.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 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 interface ConfigurationSource {
+
+ <T> Result<T> resolve(ConfigurationKey<T> key);
+
+ public static final class Result<T> {
+ private final T value;
+ private final boolean authoritative;
+
+ public Result(T value, boolean authoritative) {
+ this.value = value;
+ this.authoritative = authoritative;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ public boolean isAuthoritative() {
+ return authoritative;
+ }
+
+ @Override public String toString() {
+ return String.valueOf(value) + (authoritative ? " (set)" : " (delta)");
+ }
+ }
+
+ public static class ListModification {
+ private final Object value;
+ private final boolean added;
+
+ public ListModification(Object value, boolean added) {
+ this.value = value;
+ this.added = added;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public boolean isAdded() {
+ return added;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/StringConfigurationSource.java b/src/core/lombok/core/configuration/StringConfigurationSource.java
new file mode 100644
index 00000000..3a6cd9e3
--- /dev/null
+++ b/src/core/lombok/core/configuration/StringConfigurationSource.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2014 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class StringConfigurationSource implements ConfigurationSource {
+
+ private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))");
+
+ private final Map<String, Result<?>> values;
+
+ public static ConfigurationSource forString(String content) {
+ return forString(content, ConfigurationErrorReporter.CONSOLE);
+ }
+
+ public static ConfigurationSource forString(String content, ConfigurationErrorReporter reporter) {
+ if (reporter == null) throw new NullPointerException("reporter");
+
+ Map<String, Result<?>> values = new TreeMap<String, Result<?>>(String.CASE_INSENSITIVE_ORDER);
+
+ 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);
+
+ String operator = null;
+ String keyName = null;
+ String value;
+
+ if (matcher.matches()) {
+ if (matcher.group(1) == null) {
+ keyName = matcher.group(2);
+ operator = matcher.group(3);
+ value = matcher.group(4);
+ } else {
+ keyName = matcher.group(1);
+ operator = "clear";
+ value = null;
+ }
+ ConfigurationDataType type = registeredKeys.get(keyName);
+ if (type == null) {
+ reporter.report("Unknown key '" + keyName + "' on line: " + line);
+ } else {
+ boolean listOperator = operator.equals("+=") || operator.equals("-=");
+ if (listOperator && !type.isList()) {
+ reporter.report("'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear): " + line);
+ } else if (operator.equals("=") && type.isList()) {
+ reporter.report("'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead): " + line);
+ } else {
+ processResult(values, keyName, operator, value, type, reporter);
+ }
+ }
+ } else {
+ reporter.report("No valid line: " + line);
+ }
+ }
+
+ return new StringConfigurationSource(values);
+ }
+
+ private StringConfigurationSource(Map<String, Result<?>> values) {
+ this.values = new TreeMap<String, Result<?>>(String.CASE_INSENSITIVE_ORDER);
+ for (Entry<String, Result<?>> entry : values.entrySet()) {
+ Result<?> result = entry.getValue();
+ if (result.getValue() instanceof List<?>) {
+ this.values.put(entry.getKey(), new Result<List<?>>(Collections.unmodifiableList((List<?>) result.getValue()), result.isAuthoritative()));
+ } else {
+ this.values.put(entry.getKey(), result);
+ }
+ }
+ }
+
+ private static void processResult(Map<String, Result<?>> values, String keyName, String operator, String value, ConfigurationDataType type, ConfigurationErrorReporter reporter) {
+ Object element = null;
+ if (value != null) try {
+ element = type.getParser().parse(value);
+ } catch (Exception e) {
+ reporter.report("Error while parsing the value for '" + keyName + "' value '" + value + "' (should be a " + type.getParser().description() + ")");
+ return;
+ }
+
+ if (operator.equals("clear") || operator.equals("=")) {
+ if (element == null && type.isList()) {
+ element = new ArrayList<ListModification>();
+ }
+ values.put(keyName, new Result<Object>(element, true));
+ } else {
+ Result<?> result = values.get(keyName);
+ @SuppressWarnings("unchecked")
+ List<ListModification> list = result == null ? new ArrayList<ListModification>() : (List<ListModification>) result.getValue();
+ if (result == null) values.put(keyName, new Result<Object>(list, false));
+ list.add(new ListModification(element, operator.equals("+=")));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> Result<T> resolve(ConfigurationKey<T> key) {
+ return (Result<T>) values.get(key.getKeyName());
+ }
+}
diff --git a/src/core/lombok/core/configuration/StringResolver.java b/src/core/lombok/core/configuration/StringResolver.java
deleted file mode 100644
index 81bd0a35..00000000
--- a/src/core/lombok/core/configuration/StringResolver.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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;
-
-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;
-
-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);
-
- String operator = null;
- String keyName = null;
- String value;
-
- if (matcher.matches()) {
- if (matcher.group(1) == null) {
- keyName = matcher.group(2);
- operator = matcher.group(3);
- value = matcher.group(4);
- } else {
- keyName = matcher.group(1);
- operator = "clear";
- value = null;
- }
- ConfigurationDataType type = registeredKeys.get(keyName);
- if (type == null) {
- System.out.println("Unknown key " + keyName);
- } else {
- boolean listOperator = operator.equals("+=") || operator.equals("-=");
- if (listOperator && !type.isList()) {
- System.out.println(keyName + " is not a list");
- } else if (operator.equals("=") && type.isList()) {
- System.out.println(keyName + " IS a list");
- } else {
- 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));
- }
- }
- }
-
- 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;
- }
-
- 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);
- }
-}