What if we extend the mkgmap style language with an 'import' or
'include' directive familiar from other languages? There already is the
base-style directive (used in resources/styles/marine/info), but it
allows a style to import only one other style.
There is no real reason why it should be restricted to one. Attached
patch fixes that.
If you have a style "c" which has
base-style: a
base-style: b
Then style c will pull in the rules from a and b, so that rules
in c will come first, followed by those in b and then those in a.
They are in reverse order because the rule that matches is first is
the one that gets picked and we want c to override b and b to override a.
Both a and b can have their own base-style options and so on, as now.
..Steve
Index: src/uk/me/parabola/mkgmap/osmstyle/StylePrinter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StylePrinter.java (revision 2063)
+++ src/uk/me/parabola/mkgmap/osmstyle/StylePrinter.java (revision )
@@ -3,6 +3,7 @@
import java.io.Writer;
import java.util.Formatter;
import java.util.Map;
+import java.util.Map.Entry;
import uk.me.parabola.mkgmap.reader.osm.Rule;
import uk.me.parabola.mkgmap.reader.osm.Style;
@@ -59,7 +60,7 @@
fmt.format("name-tag-list: %s\n", fmtArray(style.getNameTagList()));
if (generalOptions != null) {
- for (Map.Entry<String, String> entry : generalOptions.entrySet())
+ for (Entry<String, String> entry : generalOptions.entrySet())
fmt.format("%s: %s\n", entry.getKey(), entry.getValue());
}
}
@@ -69,8 +70,12 @@
StyleInfo styleInfo = style.getInfo();
fmt.format("version %s\n", dumpInfoVal(styleInfo.getVersion()));
fmt.format("summary %s\n", dumpInfoVal(styleInfo.getSummary()));
- if (styleInfo.getBaseStyleName() != null)
- fmt.format("base-style %s\n", dumpInfoVal(styleInfo.getBaseStyleName()));
+
+ // The base styles are combined already, so should not be output. Retained as comments for
+ // documentation/testing purposes.
+ for (String name : styleInfo.baseStyles())
+ fmt.format("# base-style %s\n", dumpInfoVal(name));
+
fmt.format("description %s\n", dumpInfoVal(styleInfo.getLongDescription()));
}
Index: test/uk/me/parabola/mkgmap/osmstyle/StyledConverterTest.java
===================================================================
--- test/uk/me/parabola/mkgmap/osmstyle/StyledConverterTest.java (revision 2063)
+++ test/uk/me/parabola/mkgmap/osmstyle/StyledConverterTest.java (revision )
@@ -144,6 +144,44 @@
}
@Test
+ public void testMultipleBase() throws FileNotFoundException {
+ converter = makeConverter("d");
+
+ convertTag("a", "a");
+ assertEquals(1, lines.get(0).getType());
+
+ convertTag("b", "b");
+ assertEquals(1, lines.get(0).getType());
+
+ convertTag("c", "c");
+ assertEquals(1, lines.get(0).getType());
+
+ convertTag("d", "d");
+ assertEquals(1, lines.get(0).getType());
+
+ convertTag("override", "ab");
+ assertEquals(2, lines.get(0).getType());
+
+ for (String s : new String[]{"ac", "bc"}) {
+ convertTag("override", s);
+ assertEquals(3, lines.get(0).getType());
+ }
+
+ for (String s : new String[]{"ad", "bd", "cd"}) {
+ convertTag("override", s);
+ assertEquals(4, lines.get(0).getType());
+ }
+ }
+
+ private Way convertTag(String key, String value) {
+ lines.clear();
+ Way way = makeWay();
+ way.addTag(key, value);
+ converter.convertWay(way);
+ return way;
+ }
+
+ @Test
public void testFileConflicts() throws FileNotFoundException {
converter = makeConverter("waycombine");
Way w = makeWay();
Index: .idea/dictionaries/steve.xml
===================================================================
--- .idea/dictionaries/steve.xml (revision 2063)
+++ .idea/dictionaries/steve.xml (revision )
@@ -32,6 +32,7 @@
<w>gmapsupp</w>
<w>gpsmapedit</w>
<w>gtype</w>
+ <w>gtypes</w>
<w>hashlist</w>
<w>heibler</w>
<w>imgfmt</w>
@@ -97,6 +98,7 @@
<w>xcharset</w>
<w>xcode</w>
<w>xmlattr</w>
+ <w>zip'ed</w>
<w>zoraster</w>
</words>
</dictionary>
Index: src/uk/me/parabola/mkgmap/reader/osm/StyleInfo.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/StyleInfo.java (revision 2063)
+++ src/uk/me/parabola/mkgmap/reader/osm/StyleInfo.java (revision )
@@ -16,6 +16,9 @@
*/
package uk.me.parabola.mkgmap.reader.osm;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Information about a style. This is so style authors can include
* descriptions of their styles within the style itself.
@@ -27,7 +30,7 @@
private String version;
private String summary;
private String longDescription;
- private String baseStyleName;
+ private final List<String> baseStyleNames = new ArrayList<String>();
public String getSummary() {
@@ -54,11 +57,11 @@
this.longDescription = longDescription;
}
- public String getBaseStyleName() {
- return baseStyleName;
+ public Iterable<String> baseStyles() {
+ return baseStyleNames;
}
- public void setBaseStyleName(String value) {
- this.baseStyleName = value.trim();
+ public void addBaseStyleName(String name) {
+ baseStyleNames.add(name.trim());
}
}
Index: src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java (revision 2063)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java (revision )
@@ -31,7 +31,9 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
@@ -101,7 +103,7 @@
private StyleInfo info = new StyleInfo();
// Set if this style is based on another one.
- private StyleImpl baseStyle;
+ private final List<StyleImpl> baseStyles = new ArrayList<StyleImpl>();
// A list of tag names to be used as the element name
private String[] nameTagList;
@@ -134,18 +136,26 @@
readInfo();
- readBaseStyle();
- if (baseStyle != null)
- mergeStyle(baseStyle);
+ for (String baseName : info.baseStyles())
+ readBaseStyle(baseName);
+ for (StyleImpl baseStyle : baseStyles)
+ mergeOptions(baseStyle);
+
readOptions();
readRules();
readOverlays();
readMapFeatures();
- if (baseStyle != null)
- mergeRules(baseStyle);
+
+ ListIterator<StyleImpl> listIterator = baseStyles.listIterator(baseStyles.size());
+ while (listIterator.hasPrevious())
+ mergeRules(listIterator.previous());
+
+ // OR: other way
+ //for (StyleImpl s : baseStyles)
+ // mergeRules(s);
}
public String[] getNameTagList() {
@@ -170,8 +180,8 @@
* @param config The command line options.
*/
public void applyOptionOverride(Properties config) {
- Set<Map.Entry<Object,Object>> entries = config.entrySet();
- for (Map.Entry<Object,Object> ent : entries) {
+ Set<Entry<Object,Object>> entries = config.entrySet();
+ for (Entry<Object,Object> ent : entries) {
String key = (String) ent.getKey();
String val = (String) ent.getValue();
@@ -345,13 +355,13 @@
private void initFromMapFeatures(MapFeatureReader mfr) {
addBackwardCompatibleRules();
- for (Map.Entry<String, GType> me : mfr.getLineFeatures().entrySet())
+ for (Entry<String, GType> me : mfr.getLineFeatures().entrySet())
lines.add(me.getKey(), createRule(me.getKey(), me.getValue()), Collections.<String>emptySet());
- for (Map.Entry<String, GType> me : mfr.getShapeFeatures().entrySet())
+ for (Entry<String, GType> me : mfr.getShapeFeatures().entrySet())
polygons.add(me.getKey(), createRule(me.getKey(), me.getValue()), Collections.<String>emptySet());
- for (Map.Entry<String, GType> me : mfr.getPointFeatures().entrySet())
+ for (Entry<String, GType> me : mfr.getPointFeatures().entrySet())
nodes.add(me.getKey(), createRule(me.getKey(), me.getValue()), Collections.<String>emptySet());
}
@@ -463,7 +473,7 @@
else if (word.equals("version")) {
info.setVersion(value);
} else if (word.equals("base-style")) {
- info.setBaseStyleName(value);
+ info.addBaseStyleName(value);
} else if (word.equals("description")) {
info.setLongDescription(value);
}
@@ -498,14 +508,14 @@
* the current styles 'info' section and any option or rule specified
* in the current style will override any corresponding item in the
* base style.
+ * @param name The name of the base style
*/
- private void readBaseStyle() {
- String name = info.getBaseStyleName();
+ private void readBaseStyle(String name) {
if (name == null)
return;
try {
- baseStyle = new StyleImpl(location, name);
+ baseStyles.add(new StyleImpl(location, name));
} catch (SyntaxException e) {
System.err.println("Error in style: " + e.getMessage());
} catch (FileNotFoundException e) {
@@ -515,31 +525,28 @@
log.debug("could not open base style file", e);
try {
- baseStyle = new StyleImpl(null, name);
+ baseStyles.add(new StyleImpl(null, name));
} catch (SyntaxException se) {
System.err.println("Error in style: " + se.getMessage());
} catch (FileNotFoundException e1) {
- baseStyle = null;
log.error("Could not find base style", e);
}
}
}
/**
- * Merge another style into this one. The style will have a lower
- * priority, in other words if rules in the current style match the
- * 'other' one, then the current rule wins.
+ * Merge another style's options into this one. The style will have a lower
+ * priority, in other words any option set in 'other' and this style will
+ * take the value given in this style.
*
- * This is called from the options file, and options from the other
- * file are processed as if they were included in the current option
- * file at the point of inclusion.
- *
* This is used to base styles on other ones, without having to repeat
* everything.
+ *
+ * @see #mergeRules(StyleImpl)
*/
- private void mergeStyle(StyleImpl other) {
+ private void mergeOptions(StyleImpl other) {
this.nameTagList = other.nameTagList;
- for (Map.Entry<String, String> ent : other.generalOptions.entrySet()) {
+ for (Entry<String, String> ent : other.generalOptions.entrySet()) {
String opt = ent.getKey();
String val = ent.getValue();
if (opt.equals("name-tag-list")) {
@@ -560,6 +567,11 @@
/**
* Merge rules from the base style. This has to called after this
* style's rules are read.
+ *
+ * The other rules have a lower priority than the rules in this file; it is as if they
+ * were appended to the rule files of this style.
+ *
+ * @see #mergeOptions(StyleImpl)
*/
private void mergeRules(StyleImpl other) {
lines.merge(other.lines);
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev