OsmAnd/OsmAnd-java/src/net/osmand/render/RenderingRuleSearchRequest.java
2013-10-07 23:41:02 +02:00

258 lines
No EOL
6.6 KiB
Java

package net.osmand.render;
import net.osmand.binary.BinaryMapDataObject;
public class RenderingRuleSearchRequest {
private final RenderingRulesStorage storage;
RenderingRuleProperty[] props;
int[] values;
BinaryMapDataObject object;
float[] fvalues;
int[] savedValues;
float[] savedFvalues;
boolean searchResult = false;
public final RenderingRuleStorageProperties ALL;
public RenderingRuleSearchRequest(RenderingRulesStorage storage) {
this.storage = storage;
this.ALL = storage.PROPS;
props = storage.PROPS.getPoperties();
values = new int[props.length];
for (int i = 0; i < props.length; i++) {
if (!props[i].isColor()) {
values[i] = -1;
}
}
fvalues = new float[props.length];
setBooleanFilter(storage.PROPS.R_TEST, true);
saveState();
}
public void setStringFilter(RenderingRuleProperty p, String filter) {
assert p.isInputProperty();
values[p.getId()] = storage.getDictionaryValue(filter);
}
public void setIntFilter(RenderingRuleProperty p, int filter) {
assert p.isInputProperty();
values[p.getId()] = filter;
}
public void setBooleanFilter(RenderingRuleProperty p, boolean filter) {
assert p.isInputProperty();
values[p.getId()] = filter ? RenderingRuleProperty.TRUE_VALUE : RenderingRuleProperty.FALSE_VALUE;
}
public void saveState() {
savedValues = new int[values.length];
savedFvalues = new float[fvalues.length];
System.arraycopy(values, 0, savedValues, 0, values.length);
System.arraycopy(fvalues, 0, savedFvalues, 0, fvalues.length);
}
public void clearState() {
System.arraycopy(savedValues, 0, values, 0, values.length);
System.arraycopy(savedFvalues, 0, fvalues, 0, fvalues.length);
object = null;
}
public void clearValue(RenderingRuleProperty p) {
if(p.isIntParse()){
values[p.getId()] = savedValues[p.getId()];
} else {
fvalues[p.getId()] = savedFvalues[p.getId()];
values[p.getId()] = savedValues[p.getId()];
}
}
public BinaryMapDataObject getObject() {
return object;
}
public void setInitialTagValueZoom(String tag, String val, int zoom, BinaryMapDataObject obj){
clearState();
object = obj;
setIntFilter(ALL.R_MINZOOM, zoom);
setIntFilter(ALL.R_MAXZOOM, zoom);
setStringFilter(ALL.R_TAG, tag);
setStringFilter(ALL.R_VALUE, val);
}
public void setTagValueZoomLayer(String tag, String val, int zoom, int layer, BinaryMapDataObject obj){
object = obj;
setIntFilter(ALL.R_MINZOOM, zoom);
setIntFilter(ALL.R_MAXZOOM, zoom);
setIntFilter(ALL.R_LAYER, layer);
setStringFilter(ALL.R_TAG, tag);
setStringFilter(ALL.R_VALUE, val);
}
public boolean isFound() {
return searchResult;
}
public boolean searchRenderingAttribute(String attribute) {
searchResult = false;
RenderingRule rule = storage.getRenderingAttributeRule(attribute);
if(rule == null){
return false;
}
searchResult = visitRule(rule, true);
return searchResult;
}
public boolean search(int state) {
return search(state, true);
}
public boolean search(int state, boolean loadOutput) {
searchResult = false;
int tagKey = values[storage.PROPS.R_TAG.getId()];
int valueKey = values[storage.PROPS.R_VALUE.getId()];
boolean result = searchInternal(state, tagKey, valueKey, loadOutput);
if (result) {
searchResult = true;
return true;
}
result = searchInternal(state, tagKey, 0, loadOutput);
if (result) {
searchResult = true;
return true;
}
result = searchInternal(state, 0, 0, loadOutput);
if (result) {
searchResult = true;
return true;
}
return false;
}
private boolean searchInternal(int state, int tagKey, int valueKey, boolean loadOutput) {
values[storage.PROPS.R_TAG.getId()] = tagKey;
values[storage.PROPS.R_VALUE.getId()] = valueKey;
values[storage.PROPS.R_DISABLE.getId()] = 0;
RenderingRule accept = storage.getRule(state, tagKey, valueKey);
if (accept == null) {
return false;
}
boolean match = visitRule(accept, loadOutput);
if(match && values[storage.PROPS.R_DISABLE.getId()] != 0) {
return false;
}
return match;
}
private boolean visitRule(RenderingRule rule, boolean loadOutput) {
RenderingRuleProperty[] properties = rule.getProperties();
for (int i = 0; i < properties.length; i++) {
RenderingRuleProperty rp = properties[i];
if (rp.isInputProperty()) {
boolean match;
if (rp.isFloat()) {
match = rp.accept(rule.getFloatProp(i), fvalues[rp.getId()], this);
} else {
match = rp.accept(rule.getIntProp(i), values[rp.getId()], this);
}
if (!match) {
return false;
}
} else if(rp == storage.PROPS.R_DISABLE){
// quick disable return even without load output
values[rp.getId()] = rule.getIntProp(i);
}
}
if (!loadOutput) {
return true;
}
// accept it
for (int i = 0; i < properties.length; i++) {
RenderingRuleProperty rp = properties[i];
if (rp.isOutputProperty()) {
searchResult = true;
if (rp.isFloat()) {
fvalues[rp.getId()] = rule.getFloatProp(i);
values[rp.getId()] = rule.getIntProp(i);
} else {
values[rp.getId()] = rule.getIntProp(i);
}
}
}
for (RenderingRule rr : rule.getIfElseChildren()) {
boolean match = visitRule(rr, loadOutput);
if (match) {
break;
}
}
for(RenderingRule rr : rule.getIfChildren()){
visitRule(rr, loadOutput);
}
return true;
}
public boolean isSpecified(RenderingRuleProperty property){
if(property.isFloat()){
return fvalues[property.getId()] != 0 || values[property.getId()] != -1;
} else {
int val = values[property.getId()];
if(property.isColor()){
return val != 0;
} else {
return val != -1;
}
}
}
public RenderingRuleProperty[] getProperties() {
return props;
}
public String getStringPropertyValue(RenderingRuleProperty property) {
int val = values[property.getId()];
if(val < 0){
return null;
}
return storage.getStringValue(val);
}
public float getFloatPropertyValue(RenderingRuleProperty property) {
return fvalues[property.getId()];
}
public float getFloatPropertyValue(RenderingRuleProperty property, float defVal) {
float f = fvalues[property.getId()];
if(f == 0) {
return defVal;
}
return f;
}
public String getColorStringPropertyValue(RenderingRuleProperty property) {
return RenderingRuleProperty.colorToString(values[property.getId()]);
}
public int getIntPropertyValue(RenderingRuleProperty property) {
return values[property.getId()];
}
public int getIntPropertyValue(RenderingRuleProperty property, int defValue) {
int val = values[property.getId()];
return val == -1 ? defValue : val;
}
/**/ RenderingRulesStorage getStorage() {
return storage;
}
}