Skip to content

Commit

Permalink
Merge pull request #6 from cxcorp/cmdline-args-ways
Browse files Browse the repository at this point in the history
[to test] Read included and excluded way tags from args
  • Loading branch information
rovaniemi authored Jun 26, 2017
2 parents 01581c0 + 1023a7b commit ccab791
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 27 deletions.
82 changes: 72 additions & 10 deletions src/main/java/osmparser/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
Expand All @@ -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("(?<!\\\\)=", 2);
WayTag tag = tokens.length == 1
? new WayTag(tokens[0])
: new WayTag(tokens[0], tokens[1]);
tags[i] = tag;
}

return tags;
}

private static Osmparser createOsmparser(String[] files, WayTag[] includeWays, WayTag[] excludeWays) {
StreamingXmlGraphParser graphParser = new StreamingXmlGraphParser(includeWays, excludeWays);
return new Osmparser(files, "graph.json", graphParser);
}

private static Options createOptions() {
Options options = new Options();

Expand All @@ -52,12 +87,39 @@ private static Options createOptions() {
.build();
options.addOption(files);

Option verbose = Option.builder("v")
.longOpt("verbose")
.desc("print verbose output")
Option verbose = Option.builder("q")
.longOpt("quiet")
.desc("suppress console output")
.build();
options.addOption(verbose);

Option includeWays = Option.builder("i")
.longOpt("includeWays")
.desc("way tags to include")
.hasArgs()
.build();
options.addOption(includeWays);

Option excludeWays = Option.builder("e")
.longOpt("excludeWays")
.desc("way tags to exclude (overrides includeWay)")
.hasArgs()
.build();
options.addOption(excludeWays);

return options;
}

// TODO: use a proper logger library
private static void info(String message) {
System.out.println(message);
}

private static void info(String fmt, Object... args) {
System.out.printf(fmt + "%n", args);
}

private static void error(String message) {
System.out.println(message);
}
}
4 changes: 0 additions & 4 deletions src/main/java/osmparser/Osmparser.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ public class Osmparser {
private final String outFile;
private final GraphParser parser;

public Osmparser(String[] mapFiles, String outFile) {
this(mapFiles, outFile, new StreamingXmlGraphParser("highway"));
}

public Osmparser(String[] mapFiles, String outFile, GraphParser graphParser) {
this.mapFiles = mapFiles;
this.outFile = outFile;
Expand Down
47 changes: 34 additions & 13 deletions src/main/java/osmparser/StreamingXmlGraphParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Objects;

public class StreamingXmlGraphParser implements GraphParser {

private final XMLInputFactory inputFactory;
private final String[] requiredWayTags;
private final WayTag[] includedWayTags;
private final WayTag[] excludedWayTags;
private Graph graph;

public StreamingXmlGraphParser(String... requiredWayTags) {
public StreamingXmlGraphParser(WayTag[] includedWayTags, WayTag[] excludedWayTags) {
this.inputFactory = InputFactoryImpl.newFactory();
this.requiredWayTags = requiredWayTags;
this.includedWayTags = includedWayTags;
this.excludedWayTags = excludedWayTags;
}

@Override
Expand Down Expand Up @@ -66,17 +69,19 @@ private void readNodeElement(XMLStreamReader reader) {

private void readWayElement(XMLStreamReader reader) throws XMLStreamException {
ArrayList<Long> wayNodesIds = new ArrayList<>(1024);
HashSet<String> wayTags = new HashSet<>(64);
HashMap<String, String> 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<Long> nodesOut,
HashSet<String> tagsOut) throws XMLStreamException {
HashMap<String, String> tagsOut) throws XMLStreamException {
// when we're here, reader cursor is currently at START_ELEMENT, that is, <way>
int nodeChildDepth = 1;

Expand All @@ -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--;
Expand Down Expand Up @@ -121,13 +128,27 @@ private static void readIdsAndTags(XMLStreamReader reader,
throw new RuntimeException("Reached end of XMLStream inside readIdsAndTags! Expected </way>!");
}

private boolean containsAllRequiredTags(HashSet<String> foundTags) {
for (int i = 0; i < requiredWayTags.length; i++) {
if (!foundTags.contains(requiredWayTags[i])) {
return false;
private static boolean containsAnyTargetTags(HashMap<String, String> 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<Long> edges){
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/osmparser/WayTag.java
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit ccab791

Please sign in to comment.