Index: doc/options.txt
===================================================================
--- doc/options.txt	(revision 3354)
+++ doc/options.txt	(working copy)
@@ -240,6 +240,14 @@
 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.
+To activate the logging only for this info, use
+uk.me.parabola.mkgmap.osmstyle.stats.level=INFO
+in the logging properties file. 	  	
+
 ;--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: doc/styles/creating.txt
===================================================================
--- doc/styles/creating.txt	(revision 3354)
+++ doc/styles/creating.txt	(working copy)
@@ -8,6 +8,7 @@
 ++--style-file=++__path-to-style__ and the `--list-styles` option. If you see your style listed, then your style is recognized by mkgmap.
 Additional tests are performed if you use the `--check-styles` option. The type values are verified to make sure that they are valid. Further checks try to find rules which assign a routable type to a line without making it a road by assigning road_class or road_speed. This is known to cause problems with routing in routable maps. 
 Then you can test if your style is valid by using it when creating a map.
+The option `--report-style-stats` helps to analyse how often a rule expression was evaluated and how often it was true.  
 A style can be used just as it was created, but if you want to make it available to others it will be easier if you make a zip file out of it and then you just have the one file to distribute. You just can zip all files of the style. Several different styles can be placed into the same zip archive file.
 
 To use a zipped style, you can use ++--style-file=++__stylename__++.zip++. If
Index: resources/help/en/options
===================================================================
--- resources/help/en/options	(revision 3354)
+++ resources/help/en/options	(working copy)
@@ -238,6 +238,14 @@
   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.
+	To activate the logging only for this info, use
+	uk.me.parabola.mkgmap.osmstyle.stats.level=INFO
+	in the logging properties file. 	  	
+	  	
 --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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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 3354)
+++ 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();
 }
