From b879830045dc05271413e96f0fd90dff460b1823 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek <hannes.janetzek@gmail.com> Date: Sun, 9 Mar 2014 16:11:44 +0100 Subject: [PATCH] start ThemeBuilder api --- vtm/src/org/oscim/theme/ThemeBuilder.java | 125 ++++++++++++++++++ vtm/src/org/oscim/theme/XmlThemeBuilder.java | 4 +- vtm/src/org/oscim/theme/rule/RuleBuilder.java | 65 ++++++--- .../oscim/theme/rule/SingleKeyMatcher.java | 4 +- .../oscim/theme/rule/SingleValueMatcher.java | 4 +- 5 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 vtm/src/org/oscim/theme/ThemeBuilder.java diff --git a/vtm/src/org/oscim/theme/ThemeBuilder.java b/vtm/src/org/oscim/theme/ThemeBuilder.java new file mode 100644 index 00000000..cdb1481d --- /dev/null +++ b/vtm/src/org/oscim/theme/ThemeBuilder.java @@ -0,0 +1,125 @@ +package org.oscim.theme; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Stack; + +import org.oscim.core.GeometryBuffer.GeometryType; +import org.oscim.core.Tag; +import org.oscim.core.TagSet; +import org.oscim.theme.rule.Element; +import org.oscim.theme.rule.Rule; +import org.oscim.theme.rule.RuleBuilder; +import org.oscim.theme.rule.Selector; +import org.oscim.theme.rule.SingleKeyMatcher; +import org.oscim.theme.rule.SingleValueMatcher; +import org.oscim.theme.styles.Area; +import org.oscim.theme.styles.Line; +import org.oscim.theme.styles.RenderStyle; + +public class ThemeBuilder { + protected final ArrayList<RuleBuilder> mRulesList = new ArrayList<RuleBuilder>(); + protected final Stack<RuleBuilder> mRuleStack = new Stack<RuleBuilder>(); + + protected int mLevels = 0; + protected int mMapBackground = 0xffffffff; + protected float mBaseTextSize = 1; + + protected RuleBuilder mCurrentRule; + + protected RenderTheme build() { + + Rule[] rules = new Rule[mRulesList.size()]; + for (int i = 0, n = rules.length; i < n; i++) + rules[i] = mRulesList.get(i).onComplete(); + + RenderTheme theme = new RenderTheme(mMapBackground, mBaseTextSize, rules, mLevels); + + mRulesList.clear(); + mRuleStack.clear(); + + return theme; + } + + public ThemeBuilder pop() { + + mRuleStack.pop(); + if (mRuleStack.empty()) { + mRulesList.add(mCurrentRule); + } else { + mCurrentRule = mRuleStack.peek(); + } + return this; + } + + public ThemeBuilder push(RuleBuilder rule) { + if (!mRuleStack.empty()) + mCurrentRule.addSubRule(rule); + + mCurrentRule = rule; + mRuleStack.push(mCurrentRule); + + return this; + } + + public ThemeBuilder push(String key, String value) { + RuleBuilder b = new RuleBuilder(true, Element.ANY, ~0, 0, + key == null ? null : new SingleKeyMatcher(key), + value == null ? null : new SingleValueMatcher(value)); + push(b); + return this; + } + + public RuleBuilder pushParse(String keys, String values) { + + return RuleBuilder.create(mRuleStack, keys, values) + .zoom(~0) + .element(Element.ANY); + } + + public ThemeBuilder addStyle(RenderStyle style) { + mCurrentRule.addStyle(style); + return this; + } + + public static void main(String[] args) { + + ThemeBuilder b = new ThemeBuilder(); + + //b.pushParse("highway", "residential|primary|motorway") + + b.push(RuleBuilder.get().select(Selector.FIRST)) + .push("highway", null) + .addStyle(new Line(1, 1, 1)) + .pop() + + .push(RuleBuilder.get().select(Selector.WHEN_MATCHED)) + .addStyle(new Area(1, 1)) + .pop() + .pop(); + + RenderTheme t = b.build(); + TagSet tags = new TagSet(1); + RenderStyle[] styles; + + tags.add(new Tag("ahighway", "residential")); + styles = t.matchElement(GeometryType.LINE, tags, 1); + System.out.println(Arrays.deepToString(styles)); + + // tags.clear(); + // tags.add(new Tag("highway", "motorway")); + // styles = t.matchElement(GeometryType.LINE, tags, 1); + // out.println(styles); + // + // tags.clear(); + // tags.add(new Tag("sup", "wup")); + // styles = t.matchElement(GeometryType.LINE, tags, 1); + // out.println(styles); + // + // tags.clear(); + // tags.add(new Tag("highway", "motorway")); + // styles = t.matchElement(GeometryType.LINE, tags, 1); + // out.println(styles); + + } +} diff --git a/vtm/src/org/oscim/theme/XmlThemeBuilder.java b/vtm/src/org/oscim/theme/XmlThemeBuilder.java index bfaf9521..e22f56b1 100644 --- a/vtm/src/org/oscim/theme/XmlThemeBuilder.java +++ b/vtm/src/org/oscim/theme/XmlThemeBuilder.java @@ -863,13 +863,13 @@ public class XmlThemeBuilder extends DefaultHandler { return new Extrusion(level, colorSide, colorTop, colorLine, defaultHeight); } - private static void validateNonNegative(String name, float value) { + public static void validateNonNegative(String name, float value) { if (value < 0) throw new ThemeException(name + " must not be negative: " + value); } - private static void validateExists(String name, Object obj, String elementName) { + public static void validateExists(String name, Object obj, String elementName) { if (obj == null) throw new ThemeException("missing attribute " + name + " for element: " + elementName); diff --git a/vtm/src/org/oscim/theme/rule/RuleBuilder.java b/vtm/src/org/oscim/theme/rule/RuleBuilder.java index 6f80b9b8..00c3cca0 100644 --- a/vtm/src/org/oscim/theme/rule/RuleBuilder.java +++ b/vtm/src/org/oscim/theme/rule/RuleBuilder.java @@ -47,13 +47,13 @@ public class RuleBuilder { this.valueMatcher = valueMatcher; } - private static RuleBuilder createRule(Stack<RuleBuilder> ruleStack, int element, String keys, - String values, byte zoomMin, byte zoomMax, int selector) { + public RuleBuilder(boolean positive, AttributeMatcher keyMatcher, AttributeMatcher valueMatcher) { + this.positiveRule = positive; + this.keyMatcher = keyMatcher; + this.valueMatcher = valueMatcher; + } - // zoom-level bitmask - int zoom = 0; - for (int z = zoomMin; z <= zoomMax && z < 32; z++) - zoom |= (1 << z); + public static RuleBuilder create(Stack<RuleBuilder> ruleStack, String keys, String values) { List<String> keyList = null, valueList = null; boolean negativeRule = false; @@ -90,16 +90,16 @@ public class RuleBuilder { if (negativeRule) { AttributeMatcher m = new NegativeMatcher(keyList, valueList, false); - return new RuleBuilder(false, element, zoom, selector, m, null); + return new RuleBuilder(false, m, null); } else if (exclusionRule) { AttributeMatcher m = new NegativeMatcher(keyList, valueList, true); - return new RuleBuilder(false, element, zoom, selector, m, null); + return new RuleBuilder(false, m, null); } keyMatcher = RuleOptimizer.optimize(keyMatcher, ruleStack); } - return new RuleBuilder(true, element, zoom, selector, keyMatcher, valueMatcher); + return new RuleBuilder(true, keyMatcher, valueMatcher); } private static AttributeMatcher getKeyMatcher(List<String> keyList) { @@ -137,11 +137,9 @@ public class RuleBuilder { } private static void validate(byte zoomMin, byte zoomMax) { - if (zoomMin < 0) - throw new ThemeException("zoom-min must not be negative: " + zoomMin); - else if (zoomMax < 0) - throw new ThemeException("zoom-max must not be negative: " + zoomMax); - else if (zoomMin > zoomMax) + XmlThemeBuilder.validateNonNegative("zoom-min", zoomMin); + XmlThemeBuilder.validateNonNegative("zoom-max", zoomMax); + if (zoomMin > zoomMax) throw new ThemeException("zoom-min must be less or equal zoom-max: " + zoomMin); } @@ -196,7 +194,20 @@ public class RuleBuilder { validate(zoomMin, zoomMax); - return createRule(ruleStack, element, keys, values, zoomMin, zoomMax, selector); + RuleBuilder b = create(ruleStack, keys, values); + b.setZoom(zoomMin, zoomMax); + b.element = element; + b.selector = selector; + return b; + } + + public RuleBuilder setZoom(byte zoomMin, byte zoomMax) { + // zoom-level bitmask + zoom = 0; + for (int z = zoomMin; z <= zoomMax && z < 32; z++) + zoom |= (1 << z); + + return this; } public Rule onComplete() { @@ -233,4 +244,28 @@ public class RuleBuilder { subRules.add(rule); } + RuleBuilder(boolean positive) { + this.positiveRule = positive; + this.element = Element.ANY; + this.zoom = ~0; + } + + public static RuleBuilder get() { + return new RuleBuilder(true); + } + + public RuleBuilder select(int selector) { + this.selector = selector; + return this; + } + + public RuleBuilder zoom(int zoom) { + this.zoom = zoom; + return this; + } + + public RuleBuilder element(int element) { + this.element = element; + return this; + } } diff --git a/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java b/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java index 12eda8a5..90b26088 100644 --- a/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java +++ b/vtm/src/org/oscim/theme/rule/SingleKeyMatcher.java @@ -19,10 +19,10 @@ package org.oscim.theme.rule; import org.oscim.core.Tag; -class SingleKeyMatcher implements AttributeMatcher { +public class SingleKeyMatcher implements AttributeMatcher { private final String mKey; - SingleKeyMatcher(String key) { + public SingleKeyMatcher(String key) { mKey = key.intern(); } diff --git a/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java b/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java index 5327bf56..8dc3ef7b 100644 --- a/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java +++ b/vtm/src/org/oscim/theme/rule/SingleValueMatcher.java @@ -19,10 +19,10 @@ package org.oscim.theme.rule; import org.oscim.core.Tag; -class SingleValueMatcher implements AttributeMatcher { +public class SingleValueMatcher implements AttributeMatcher { private final String mValue; - SingleValueMatcher(String value) { + public SingleValueMatcher(String value) { mValue = value.intern(); }