package me.osm.gazetter.striper.readers;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class PointsReader extends DefaultHandler {
private PointsHandler[] handlers;
private HashSet<String> drop;
private Timestamp lastNodeTimestamp = null;
public static class Node {
public long id;
public double lon;
public double lat;
public Map<String, String> tags = new HashMap<>();
}
public static interface PointsHandler {
public void handle(Node node);
}
public PointsReader(HashSet<String> drop) {
this.drop = drop;
}
private Node node = null;
public void read(InputStream is, PointsHandler... handlers) {
this.handlers = handlers;
try {
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
saxParser.parse(is, this);
} catch (Exception e) {
throw new RuntimeException("Parsing failed for: " + is, e);
}
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(qName.equals("node")) {
this.node = new Node();
this.node.id = Long.valueOf(attributes.getValue("id"));
this.node.lon = Double.valueOf(attributes.getValue("lon"));
this.node.lat = Double.valueOf(attributes.getValue("lat"));
Timestamp ts = Timestamp.valueOf(StringUtils.remove(attributes.getValue("timestamp"), 'Z').replace('T', ' '));
if(lastNodeTimestamp == null || ts.after(lastNodeTimestamp)) {
lastNodeTimestamp = ts;
}
}
if(qName.equals("tag") && this.node != null) {
this.node.tags.put(attributes.getValue("k"), attributes.getValue("v"));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.equals("node")) {
if(!drop(this.node)) {
for(PointsHandler handler : handlers) {
handler.handle(this.node);
}
}
this.node = null;
}
}
private final boolean drop(Node n) {
return !this.drop.isEmpty() && this.drop.contains("n" + n.id);
}
public Timestamp getLastNodeTimestamp() {
return lastNodeTimestamp;
}
}