start ThemeBuilder api

This commit is contained in:
Hannes Janetzek 2014-03-09 16:11:44 +01:00
parent 494e553ac0
commit b879830045
5 changed files with 181 additions and 21 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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();
}