From 1023a7ba288912662cb338ec9ecd7313c6244e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joona=20Heikkil=C3=A4?= Date: Sun, 25 Jun 2017 12:54:04 +0300 Subject: [PATCH] Read included and excluded way tags from args Add two new command line flags: `--includeWays` and `--excludeWays`. Include can be used as a "if any of these match, include the tag" whereas exclude can be used as a "if any of these match, do not include the tag". Shorthands are -i and -e. Usage: osmparser -f map.osm -i highway railway=abandoned -e access=no access=private osmparser -f map.osm -i railway -e railway=abandoned Commit also removes --verbose and adds --quiet. Proper logging should be added next. --- src/main/java/osmparser/Main.java | 82 ++++++++++++++++--- src/main/java/osmparser/Osmparser.java | 4 - .../osmparser/StreamingXmlGraphParser.java | 47 ++++++++--- src/main/java/osmparser/WayTag.java | 30 +++++++ 4 files changed, 136 insertions(+), 27 deletions(-) create mode 100644 src/main/java/osmparser/WayTag.java diff --git a/src/main/java/osmparser/Main.java b/src/main/java/osmparser/Main.java index 92413aa..53311c2 100644 --- a/src/main/java/osmparser/Main.java +++ b/src/main/java/osmparser/Main.java @@ -2,10 +2,11 @@ import org.apache.commons.cli.*; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; public class Main { private static String PROGRAM_NAME = "osmparser"; @@ -19,20 +20,31 @@ public static void main(String[] args) throws IOException { try { cmd = parser.parse(options, args); } catch (ParseException ex) { - System.out.println(ex.getMessage()); + error(ex.getMessage()); new HelpFormatter().printHelp(PROGRAM_NAME, options); System.exit(EXIT_FAIL); } - boolean verbose = cmd.hasOption("verbose"); + boolean notQuiet = cmd.hasOption("quiet"); String[] files = cmd.getOptionValues("files"); - if (verbose) { - System.out.println("Parsing files: " + Arrays.asList(files)); + if (notQuiet) { + info("Parsing files: " + Arrays.asList(files)); + } + + String[] includeWayProps = cmd.getOptionValues("includeWays"); + String[] excludeWayProps = cmd.getOptionValues("excludeWays"); + + WayTag[] includedTags = parseWayTagsFromOptions(includeWayProps); + WayTag[] excludedTags = parseWayTagsFromOptions(excludeWayProps); + + if (notQuiet) { + info("Included tags: " + Arrays.asList(includedTags)); + info("Excluded tags: " + Arrays.asList(excludedTags)); } try { - new Osmparser(files, "graph.json").start(); + createOsmparser(files, includedTags, excludedTags).start(); } catch (RuntimeException ex) { if (!(ex.getCause() instanceof IOException)) { throw ex; @@ -41,6 +53,29 @@ public static void main(String[] args) throws IOException { } } + private static WayTag[] parseWayTagsFromOptions(String[] optionValues) { + if (optionValues == null || optionValues.length == 0) { + return new WayTag[0]; + } + + WayTag[] tags = new WayTag[optionValues.length]; + for (int i = 0; i < tags.length; i++) { + // Split key=value pairs, skipping escaped \= + String[] tokens = optionValues[i].split("(? wayNodesIds = new ArrayList<>(1024); - HashSet wayTags = new HashSet<>(64); + HashMap wayTags = new HashMap<>(64); readIdsAndTags(reader, wayNodesIds, wayTags); - if (containsAllRequiredTags(wayTags)) { + if (!containsAnyTargetTags(wayTags, excludedWayTags) + && containsAnyTargetTags(wayTags, includedWayTags) + ) { addEdgesToGraph(wayNodesIds); } } private static void readIdsAndTags(XMLStreamReader reader, ArrayList nodesOut, - HashSet tagsOut) throws XMLStreamException { + HashMap tagsOut) throws XMLStreamException { // when we're here, reader cursor is currently at START_ELEMENT, that is, int nodeChildDepth = 1; @@ -92,8 +97,10 @@ private static void readIdsAndTags(XMLStreamReader reader, Long id = Long.parseLong(ndRefAttribute); nodesOut.add(id); } else if (elementName.equals("tag")) { + // according to the schema, "k" and "v" are required String tagKeyAttribute = reader.getAttributeValue(null, "k"); - tagsOut.add(tagKeyAttribute); + String tagKeyValue = reader.getAttributeValue(null, "v"); + tagsOut.put(tagKeyAttribute, tagKeyValue); } } else if (eventType == XMLEvent.END_ELEMENT) { nodeChildDepth--; @@ -121,13 +128,27 @@ private static void readIdsAndTags(XMLStreamReader reader, throw new RuntimeException("Reached end of XMLStream inside readIdsAndTags! Expected !"); } - private boolean containsAllRequiredTags(HashSet foundTags) { - for (int i = 0; i < requiredWayTags.length; i++) { - if (!foundTags.contains(requiredWayTags[i])) { - return false; + private static boolean containsAnyTargetTags(HashMap foundTags, WayTag[] targetTags) { + for (WayTag tag : targetTags) { + String targetKey = tag.getTagKey(); + String targetValue = tag.getTagValue(); // may be null + + // foundValue is guaranteed to be non-null if the key was found + String foundValue = foundTags.get(targetKey); + if (foundValue != null && (targetMatchesAnyValue(targetValue) || targetMatchesValue(targetValue, foundValue))) { + return true; } } - return true; + + return false; + } + + private static boolean targetMatchesValue(String targetValue, String foundValue) { + return Objects.equals(targetValue, foundValue); + } + + private static boolean targetMatchesAnyValue(String targetValue) { + return targetValue == null; } private void addEdgesToGraph(ArrayList edges){ diff --git a/src/main/java/osmparser/WayTag.java b/src/main/java/osmparser/WayTag.java new file mode 100644 index 0000000..2cf4296 --- /dev/null +++ b/src/main/java/osmparser/WayTag.java @@ -0,0 +1,30 @@ +package osmparser; + +public class WayTag { + private final String tagKey; + private final String tagValue; + + public WayTag(String tagKeyToMatch) { + this(tagKeyToMatch, null); + } + + public WayTag(String tagKey, String tagValue) { + this.tagKey = tagKey; + this.tagValue = tagValue; + } + + public String getTagKey() { + return tagKey; + } + + public String getTagValue() { + return tagValue; + } + + @Override + public String toString() { + return tagValue == null + ? String.format("WayTag{tagKey='%s'}", tagKey) + : String.format("WayTag{tagKey='%s', tagValue='%s'}", tagKey, tagValue); + } +}