From 211ba90108a1105d291b47820c3f33868a2b4f1a Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Mon, 31 Mar 2014 14:25:26 +0200 Subject: [PATCH] rendertheme: merge AttributeMatcher into Rule - allow to match actual key-value-pairs. previously value matcher just checked *any* value not the one that matched key. See PositiveRuleKV/MultiKV --- vtm/src/org/oscim/theme/rule/AnyMatcher.java | 45 ----- .../oscim/theme/rule/AttributeMatcher.java | 26 --- .../org/oscim/theme/rule/MultiKeyMatcher.java | 57 ------ .../oscim/theme/rule/MultiValueMatcher.java | 57 ------ .../org/oscim/theme/rule/NegativeMatcher.java | 78 --------- .../org/oscim/theme/rule/NegativeRule.java | 51 +++++- .../org/oscim/theme/rule/PositiveRule.java | 158 +++++++++++++++-- vtm/src/org/oscim/theme/rule/Rule.java | 6 +- vtm/src/org/oscim/theme/rule/RuleBuilder.java | 163 +++++++----------- .../org/oscim/theme/rule/RuleOptimizer.java | 133 -------------- .../oscim/theme/rule/SingleKeyMatcher.java | 44 ----- .../oscim/theme/rule/SingleValueMatcher.java | 44 ----- 12 files changed, 252 insertions(+), 610 deletions(-) delete mode 100644 vtm/src/org/oscim/theme/rule/AnyMatcher.java delete mode 100644 vtm/src/org/oscim/theme/rule/AttributeMatcher.java delete mode 100644 vtm/src/org/oscim/theme/rule/MultiKeyMatcher.java delete mode 100644 vtm/src/org/oscim/theme/rule/MultiValueMatcher.java delete mode 100644 vtm/src/org/oscim/theme/rule/NegativeMatcher.java delete mode 100644 vtm/src/org/oscim/theme/rule/RuleOptimizer.java delete mode 100644 vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java delete mode 100644 vtm/src/org/oscim/theme/rule/SingleValueMatcher.java diff --git a/vtm/src/org/oscim/theme/rule/AnyMatcher.java b/vtm/src/org/oscim/theme/rule/AnyMatcher.java deleted file mode 100644 index c0130570..00000000 --- a/vtm/src/org/oscim/theme/rule/AnyMatcher.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import org.oscim.core.Tag; - -final class AnyMatcher implements AttributeMatcher { - private static final AnyMatcher INSTANCE = new AnyMatcher(); - - static AnyMatcher getInstance() { - return INSTANCE; - } - - /** - * Private constructor to prevent instantiation from other classes. - */ - private AnyMatcher() { - // do nothing - } - - @Override - public boolean isCoveredBy(AttributeMatcher attributeMatcher) { - return attributeMatcher == this; - } - - @Override - public boolean matches(Tag[] tags) { - return true; - } -} diff --git a/vtm/src/org/oscim/theme/rule/AttributeMatcher.java b/vtm/src/org/oscim/theme/rule/AttributeMatcher.java deleted file mode 100644 index 4f02ce68..00000000 --- a/vtm/src/org/oscim/theme/rule/AttributeMatcher.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import org.oscim.core.Tag; - -interface AttributeMatcher { - boolean isCoveredBy(AttributeMatcher attributeMatcher); - - boolean matches(Tag[] tags); -} diff --git a/vtm/src/org/oscim/theme/rule/MultiKeyMatcher.java b/vtm/src/org/oscim/theme/rule/MultiKeyMatcher.java deleted file mode 100644 index 1389e84e..00000000 --- a/vtm/src/org/oscim/theme/rule/MultiKeyMatcher.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import java.util.List; - -import org.oscim.core.Tag; - -class MultiKeyMatcher implements AttributeMatcher { - private final String[] mKeys; - - MultiKeyMatcher(List keys) { - mKeys = new String[keys.size()]; - for (int i = 0, n = mKeys.length; i < n; ++i) { - mKeys[i] = keys.get(i).intern(); - } - } - - @Override - public boolean isCoveredBy(AttributeMatcher attributeMatcher) { - if (attributeMatcher == this) { - return true; - } - - Tag[] tags = new Tag[mKeys.length]; - int i = 0; - for (String key : mKeys) { - tags[i++] = new Tag(key, null); - } - return attributeMatcher.matches(tags); - } - - @Override - public boolean matches(Tag[] tags) { - for (Tag tag : tags) - for (String key : mKeys) - if (key == tag.key) - return true; - - return false; - } -} diff --git a/vtm/src/org/oscim/theme/rule/MultiValueMatcher.java b/vtm/src/org/oscim/theme/rule/MultiValueMatcher.java deleted file mode 100644 index 821d1269..00000000 --- a/vtm/src/org/oscim/theme/rule/MultiValueMatcher.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import java.util.List; - -import org.oscim.core.Tag; - -class MultiValueMatcher implements AttributeMatcher { - private final String[] mValues; - - MultiValueMatcher(List values) { - mValues = new String[values.size()]; - for (int i = 0, n = mValues.length; i < n; ++i) { - mValues[i] = values.get(i).intern(); - } - } - - @Override - public boolean isCoveredBy(AttributeMatcher attributeMatcher) { - if (attributeMatcher == this) { - return true; - } - Tag[] tags = new Tag[mValues.length]; - - int i = 0; - for (String val : mValues) { - tags[i++] = new Tag(null, val); - } - return attributeMatcher.matches(tags); - } - - @Override - public boolean matches(Tag[] tags) { - for (Tag tag : tags) - for (String val : mValues) - if (val == tag.value) - return true; - - return false; - } -} diff --git a/vtm/src/org/oscim/theme/rule/NegativeMatcher.java b/vtm/src/org/oscim/theme/rule/NegativeMatcher.java deleted file mode 100644 index d859bd4e..00000000 --- a/vtm/src/org/oscim/theme/rule/NegativeMatcher.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import java.util.List; - -import org.oscim.core.Tag; - -class NegativeMatcher implements AttributeMatcher { - private final String[] mKeyList; - private final String[] mValueList; - - // (-) 'exclusive negation' matches when either KEY is not present - // or KEY is present and any VALUE is NOT present - // - // (\) 'except negation' matches when KEY is present - // none items of VALUE is present (TODO). - // (can be emulated by ...) - // - // (~) 'non-exclusive negation' matches when either KEY is not present - // or KEY is present and any VALUE is present - // - private final boolean mExclusive; - - NegativeMatcher(List keyList, List valueList, boolean exclusive) { - mKeyList = new String[keyList.size()]; - for (int i = 0; i < mKeyList.length; i++) - mKeyList[i] = keyList.get(i).intern(); - - mValueList = new String[valueList.size()]; - for (int i = 0; i < mValueList.length; i++) - mValueList[i] = valueList.get(i).intern(); - - mExclusive = exclusive; - } - - @Override - public boolean isCoveredBy(AttributeMatcher attributeMatcher) { - return false; - } - - @Override - public boolean matches(Tag[] tags) { - if (keyListDoesNotContainKeys(tags)) - return true; - - for (Tag tag : tags) - for (String value : mValueList) - if (value == tag.value) - return !mExclusive; - - return mExclusive; - } - - private boolean keyListDoesNotContainKeys(Tag[] tags) { - for (Tag tag : tags) - for (String key : mKeyList) - if (key == tag.key) - return false; - - return true; - } -} diff --git a/vtm/src/org/oscim/theme/rule/NegativeRule.java b/vtm/src/org/oscim/theme/rule/NegativeRule.java index ce750aaa..9454a009 100644 --- a/vtm/src/org/oscim/theme/rule/NegativeRule.java +++ b/vtm/src/org/oscim/theme/rule/NegativeRule.java @@ -18,20 +18,61 @@ package org.oscim.theme.rule; import org.oscim.core.Tag; +import org.oscim.theme.rule.RuleBuilder.RuleType; import org.oscim.theme.styles.RenderStyle; class NegativeRule extends Rule { - final AttributeMatcher mAttributeMatcher; - NegativeRule(int element, int zoom, int selector, AttributeMatcher attributeMatcher, + public final String[] keys; + public final String[] values; + + /* (-) 'exclusive negation' matches when either KEY is not present + * or KEY is present and any VALUE is NOT present + * + * (\) 'except negation' matches when KEY is present + * none items of VALUE is present (TODO). + * (can be emulated by ...) + * + * (~) 'non-exclusive negation' matches when either KEY is not present + * or KEY is present and any VALUE is present */ + + public final boolean exclusive; + + NegativeRule(RuleType type, int element, int zoom, int selector, + String[] keys, String[] values, Rule[] subRules, RenderStyle[] styles) { super(element, zoom, selector, subRules, styles); - mAttributeMatcher = attributeMatcher; + for (int i = 0; i < keys.length; i++) + keys[i] = keys[i].intern(); + + for (int i = 0; i < values.length; i++) + values[i] = values[i].intern(); + + this.keys = keys; + this.values = values; + this.exclusive = type == RuleType.EXCLUDE; } @Override - boolean matchesTags(Tag[] tags) { - return mAttributeMatcher.matches(tags); + public boolean matchesTags(Tag[] tags) { + if (keyListDoesNotContainKeys(tags)) + return true; + + for (Tag tag : tags) + for (String value : values) + if (value == tag.value) + return !exclusive; + + return exclusive; + } + + private boolean keyListDoesNotContainKeys(Tag[] tags) { + for (Tag tag : tags) + for (String key : keys) + if (key == tag.key) + return false; + + return true; } } diff --git a/vtm/src/org/oscim/theme/rule/PositiveRule.java b/vtm/src/org/oscim/theme/rule/PositiveRule.java index 370bcb24..59ecb111 100644 --- a/vtm/src/org/oscim/theme/rule/PositiveRule.java +++ b/vtm/src/org/oscim/theme/rule/PositiveRule.java @@ -1,5 +1,4 @@ /* - * Copyright 2010, 2011, 2012 mapsforge.org * Copyright 2013 Hannes Janetzek * * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). @@ -20,28 +19,149 @@ package org.oscim.theme.rule; import org.oscim.core.Tag; import org.oscim.theme.styles.RenderStyle; -class PositiveRule extends Rule { - final AttributeMatcher mKeyMatcher; - final AttributeMatcher mValueMatcher; +class PositiveRule { - PositiveRule(int element, int zoom, int selector, AttributeMatcher keyMatcher, - AttributeMatcher valueMatcher, Rule[] subRules, RenderStyle[] styles) { - super(element, zoom, selector, subRules, styles); + static class PositiveRuleK extends Rule { + private final String mKey; - if (keyMatcher instanceof AnyMatcher) - mKeyMatcher = null; - else - mKeyMatcher = keyMatcher; + PositiveRuleK(int element, int zoom, int selector, String key, + Rule[] subRules, RenderStyle[] styles) { - if (valueMatcher instanceof AnyMatcher) - mValueMatcher = null; - else - mValueMatcher = valueMatcher; + super(element, zoom, selector, subRules, styles); + mKey = key; + } + + @Override + boolean matchesTags(Tag[] tags) { + for (Tag tag : tags) + if (mKey == tag.key) + return true; + + return false; + } } - @Override - boolean matchesTags(Tag[] tags) { - return (mKeyMatcher == null || mKeyMatcher.matches(tags)) - && (mValueMatcher == null || mValueMatcher.matches(tags)); + static class PositiveRuleV extends Rule { + private final String mValue; + + PositiveRuleV(int element, int zoom, int selector, String value, + Rule[] subRules, RenderStyle[] styles) { + + super(element, zoom, selector, subRules, styles); + mValue = value; + } + + @Override + boolean matchesTags(Tag[] tags) { + for (Tag tag : tags) + if (mValue == tag.value) + return true; + + return false; + } + } + + static class PositiveRuleKV extends Rule { + private final String mKey; + private final String mValue; + + PositiveRuleKV(int element, int zoom, int selector, String key, String value, + Rule[] subRules, RenderStyle[] styles) { + + super(element, zoom, selector, subRules, styles); + mKey = key; + mValue = value; + } + + @Override + boolean matchesTags(Tag[] tags) { + for (Tag tag : tags) + if (mKey == tag.key) + return (mValue == tag.value); + + return false; + } + } + + static class PositiveRuleMultiKV extends Rule { + private final String mKeys[]; + private final String mValues[]; + + PositiveRuleMultiKV(int element, int zoom, int selector, String keys[], String values[], + Rule[] subRules, RenderStyle[] styles) { + + super(element, zoom, selector, subRules, styles); + if (keys.length == 0) { + mKeys = null; + } else { + for (int i = 0; i < keys.length; i++) + keys[i] = keys[i].intern(); + mKeys = keys; + } + + if (values.length == 0) { + mValues = null; + } else { + for (int i = 0; i < values.length; i++) + values[i] = values[i].intern(); + mValues = values; + } + } + + @Override + boolean matchesTags(Tag[] tags) { + if (mKeys == null) { + for (Tag tag : tags) { + for (String value : mValues) { + if (value == tag.value) + return true; + } + } + return false; + } + + for (Tag tag : tags) + for (String key : mKeys) { + if (key == tag.key) { + if (mValues == null) + return true; + + for (String value : mValues) { + if (value == tag.value) + return true; + } + } + } + return false; + } + } + + public static Rule create(int element, int zoom, int selector, + String[] keys, String values[], Rule[] subRules, RenderStyle[] styles) { + int numKeys = keys.length; + int numVals = values.length; + + if (numKeys == 0 && numVals == 0) + return new Rule(element, zoom, selector, subRules, styles); + + for (int i = 0; i < numVals; i++) + values[i] = values[i].intern(); + + for (int i = 0; i < numKeys; i++) + keys[i] = keys[i].intern(); + + if (numKeys == 1 && numKeys == 0) { + return new PositiveRuleK(element, zoom, selector, keys[0], subRules, styles); + } + + if (numKeys == 0 && numVals == 1) { + return new PositiveRuleV(element, zoom, selector, values[0], subRules, styles); + } + + if (numKeys == 1 && numVals == 1) + return new PositiveRuleKV(element, zoom, selector, keys[0], values[0], subRules, styles); + + return new PositiveRuleMultiKV(element, zoom, selector, keys, values, subRules, styles); + } } diff --git a/vtm/src/org/oscim/theme/rule/Rule.java b/vtm/src/org/oscim/theme/rule/Rule.java index 31756ca2..347792ca 100644 --- a/vtm/src/org/oscim/theme/rule/Rule.java +++ b/vtm/src/org/oscim/theme/rule/Rule.java @@ -21,7 +21,7 @@ import java.util.List; import org.oscim.core.Tag; import org.oscim.theme.styles.RenderStyle; -public abstract class Rule { +public class Rule { public final static RenderStyle[] EMPTY_STYLE = new RenderStyle[0]; public final static Rule[] EMPTY_RULES = new Rule[0]; @@ -44,7 +44,9 @@ public abstract class Rule { selectWhenMatched = (selector & Selector.WHEN_MATCHED) != 0; } - abstract boolean matchesTags(Tag[] tags); + boolean matchesTags(Tag[] tags) { + return true; + } public boolean matchElement(int type, Tag[] tags, int zoomLevel, List result) { diff --git a/vtm/src/org/oscim/theme/rule/RuleBuilder.java b/vtm/src/org/oscim/theme/rule/RuleBuilder.java index 00c3cca0..968679e5 100644 --- a/vtm/src/org/oscim/theme/rule/RuleBuilder.java +++ b/vtm/src/org/oscim/theme/rule/RuleBuilder.java @@ -1,139 +1,104 @@ package org.oscim.theme.rule; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.Stack; import org.oscim.theme.IRenderTheme.ThemeException; import org.oscim.theme.XmlThemeBuilder; import org.oscim.theme.styles.RenderStyle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; public class RuleBuilder { - boolean positiveRule; + final static Logger log = LoggerFactory.getLogger(RuleBuilder.class); + + private final static String[] EMPTY_KV = {}; + + public enum RuleType { + POSITIVE, + NEGATIVE, + EXCLUDE + } int zoom; int element; int selector; + RuleType type; - AttributeMatcher keyMatcher; - AttributeMatcher valueMatcher; + String keys[]; + String values[]; ArrayList renderStyles = new ArrayList(4); ArrayList subRules = new ArrayList(4); - private static final Map, AttributeMatcher> MATCHERS_CACHE_KEY = - new HashMap, AttributeMatcher>(); - private static final Map, AttributeMatcher> MATCHERS_CACHE_VALUE = - new HashMap, AttributeMatcher>(); - private static final String STRING_NEGATION = "~"; private static final String STRING_EXCLUSIVE = "-"; - private static final String STRING_WILDCARD = "*"; + private static final String SEPARATOR = "\\|"; + //private static final String STRING_WILDCARD = "*"; private static final int SELECT_FIRST = 1 << 0; private static final int SELECT_WHEN_MATCHED = 1 << 1; - public RuleBuilder(boolean positive, int element, int zoom, int selector, - AttributeMatcher keyMatcher, AttributeMatcher valueMatcher) { - this.positiveRule = positive; + public RuleBuilder(RuleType type, int element, int zoom, int selector, + String[] keys, String[] values) { + this.type = type; this.element = element; this.zoom = zoom; this.selector = selector; - this.keyMatcher = keyMatcher; - this.valueMatcher = valueMatcher; + this.keys = keys; + this.values = values; } - public RuleBuilder(boolean positive, AttributeMatcher keyMatcher, AttributeMatcher valueMatcher) { - this.positiveRule = positive; - this.keyMatcher = keyMatcher; - this.valueMatcher = valueMatcher; + public RuleBuilder(RuleType type, String[] keys, String[] values) { + this.element = Element.ANY; + this.zoom = ~0; + this.type = type; + this.keys = keys; + this.values = values; + } + + public RuleBuilder() { + this.type = RuleType.POSITIVE; + this.element = Element.ANY; + this.zoom = ~0; + this.keys = EMPTY_KV; + this.values = EMPTY_KV; } public static RuleBuilder create(Stack ruleStack, String keys, String values) { - List keyList = null, valueList = null; - boolean negativeRule = false; - boolean exclusionRule = false; + String[] keyList = EMPTY_KV; + String[] valueList = EMPTY_KV; + RuleType type = RuleType.POSITIVE; - AttributeMatcher keyMatcher, valueMatcher = null; - - if (values == null) { - valueMatcher = AnyMatcher.getInstance(); - } else { - valueList = new ArrayList(Arrays.asList(values.split("\\|"))); - if (valueList.remove(STRING_NEGATION)) - negativeRule = true; - else if (valueList.remove(STRING_EXCLUSIVE)) - exclusionRule = true; - else { - valueMatcher = getValueMatcher(valueList); - valueMatcher = RuleOptimizer.optimize(valueMatcher, ruleStack); + if (values != null) { + if (values.startsWith(STRING_NEGATION)) { + type = RuleType.NEGATIVE; + if (values.length() > 2) + valueList = values.substring(2) + .split(SEPARATOR); + } else if (values.startsWith(STRING_EXCLUSIVE)) { + type = RuleType.EXCLUDE; + if (values.length() > 2) + valueList = values.substring(2) + .split(SEPARATOR); + } else { + valueList = values.split(SEPARATOR); } } - if (keys == null) { - if (negativeRule || exclusionRule) { + if (keys != null) { + keyList = keys.split("\\|"); + } + + if (type != RuleType.POSITIVE) { + if (keyList == null || keyList.length == 0) { throw new ThemeException("negative rule requires key"); } - keyMatcher = AnyMatcher.getInstance(); - } else { - keyList = new ArrayList(Arrays.asList(keys.split("\\|"))); - keyMatcher = getKeyMatcher(keyList); - - if ((keyMatcher instanceof AnyMatcher) && (negativeRule || exclusionRule)) { - throw new ThemeException("negative rule requires key"); - } - - if (negativeRule) { - AttributeMatcher m = new NegativeMatcher(keyList, valueList, false); - return new RuleBuilder(false, m, null); - } else if (exclusionRule) { - AttributeMatcher m = new NegativeMatcher(keyList, valueList, true); - return new RuleBuilder(false, m, null); - } - - keyMatcher = RuleOptimizer.optimize(keyMatcher, ruleStack); } - return new RuleBuilder(true, keyMatcher, valueMatcher); - } - - private static AttributeMatcher getKeyMatcher(List keyList) { - if (STRING_WILDCARD.equals(keyList.get(0))) { - return AnyMatcher.getInstance(); - } - - AttributeMatcher attributeMatcher = MATCHERS_CACHE_KEY.get(keyList); - if (attributeMatcher == null) { - if (keyList.size() == 1) { - attributeMatcher = new SingleKeyMatcher(keyList.get(0)); - } else { - attributeMatcher = new MultiKeyMatcher(keyList); - } - MATCHERS_CACHE_KEY.put(keyList, attributeMatcher); - } - return attributeMatcher; - } - - private static AttributeMatcher getValueMatcher(List valueList) { - if (STRING_WILDCARD.equals(valueList.get(0))) { - return AnyMatcher.getInstance(); - } - - AttributeMatcher attributeMatcher = MATCHERS_CACHE_VALUE.get(valueList); - if (attributeMatcher == null) { - if (valueList.size() == 1) { - attributeMatcher = new SingleValueMatcher(valueList.get(0)); - } else { - attributeMatcher = new MultiValueMatcher(valueList); - } - MATCHERS_CACHE_VALUE.put(valueList, attributeMatcher); - } - return attributeMatcher; + return new RuleBuilder(type, keyList, valueList); } private static void validate(byte zoomMin, byte zoomMax) { @@ -211,8 +176,6 @@ public class RuleBuilder { } public Rule onComplete() { - MATCHERS_CACHE_KEY.clear(); - MATCHERS_CACHE_VALUE.clear(); RenderStyle[] styles = null; Rule[] rules = null; @@ -228,12 +191,12 @@ public class RuleBuilder { rules[i] = subRules.get(i).onComplete(); } - if (positiveRule) - return new PositiveRule(element, zoom, selector, keyMatcher, - valueMatcher, rules, styles); + if (type != RuleType.POSITIVE) + return new NegativeRule(type, element, zoom, selector, + keys, values, rules, styles); else - return new NegativeRule(element, zoom, selector, keyMatcher, - rules, styles); + return PositiveRule.create(element, zoom, selector, + keys, values, rules, styles); } public void addStyle(RenderStyle style) { diff --git a/vtm/src/org/oscim/theme/rule/RuleOptimizer.java b/vtm/src/org/oscim/theme/rule/RuleOptimizer.java deleted file mode 100644 index 5b74f873..00000000 --- a/vtm/src/org/oscim/theme/rule/RuleOptimizer.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import java.util.Stack; - -final class RuleOptimizer { - - private static AttributeMatcher optimizeKeyMatcher(AttributeMatcher attributeMatcher, - Stack ruleStack) { - for (int i = 0, n = ruleStack.size(); i < n; ++i) { - if (ruleStack.get(i).positiveRule) { - RuleBuilder positiveRule = ruleStack.get(i); - - if (positiveRule.keyMatcher != null - && positiveRule.keyMatcher.isCoveredBy(attributeMatcher)) { - return null; - } - } - } - - return attributeMatcher; - } - - private static AttributeMatcher optimizeValueMatcher( - AttributeMatcher attributeMatcher, Stack ruleStack) { - for (int i = 0, n = ruleStack.size(); i < n; ++i) { - if (ruleStack.get(i).positiveRule) { - RuleBuilder positiveRule = ruleStack.get(i); - - if (positiveRule.valueMatcher != null - && positiveRule.valueMatcher.isCoveredBy(attributeMatcher)) { - return null; - } - } - } - - return attributeMatcher; - } - - static AttributeMatcher optimize(AttributeMatcher attributeMatcher, - Stack ruleStack) { - if (attributeMatcher instanceof AnyMatcher) - return attributeMatcher;// return null; - else if (attributeMatcher instanceof NegativeMatcher) { - return attributeMatcher; - } else if (attributeMatcher instanceof SingleKeyMatcher) { - return optimizeKeyMatcher(attributeMatcher, ruleStack); - } else if (attributeMatcher instanceof SingleValueMatcher) { - return optimizeValueMatcher(attributeMatcher, ruleStack); - } else if (attributeMatcher instanceof MultiKeyMatcher) { - return optimizeKeyMatcher(attributeMatcher, ruleStack); - } else if (attributeMatcher instanceof MultiValueMatcher) { - return optimizeValueMatcher(attributeMatcher, ruleStack); - } - throw new IllegalArgumentException("unknown AttributeMatcher: " - + attributeMatcher); - } - - // static ClosedMatcher optimize(ClosedMatcher closedMatcher, Stack ruleStack) { - // if (closedMatcher == null) { - // return null; - // } - // - // if (closedMatcher instanceof AnyMatcher) { - // return null; - // } - // - // for (int i = 0, n = ruleStack.size(); i < n; ++i) { - // ClosedMatcher matcher = ruleStack.get(i).mClosedMatcher; - // if (matcher == null) - // return null; - // - // if (matcher.isCoveredBy(closedMatcher)) { - // return null; // AnyMatcher.getInstance(); - // - // } else if (!closedMatcher.isCoveredBy(ruleStack.get(i).mClosedMatcher)) { - // LOG.warning("unreachable rule (closed)"); - // } - // } - // - // return closedMatcher; - // } - // - // static ElementMatcher optimize(ElementMatcher elementMatcher, Stack ruleStack) { - // - // if (elementMatcher == null) { - // return null; - // } - // - // if (elementMatcher instanceof AnyMatcher) { - // return null; - // } - // - // for (int i = 0, n = ruleStack.size(); i < n; ++i) { - // ElementMatcher matcher = ruleStack.get(i).mElementMatcher; - // - // if (matcher == null) - // return null; - // - // if (matcher.isCoveredBy(elementMatcher)) { - // return null; // AnyMatcher.getInstance(); - // - // } else if (!elementMatcher.isCoveredBy(ruleStack.get(i).mElementMatcher)) { - // LOG.warning("unreachable rule (e)"); - // } - // } - // - // return elementMatcher; - // } - - /** - * Private constructor to prevent instantiation from other classes. - */ - private RuleOptimizer() { - // do nothing - } -} diff --git a/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java b/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java deleted file mode 100644 index 90b26088..00000000 --- a/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import org.oscim.core.Tag; - -public class SingleKeyMatcher implements AttributeMatcher { - private final String mKey; - - public SingleKeyMatcher(String key) { - mKey = key.intern(); - } - - @Override - public boolean isCoveredBy(AttributeMatcher attributeMatcher) { - Tag[] tags = { new Tag(mKey, null) }; - - return attributeMatcher == this || attributeMatcher.matches(tags); - } - - @Override - public boolean matches(Tag[] tags) { - for (Tag tag : tags) - if (mKey == tag.key) - return true; - - return false; - } -} diff --git a/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java b/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java deleted file mode 100644 index 8dc3ef7b..00000000 --- a/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Janetzek - * - * This file is part of the OpenScienceMap project (http://www.opensciencemap.org). - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.theme.rule; - -import org.oscim.core.Tag; - -public class SingleValueMatcher implements AttributeMatcher { - private final String mValue; - - public SingleValueMatcher(String value) { - mValue = value.intern(); - } - - @Override - public boolean isCoveredBy(AttributeMatcher attributeMatcher) { - Tag[] tags = { new Tag(null, mValue) }; - - return attributeMatcher == this || attributeMatcher.matches(tags); - } - - @Override - public boolean matches(Tag[] tags) { - for (Tag tag : tags) - if (mValue == tag.value) - return true; - - return false; - } -}