/* * Copyright (C) 2014-2016 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.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ConfigurationParser { private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))"); private static final Pattern NEWLINE_FINDER = Pattern.compile("^[\t ]*(.*?)[\t\r ]*$", Pattern.MULTILINE); private ConfigurationProblemReporter reporter; public ConfigurationParser(ConfigurationProblemReporter reporter) { if (reporter == null) throw new NullPointerException("reporter"); this.reporter = reporter; } public void parse(CharSequence content, String contentDescription, Collector collector) { Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys(); int lineNumber = 0; Matcher lineMatcher = NEWLINE_FINDER.matcher(content); while (lineMatcher.find()) { CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1)); lineNumber++; if (line.length() == 0 || line.charAt(0) == '#') continue; Matcher matcher = LINE.matcher(line); if (!matcher.matches()) { reporter.report(contentDescription, "Invalid line", lineNumber, line); continue; } String operator = null; String keyName = null; String stringValue; if (matcher.group(1) == null) { keyName = matcher.group(2); operator = matcher.group(3); stringValue = matcher.group(4); } else { keyName = matcher.group(1); operator = "clear"; stringValue = null; } ConfigurationKey<?> key = registeredKeys.get(keyName); if (key == null) { reporter.report(contentDescription, "Unknown key '" + keyName + "'", lineNumber, line); continue; } ConfigurationDataType type = key.getType(); boolean listOperator = operator.equals("+=") || operator.equals("-="); if (listOperator && !type.isList()) { reporter.report(contentDescription, "'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear)", lineNumber, line); continue; } if (operator.equals("=") && type.isList()) { reporter.report(contentDescription, "'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line); continue; } Object value = null; if (stringValue != null) try { value = type.getParser().parse(stringValue); } catch (Exception e) { reporter.report(contentDescription, "Error while parsing the value for '" + keyName + "' value '" + stringValue + "' (should be " + type.getParser().exampleValue() + ")", lineNumber, line); continue; } if (operator.equals("clear")) { collector.clear(key, contentDescription, lineNumber); } else if (operator.equals("=")) { collector.set(key, value, contentDescription, lineNumber); } else if (operator.equals("+=")) { collector.add(key, value, contentDescription, lineNumber); } else { collector.remove(key, value, contentDescription, lineNumber); } } } public interface Collector { void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber); void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber); void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber); void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber); } }