/*
* Copyright 2010, 2011, 2012 mapsforge.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 <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.map.rendertheme.rule;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mapsforge.core.model.Tag;
import org.mapsforge.map.rendertheme.RenderCallback;
import org.mapsforge.map.rendertheme.renderinstruction.RenderInstruction;
abstract class Rule {
static final Map<List<String>, AttributeMatcher> MATCHERS_CACHE_KEY = new HashMap<List<String>, AttributeMatcher>();
static final Map<List<String>, AttributeMatcher> MATCHERS_CACHE_VALUE = new HashMap<List<String>, AttributeMatcher>();
private final ArrayList<RenderInstruction> renderInstructions;
private final ArrayList<Rule> subRules;
final ClosedMatcher closedMatcher;
final ElementMatcher elementMatcher;
final byte zoomMax;
final byte zoomMin;
Rule(RuleBuilder ruleBuilder) {
this.closedMatcher = ruleBuilder.closedMatcher;
this.elementMatcher = ruleBuilder.elementMatcher;
this.zoomMax = ruleBuilder.zoomMax;
this.zoomMin = ruleBuilder.zoomMin;
this.renderInstructions = new ArrayList<RenderInstruction>(4);
this.subRules = new ArrayList<Rule>(4);
}
void addRenderingInstruction(RenderInstruction renderInstruction) {
this.renderInstructions.add(renderInstruction);
}
void addSubRule(Rule rule) {
this.subRules.add(rule);
}
abstract boolean matchesNode(List<Tag> tags, byte zoomLevel);
abstract boolean matchesWay(List<Tag> tags, byte zoomLevel, Closed closed);
void matchNode(RenderCallback renderCallback, List<Tag> tags, byte zoomLevel) {
if (matchesNode(tags, zoomLevel)) {
for (int i = 0, n = this.renderInstructions.size(); i < n; ++i) {
this.renderInstructions.get(i).renderNode(renderCallback, tags);
}
for (int i = 0, n = this.subRules.size(); i < n; ++i) {
this.subRules.get(i).matchNode(renderCallback, tags, zoomLevel);
}
}
}
void matchWay(RenderCallback renderCallback, List<Tag> tags, byte zoomLevel, Closed closed,
List<RenderInstruction> matchingList) {
if (matchesWay(tags, zoomLevel, closed)) {
for (int i = 0, n = this.renderInstructions.size(); i < n; ++i) {
this.renderInstructions.get(i).renderWay(renderCallback, tags);
matchingList.add(this.renderInstructions.get(i));
}
for (int i = 0, n = this.subRules.size(); i < n; ++i) {
this.subRules.get(i).matchWay(renderCallback, tags, zoomLevel, closed, matchingList);
}
}
}
void onComplete() {
MATCHERS_CACHE_KEY.clear();
MATCHERS_CACHE_VALUE.clear();
this.renderInstructions.trimToSize();
this.subRules.trimToSize();
for (int i = 0, n = this.subRules.size(); i < n; ++i) {
this.subRules.get(i).onComplete();
}
}
void onDestroy() {
for (int i = 0, n = this.renderInstructions.size(); i < n; ++i) {
this.renderInstructions.get(i).destroy();
}
for (int i = 0, n = this.subRules.size(); i < n; ++i) {
this.subRules.get(i).onDestroy();
}
}
void scaleStrokeWidth(float scaleFactor) {
for (int i = 0, n = this.renderInstructions.size(); i < n; ++i) {
this.renderInstructions.get(i).scaleStrokeWidth(scaleFactor);
}
for (int i = 0, n = this.subRules.size(); i < n; ++i) {
this.subRules.get(i).scaleStrokeWidth(scaleFactor);
}
}
void scaleTextSize(float scaleFactor) {
for (int i = 0, n = this.renderInstructions.size(); i < n; ++i) {
this.renderInstructions.get(i).scaleTextSize(scaleFactor);
}
for (int i = 0, n = this.subRules.size(); i < n; ++i) {
this.subRules.get(i).scaleTextSize(scaleFactor);
}
}
}