On Mon, Dec 14, 2009 at 11:41:05PM +0200, Marko Mäkelä wrote:
> Yet another solution would be to have a special syntax of variable
> substitution that would bypass the valueTags, say, $(var) instead of ${var}:
> 
> (type=boundary | type=multipolygon) & boundary=administrative & name=*
> { apply
>   {
>     set mkgmap:boundary_name='$(mkgmap:boundary_name)/${name}' | '${name}';
>   }
> }

I implemented this (see the attached patch).  It was easier than I thought,
and the runtime penalty should be low.

Unless someone complains, I will commit this patch tomorrow.

        Marko
Index: src/uk/me/parabola/mkgmap/osmstyle/actions/EchoAction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/actions/EchoAction.java	(revision 1436)
+++ src/uk/me/parabola/mkgmap/osmstyle/actions/EchoAction.java	(working copy)
@@ -30,7 +30,7 @@ public class EchoAction implements Actio
 	}
 
 	public void perform(Element el) {
-		String e = value.build(el);
+		String e = value.build(el, el);
 		System.err.println(el.getId() + ": " + e);
 	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/actions/NameAction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/actions/NameAction.java	(revision 1436)
+++ src/uk/me/parabola/mkgmap/osmstyle/actions/NameAction.java	(working copy)
@@ -46,7 +46,7 @@ public class NameAction implements Actio
 			return;
 		
 		for (ValueBuilder vb : names) {
-			String s = vb.build(el);
+			String s = vb.build(el, el);
 			if (s != null) {
 				el.setName(s);
 				break;
Index: src/uk/me/parabola/mkgmap/osmstyle/actions/AddTagAction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/actions/AddTagAction.java	(revision 1436)
+++ src/uk/me/parabola/mkgmap/osmstyle/actions/AddTagAction.java	(working copy)
@@ -54,7 +54,7 @@ public class AddTagAction implements Act
 		Element tags = valueTags!=null? valueTags: el;
 
 		for (ValueBuilder value : values) {
-			String newval = value.build(tags);
+			String newval = value.build(tags, el);
 			if (newval != null) {
 				el.addTag(tag, newval);
 				break;
Index: src/uk/me/parabola/mkgmap/osmstyle/actions/ValueBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/actions/ValueBuilder.java	(revision 1436)
+++ src/uk/me/parabola/mkgmap/osmstyle/actions/ValueBuilder.java	(working copy)
@@ -44,25 +44,26 @@ public class ValueBuilder {
 	 * you to make conditional replacements.
 	 *
 	 * @param el Used as a source of tags.
+	 * @param lel Used as a source of local tags.
 	 * @return The built string if all required tags are available.  If any
 	 * are missing then it returns null.
 	 */
-	public String build(Element el) {
+	public String build(Element el, Element lel) {
 		// Check early for no match and return early
 		for (ValueItem item : items) {
-			if (item.getValue(el) == null)
+			if (item.getValue(el, lel) == null)
 				return null;
 		}
 
 		// If we get here we can build the final string.  A common case
 		// is that there is just one, so return it directly.
 		if (items.size() == 1)
-			return items.get(0).getValue(el);
+			return items.get(0).getValue(el, lel);
 
 		// OK we have to construct the result.
 		StringBuilder sb = new StringBuilder();
 		for (ValueItem item : items)
-			sb.append(item.getValue(el));
+			sb.append(item.getValue(el, lel));
 
 		return sb.toString();
 	}
@@ -86,37 +87,41 @@ public class ValueBuilder {
 			return;
 		}
 
-		int state = 0;
+		char state = '\0';
 		StringBuilder text = new StringBuilder();
 		StringBuilder tagname = null;
 		for (char c : in.toCharArray()) {
 			switch (state) {
-			case 0:
+			case '\0':
 				if (c == '$') {
-					state = 1;
+					state = '$';
 				} else
 					text.append(c);
 				break;
-			case 1:
-				if (c == '{') {
+			case '$':
+				switch (c) {
+				case '{':
+				case '(':
 					if (text.length() > 0) {
 						items.add(new ValueItem(text.toString()));
 						text.setLength(0);
 					}
 					tagname = new StringBuilder();
-					state = 2;
-				} else {
-					state = 0;
+					state = (c == '{') ? '}' : ')';
+					break;
+				default:
+					state = '\0';
 					text.append('$');
 					text.append(c);
 				}
 				break;
-			case 2:
-				if (c == '}') {
+			case '}':
+			case ')':
+				if (c == state) {
 					//noinspection ConstantConditions
 					assert tagname != null;
-					addTagValue(tagname.toString());
-					state = 0;
+					addTagValue(tagname.toString(), c == ')');
+					state = '\0';
 					tagname = null;
 				} else {
 					tagname.append(c);
@@ -131,16 +136,16 @@ public class ValueBuilder {
 			items.add(new ValueItem(text.toString()));
 	}
 
-	private void addTagValue(String tagname) {
+	private void addTagValue(String tagname, boolean is_local) {
 		ValueItem item = new ValueItem();
 		if (tagname.contains("|")) {
 			String[] parts = tagname.split("\\|");
 			assert parts.length > 1;
-			item.setTagname(parts[0]);
+			item.setTagname(parts[0], is_local);
 			for (int i = 1; i < parts.length; i++)
 				addFilter(item, parts[i]);
 		} else {
-			item.setTagname(tagname);
+			item.setTagname(tagname, is_local);
 		}
 		items.add(item);
 	}
Index: src/uk/me/parabola/mkgmap/osmstyle/actions/ValueItem.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/actions/ValueItem.java	(revision 1436)
+++ src/uk/me/parabola/mkgmap/osmstyle/actions/ValueItem.java	(working copy)
@@ -26,6 +26,7 @@ import uk.me.parabola.mkgmap.reader.osm.
  */
 public class ValueItem {
 	private String tagname;
+	private boolean tagname_is_local;
 	private ValueFilter filter;
 	private String value;
 
@@ -36,12 +37,13 @@ public class ValueItem {
 		this.value = value;
 	}
 
-	public String getValue(Element el) {
+	public String getValue(Element el, Element local_el) {
 		if (tagname == null && value != null)
 			return value;   // already known
-		
+
 		if (tagname != null) {
-			String tagval = el.getTag(tagname);
+			Element e = tagname_is_local ? local_el : el;
+			String tagval = e.getTag(tagname);
 			if (filter != null)
 				value = filter.filter(tagval);
 			else
@@ -58,15 +60,20 @@ public class ValueItem {
 			filter.add(f);
 	}
 
-	public void setTagname(String tagname) {
+	public void setTagname(String tagname, boolean local) {
 		this.tagname = tagname;
+		this.tagname_is_local = local;
 	}
 
 	public String toString() {
-		if (tagname != null) {
+		if (tagname == null)
+			return value;
+		if (tagname_is_local) {
+			// TODO: don't ignore filter.
+			return "$(" + tagname + ")";
+		} else {
 			// TODO: don't ignore filter.
 			return "${" + tagname + "}";
-		} else
-			return value;
+		}
 	}
 }
Index: resources/styles/default/relations
===================================================================
--- resources/styles/default/relations	(revision 1436)
+++ resources/styles/default/relations	(working copy)
@@ -1,7 +1,22 @@
-
-#
-# You can have rules for relations.  Usually you will set tags on the
-# elements that make up the relation.
+# -------------------------------------------------------------------
+# This is the default mkgmap style file for applying rules on
+# OSM relations.  Usually you will set tags on the
+# elements that make up the relation, and the tags will be
+# processed by the rules defined in the "points" or "lines" files.
 #
+# Any line prefaced with # is a comment and will not be applied.
+# Each line is a rule, of the generalised format:
+#  OSM_tag(s)_to_match  [Garmin_type_code resolution]
+# See http://wiki.openstreetmap.org/wiki/Mkgmap/help/style_rules
+# and http://wiki.openstreetmap.org/wiki/Mkgmap/help/Custom_styles
+# for more information.
+
 # eg. type=route & route=bus { apply { set route=bus; add rn='${route_no}' ; }}
 #
+
+(type=boundary | type=multipolygon) & boundary=administrative & name=*
+{ apply
+  {
+    set mkgmap:boundary_name='$(mkgmap:boundary_name)/${name}' | '${name}';
+  }
+}
Index: resources/styles/default/lines
===================================================================
--- resources/styles/default/lines	(revision 1436)
+++ resources/styles/default/lines	(working copy)
@@ -113,7 +113,7 @@ man_made=pipeline {name '${operator}'} [
 # The following boundary styles are after the highway rules because ways
 # are frequently tagged with both and we want the highway to take priority.
 boundary=administrative
-{ name
+{ name '${mkgmap:boundary_name}' |
   '${left:country}/${right:country}' |
   '${left:state}/${right:state}' |
   '${left:district}/${right:district}' |
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to