diff --git a/README.md b/README.md index bada6aa..40f93a7 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,24 @@ # JosmTemplateParser +## Grammar + +`{key}` - insert the _value_ of the tag that corresponds to _key_ . + +`{%key}` - insert the _display value_ of the tag corresponding to _key_ if one is available, otherwise just insert the _value_ _(this is an extension)_ . + +`?{condition1 'value1' | condition2 'value2' | 'value3'}` - use value1 if condition1 is satisfied, else use value2 if condition2 is satisfied, finally use value3 if no condition is satisfied. Condition can be either explicit - in JOSM search syntax - or implicit: The value is used when all tags referenced inside exist. + +`!{search_expression 'template'}` - search_expression is evaluated and first matching primitive is used as context for template. Useful for example to get tags of parent relation. + +`\` - use a backslash to escape special characters '{', '}', '?', '!'. E.g. What is this\? It is a `{type}\!`. + +`{special:everything}` - prints all available values, output is implementation dependent. + +`{special:id}` - prints the ID of the OSM element. + +`{special:localName}` - prints the localized name, that is the value of _name:lang_ for your language if it is available, or the value of _name_ if it is not. + ## Usage @@ -35,6 +53,6 @@ You can either download the jar from github or add the following to your build.g dependencies { ... - compile 'ch.poole.osm:JosmTemplateParser:0.2.0' + compile 'ch.poole.osm:JosmTemplateParser:0.3.0' ... } diff --git a/build.gradle b/build.gradle index db06c33..98789a5 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ apply plugin: 'maven-publish' apply plugin: 'signing' -version = '0.2.0' +version = '0.3.0' java { sourceCompatibility = JavaVersion.VERSION_1_8 @@ -143,8 +143,8 @@ repositories { // In this section you declare the dependencies for your production and test code dependencies { - implementation "ch.poole.osm:JosmFilterParser:0.9.0" + implementation "ch.poole.osm:JosmFilterParser:0.14.0" compileOnly 'org.jetbrains:annotations:15.0' testCompileOnly 'org.jetbrains:annotations:15.0' - testCompileOnly 'junit:junit:4.12' + testImplementation 'junit:junit:4.12' } diff --git a/src/main/java/ch/poole/osm/josmtemplateparser/JosmTemplateParser.jj b/src/main/java/ch/poole/osm/josmtemplateparser/JosmTemplateParser.jj index 5029a2d..7144bbf 100644 --- a/src/main/java/ch/poole/osm/josmtemplateparser/JosmTemplateParser.jj +++ b/src/main/java/ch/poole/osm/josmtemplateparser/JosmTemplateParser.jj @@ -48,18 +48,21 @@ import java.util.Locale; import java.util.Stack; /** - {tag} - insert the value of the tag. + {key} - insert the value of the tag that corresponds to key. + {%key} - insert the display value of the tag corresponding to key if one is available, otherwise just insert the value (this is an extension) . ?{condition1 'value1' | condition2 'value2' | 'value3'} - use value1 if condition1 is satisfied, else use value2 if condition2 is satisfied, finally use value3 if no condition is satisfied. Condition can be either explicit - in JOSM search syntax - or implicit: The value is used when all tags referenced inside exist. !{search_expression 'template'} - search_expression is evaluated and first matching primitive is used as context for template. Useful for example to get tags of parent relation. \ - use a backslash to escape special characters '{', '}', '?', '!'. E.g. What is this\? It is a {type}\!. - {special:everything} prints all available values, available for formatting of both primitives and waypoints. - {special:id} prints the ID of the osm primitive. - {special:localName} prints the localized name, that is the value of name:lang for your language if it is available, or the value of name if it is not. + {special:everything} - prints all available values, output is implementation dependent. + {special:id} - prints the ID of the OSM element. + {special:localName} - prints the localized name, that is the value of name:lang for your language if it is available, or the value of name if it is not. */ public class JosmTemplateParser { - Stack < Boolean > startParen = new Stack < Boolean > (); + private static final String USE_DISPLAY_VALUE = "%"; // extension + + private Stack < Boolean > startParen = new Stack < Boolean > (); public List < Formatter > formatters() throws JosmTemplateParseException { @@ -140,7 +143,7 @@ TOKEN : < DEFAULT > TOKEN : { - < LITERAL : (~[ "\'", "\\", "?", "!", "|", "{", "}" ])+ > + < LITERAL : (~[ "\'", "\\", "?", "!", "|", "{", "}"])+ > } /** @@ -154,7 +157,7 @@ String literal() : t = < LITERAL > { return t.image; - } + } } /** @@ -307,6 +310,7 @@ List < Formatter > template() : String s = null; Formatter f = null; Token t = null; + Token u = null; } { ( @@ -360,12 +364,16 @@ List < Formatter > template() : LOOKAHEAD(< CURLY_START > literal() < CURLY_END >) ( ( - < CURLY_START > + < CURLY_START > s = literal() < CURLY_END > ) { - result.add(new Tag(s)); + if (s != null && s.startsWith(USE_DISPLAY_VALUE)) { + result.add(new Tag(s.substring(1), true)); + } else { + result.add(new Tag(s, false)); + } } ) ) diff --git a/src/main/java/ch/poole/osm/josmtemplateparser/Search.java b/src/main/java/ch/poole/osm/josmtemplateparser/Search.java index 5d41549..49357aa 100644 --- a/src/main/java/ch/poole/osm/josmtemplateparser/Search.java +++ b/src/main/java/ch/poole/osm/josmtemplateparser/Search.java @@ -1,6 +1,7 @@ package ch.poole.osm.josmtemplateparser; import java.io.ByteArrayInputStream; +import java.io.Serializable; import java.util.List; import java.util.Map; @@ -36,7 +37,7 @@ public Search(@NotNull String searchExpression, @NotNull String template) throws @NotNull public String format(@NotNull Type type, @Nullable Meta meta, @Nullable Map tags) { if (meta != null) { - List matches = meta.getMatchingElements(condition); + List matches = meta.getMatchingElements(condition); if (!matches.isEmpty()) { Meta match = meta.wrap(matches.get(0)); return Util.listFormat(formatters, match.getType(), match, match.getTags()); diff --git a/src/main/java/ch/poole/osm/josmtemplateparser/Tag.java b/src/main/java/ch/poole/osm/josmtemplateparser/Tag.java index 8aaadc2..9d6c5c8 100644 --- a/src/main/java/ch/poole/osm/josmtemplateparser/Tag.java +++ b/src/main/java/ch/poole/osm/josmtemplateparser/Tag.java @@ -16,12 +16,16 @@ */ public class Tag implements Formatter { - private final String key; + private static final String USE_DISPLAY_VALUE_PREFIX = "%"; - public Tag(@NotNull String key) { + private final String key; + private final boolean useDisplayValue; + + public Tag(@NotNull String key, boolean useDisplayValue) { this.key = key; + this.useDisplayValue = useDisplayValue; } - + @Override @NotNull public String format(@NotNull Type type, @Nullable Meta meta, @Nullable Map tags) { @@ -29,11 +33,23 @@ public String format(@NotNull Type type, @Nullable Meta meta, @Nullable Map getTags() { } @Override - public List getMatchingElements(@NotNull Condition c) { + public List getMatchingElements(@NotNull Condition c) { return Arrays.asList(this); } @Override - public @NotNull Meta wrap(Object o) { + public @NotNull Meta wrap(Serializable o) { return this; } }; @@ -144,6 +145,9 @@ public Map getTags() { @Test public void specialLocalNameTest() { TestMeta meta = new TestMeta() { + + private static final long serialVersionUID = 1L; + @Override public Map getTags() { Map tags = new HashMap<>(); @@ -157,6 +161,29 @@ public Map getTags() { assertEquals(1, f.size()); assertEquals("grrr2", f.get(0).format(Type.NODE, meta, null)); } + + @Test + public void displayValueTest() { + Map tags = new HashMap<>(); + tags.put("te%st1", "grrr"); + tags.put("name", "grrr2"); + TestMeta meta = new TestMeta() { + + private static final long serialVersionUID = 1L; + + @Override + public Map getTags() { + return tags; + } + }; + + List f = parse("{%name}"); + assertEquals(1, f.size()); + assertEquals("GRRR2", f.get(0).format(Type.NODE, meta, tags)); + f = parse("{te%st1}"); + assertEquals(1, f.size()); + assertEquals("grrr", f.get(0).format(Type.NODE, meta, tags)); + } /** * Parse a filter string and return the Condition object diff --git a/src/test/java/ch/poole/osm/josmtemplateparser/JosmTemplateParserTest.java b/src/test/java/ch/poole/osm/josmtemplateparser/JosmTemplateParserTest.java index 302762c..a6af9cf 100644 --- a/src/test/java/ch/poole/osm/josmtemplateparser/JosmTemplateParserTest.java +++ b/src/test/java/ch/poole/osm/josmtemplateparser/JosmTemplateParserTest.java @@ -148,7 +148,6 @@ private void parseData(String inputFile, String resultsFile) { } catch (FileNotFoundException fnfex) { System.err.println("File not found " + fnfex.toString()); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (AssertionError ae) { System.err.println("Assertion failed for " + line); @@ -158,7 +157,6 @@ private void parseData(String inputFile, String resultsFile) { try { inputRules.close(); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } @@ -166,7 +164,6 @@ private void parseData(String inputFile, String resultsFile) { try { outputExpected.close(); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } diff --git a/src/test/java/ch/poole/osm/josmtemplateparser/TestMeta.java b/src/test/java/ch/poole/osm/josmtemplateparser/TestMeta.java index 3ec9c27..6370f21 100644 --- a/src/test/java/ch/poole/osm/josmtemplateparser/TestMeta.java +++ b/src/test/java/ch/poole/osm/josmtemplateparser/TestMeta.java @@ -1,5 +1,6 @@ package ch.poole.osm.josmtemplateparser; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -16,7 +17,7 @@ * @author simon * */ -public class TestMeta implements Meta { +public class TestMeta implements Meta, Serializable { long id; long version; @@ -118,12 +119,12 @@ public boolean hasRole(@NotNull String role) { } @Override - public Object getPreset(@NotNull String presetPath) { + public Serializable getPreset(@NotNull String presetPath) { return presetPath; } @Override - public boolean matchesPreset(@NotNull Object preset) { + public boolean matchesPreset(@NotNull Serializable preset) { return preset.equals(this.preset); } @@ -153,17 +154,22 @@ public boolean isAllInDownloadedArea() { } @Override - public boolean isChild(@NotNull Type type, @NotNull Meta element, List parents) { + public boolean isChild(@NotNull Type type, @NotNull Meta element, List parents) { return isChild; } @Override - public boolean isParent(@NotNull Type type, @NotNull Meta meta, @NotNull List children) { + public boolean isParent(@NotNull Type type, @NotNull Meta meta, @NotNull List children) { return isParent; } + + @Override + public String displayValue(@NotNull String key, @NotNull String value) { + return value.toUpperCase(); + } @Override - public @NotNull Meta wrap(Object o) { + public @NotNull Meta wrap(Serializable o) { return new TestMeta(); } }