Index: resources/help/en/options
===================================================================
--- resources/help/en/options	(revision 3352)
+++ resources/help/en/options	(working copy)
@@ -238,6 +238,11 @@
   available within that file. If it is also preceded by the style
   option it will only check that style.
 
+--report-style-stats
+	Issue one info message for each rule in the style file(s)
+	showing how often the rule expression was evaluated and how 
+	often the evaluation returned true.
+	  	
 --levels=levels code
 	Change the way that the levels on the map correspond to the zoom
 	levels in the device. See customisation help. The default is:
Index: src/uk/me/parabola/mkgmap/main/StyleTester.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/StyleTester.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/main/StyleTester.java	(working copy)
@@ -670,6 +670,21 @@
 					rule.setFinalizeRule(finalizeRule);
 				}
 			}
+
+			@Override
+			public Rule getFinalizeRule() {
+				Rule r = null;
+				for (Rule rule : rules){ 
+					r = rule.getFinalizeRule();
+					break;
+				}
+				return r;
+			}
+			
+			@Override
+			public void printStats(String header) {
+				// TODO Auto-generated method stub
+			}
 		}
 
 		/**
Index: src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java	(working copy)
@@ -18,6 +18,7 @@
 
 import java.util.List;
 
+import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.osmstyle.actions.Action;
 import uk.me.parabola.mkgmap.osmstyle.eval.Op;
 import uk.me.parabola.mkgmap.reader.osm.Element;
@@ -36,10 +37,13 @@
  * @author Steve Ratcliffe
  */
 public class ActionRule implements Rule {
+	private static final Logger statsLog = Logger.getLogger(ActionRule.class.getPackage().getName()+".stats");
 	private Op expression;
 	private final List<Action> actions;
 	private final GType type;
 	private Rule finalizeRule;
+	private long numEval; // count how often the expression was evaluated 
+	private long numTrue; // count how often the evaluation returned true
 
 	/** Finalize rules must not have an element type definition so the add method must never be called. */
 	private final static TypeResult finalizeTypeResult = new TypeResult() {
@@ -66,9 +70,10 @@
 	public int resolveType(int cacheId, Element el, TypeResult result) {
 		Element element = el;
 		if (expression != null) {
+			numEval++;
 			if (!expression.eval(cacheId, element))
 				return cacheId;
-				
+			numTrue++;
 			// If this is a continue and we are not to propagate the effects
 			// of the action on the element to further rules, then make
 			// a copy of the element so that the original is unsullied.
@@ -108,8 +113,10 @@
 	public void resolveType(Element el, TypeResult result) {
 		Element element = el;
 		if (expression != null) {
+			numEval++;
 			if (!expression.eval(element))
 				return;
+			numTrue++;
 			// If this is a continue and we are not to propagate the effects
 			// of the action on the element to further rules, then make
 			// a copy of the element so that the original is unsullied.
@@ -168,4 +175,13 @@
 		this.expression = expression;
 	}
 	
+	@Override
+	public Rule getFinalizeRule() {
+		return finalizeRule;
+	}
+
+	@Override
+	public void printStats(String header) {
+		statsLog.info(header,"stats (rule/evals/true)", this.toString() + "/" + numEval + "/" + numTrue);
+	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package uk.me.parabola.mkgmap.osmstyle;
 
+import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.osmstyle.eval.Op;
 import uk.me.parabola.mkgmap.reader.osm.Element;
 import uk.me.parabola.mkgmap.reader.osm.GType;
@@ -29,9 +30,13 @@
  * @author Steve Ratcliffe
  */
 public class ExpressionRule implements Rule {
+	private static final Logger statsLog = Logger.getLogger(ExpressionRule.class.getPackage().getName()+".stats");
+
 	private Op expression;
 	private final GType gtype;
 	private Rule finalizeRule;
+	private long numEval; // count how often the expression was evaluated 
+	private long numTrue; // count how often the evaluation returned true
 
 	/** Finalize rules must not have an element type definition so the add method must never be called. */
 	private final static TypeResult finalizeTypeResult = new TypeResult() {
@@ -47,7 +52,9 @@
 
 	
 	public void resolveType(Element el, TypeResult result) {
+		numEval++;
 		if (expression.eval(el)) {
+			numTrue++;
 			// expression matches
 			if (finalizeRule != null) {
 				if (gtype.isContinueSearch()) {
@@ -63,7 +70,9 @@
 	}
 
 	public int resolveType(int cacheId, Element el, TypeResult result) {
+		numEval++;
 		if (expression.eval(cacheId, el)){
+			numTrue++;
 			if (finalizeRule != null) {
 				if (gtype.isContinueSearch()) {
 					el = el.copy();
@@ -93,5 +102,14 @@
 	public void setOp(Op expression){
 		this.expression = expression;
 	}
+
+	@Override
+	public Rule getFinalizeRule() {
+		return finalizeRule;
+	}
 	
+	@Override
+	public void printStats(String header) {
+		statsLog.info(header,"stats (rule/evals/true)", this.toString() + "/" + numEval + "/" + numTrue);
+	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java	(working copy)
@@ -260,4 +260,33 @@
 		
 		compiled = false;
 	}
+
+	@Override
+	public Rule getFinalizeRule() {
+		if (rules == null) {
+			// this method must be called after prepare() is called so
+			// that we have rules to which the finalize rules can be applied
+			throw new IllegalStateException("First call prepare() before setting the finalize rules");
+		}
+		// all rules have the same finalize rule(s), so we just use the first one to extract it
+		Rule r = null;
+		for (Rule rule : rules){ 
+			r = rule.getFinalizeRule();
+			break;
+		}
+		return r;
+	}
+
+
+	@Override
+	public void printStats(String header) {
+		Rule finaleRule = null;
+		for (Rule rule : rules){ 
+			rule.printStats(header);
+			finaleRule = rule.getFinalizeRule();
+		}
+		if (finaleRule != null)
+			finaleRule.printStats(header);
+	}
+
 } 
\ No newline at end of file
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -124,6 +124,8 @@
 	private final Rule nodeRules;
 	private final Rule lineRules;
 	private final Rule polygonRules;
+	private final Rule relationRules;
+	private Style style;
 
 	private boolean driveOnLeft;
 	private boolean driveOnRight;
@@ -132,6 +134,7 @@
 	private final boolean linkPOIsToWays;
 	private final boolean mergeRoads;
 	private WrongAngleFixer wrongAngleFixer;
+	private boolean reportStyleStats;
 
 	private LineAdder lineAdder = new LineAdder() {
 		public void add(MapLine element) {
@@ -153,11 +156,12 @@
 				nameTagList.add(TagDict.getInstance().xlate(n));
 		} else 
 			nameTagList = null;
-
+		this.style = style;
 		wayRules = style.getWayRules();
 		nodeRules = style.getNodeRules();
 		lineRules = style.getLineRules();
 		polygonRules = style.getPolygonRules();
+		relationRules = style.getRelationRules();
 		
 		housenumberGenerator = new HousenumberGenerator(props);
 
@@ -180,6 +184,7 @@
 		mergeRoads = props.getProperty("no-mergeroads", false) == false;
 
 		wrongAngleFixer = new WrongAngleFixer(bbox);
+		reportStyleStats = props.getProperty("report-style-stats") != null;
 	}
 
 	/** One type result for ways to avoid recreating one for each way. */ 
@@ -504,6 +509,8 @@
 	}
 	
 	public void end() {
+		if (reportStyleStats)
+			style.reportStats();
 		setHighwayCounts();
 		findUnconnectedRoads();
 		rotateClosedWaysToFirstNode();
Index: src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java	(working copy)
@@ -568,6 +568,14 @@
 		}
 		return style;
 	}
+
+	@Override
+	public void reportStats() {
+		relations.printStats("relations");
+		nodes.printStats("points");
+		lines.printStats("lines");
+		polygons.printStats("polygons");
+	}
 	
 	public static void main(String[] args) throws FileNotFoundException {
 		String file = args[0];
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java	(working copy)
@@ -150,13 +150,13 @@
 	 */
 	protected void setupHandler(OsmHandler handler) {
 		createElementSaver();
+		createConverter();
+		
 		osmReadingHooks = pluginChain(elementSaver, getConfig());
 
 		handler.setElementSaver(elementSaver);
 		handler.setHooks(osmReadingHooks);
 
-		createConverter();
-
 		handler.setUsedTags(getUsedTags());
 
 		String deleteTagsFileName = getConfig().getProperty("delete-tags-file");
@@ -180,10 +180,12 @@
 	
 	protected OsmReadingHooks pluginChain(ElementSaver saver, EnhancedProperties props) {
 		List<OsmReadingHooks> plugins = new ArrayList<OsmReadingHooks>();
-
 		for (OsmReadingHooks p : getPossibleHooks()) {
-			if (p.init(saver, props))
+			if (p.init(saver, props)){
 				plugins.add(p);
+				if (p instanceof RelationStyleHook)
+					((RelationStyleHook) p).setStyle(style);
+			}
 		}
 
 		OsmReadingHooks hooks;
Index: src/uk/me/parabola/mkgmap/reader/osm/RelationStyleHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/RelationStyleHook.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/reader/osm/RelationStyleHook.java	(working copy)
@@ -35,10 +35,13 @@
 	public boolean init(ElementSaver saver, EnhancedProperties props) {
 		this.saver = saver;
 		nameTagList = LocatorUtil.getNameTags(props);
-		style = StyleImpl.readStyle(props);
 		return super.init(saver, props);
 	}
 
+	public void setStyle(Style style){
+		this.style = style;
+	}
+	
 	public void end() {
 		Rule relationRules = style.getRelationRules();
 		for (Relation rel : saver.getRelations().values()) {
@@ -57,8 +60,6 @@
 			}
 		}
 		super.end();
-		
-		style = null;
 	}
 
 	
Index: src/uk/me/parabola/mkgmap/reader/osm/Rule.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Rule.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/reader/osm/Rule.java	(working copy)
@@ -53,5 +53,8 @@
 	 */
 	public void setFinalizeRule(Rule finalizeRule);
 	
+	public Rule getFinalizeRule();
 	
+	public void printStats(String header);
+	
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/Style.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Style.java	(revision 3352)
+++ src/uk/me/parabola/mkgmap/reader/osm/Style.java	(working copy)
@@ -74,4 +74,6 @@
 	 * Get the tags that are used by this style.
 	 */
 	public Set<String> getUsedTags();
+	
+	public void reportStats();
 }
