package se.kodapan.osm.xml;
import se.kodapan.osm.domain.*;
import se.kodapan.osm.domain.root.Root;
import java.io.IOException;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* @author kalle
* @since 2013-09-02 5:03 PM
*/
public class OsmXmlWriter extends Writer {
private Writer xml;
private String version = "0.6";
private Boolean upload = true;
private String generator = getClass().getName();
public OsmXmlWriter(Writer xml) throws IOException {
this.xml = xml;
writeHeader();
}
public void writeHeader() throws IOException {
xml.write("<?xml version='1.0' encoding='UTF-8'?>\n");
xml.write("<osm version='");
xml.write(version);
if (upload != null) {
xml.write("' upload='");
xml.write(upload ? "true" : "false");
xml.write("'");
}
xml.write(" generator='");
xml.write(generator);
xml.write("'>\n");
}
public void writeFooter() throws IOException {
xml.write("</osm>\n");
}
public void write(Root root) throws IOException {
for (Node node : root.getNodes().values()) {
write(node);
}
for (Way way : root.getWays().values()) {
write(way);
}
for (Relation relation : root.getRelations().values()) {
write(relation);
}
}
public void writeTags(OsmObject osmObject) throws IOException {
// <tag k='landuse' v='farmland' />
if (osmObject.getTags() != null) {
for (Map.Entry<String, String> tag : osmObject.getTags().entrySet()) {
xml.write("\t\t<tag k='");
xml.write(tag.getKey());
xml.write("' v='");
xml.write(tag.getValue());
xml.write("' />\n");
}
}
}
public void write(Node node) throws IOException {
writeObjectHead(node);
xml.write(" lat='");
xml.write(new DecimalFormat("#.##################################").format(node.getLatitude()));
xml.write("'");
xml.write(" lon='");
xml.write(new DecimalFormat("#.##################################").format(node.getLongitude()));
xml.write("'");
xml.write(" >\n");
writeTags(node);
xml.write("\t</node>\n");
}
public void write(Way way) throws IOException {
writeObjectHead(way);
xml.write(" >\n");
for (Node node : way.getNodes()) {
xml.append("\t\t<nd ref='");
xml.append(String.valueOf(node.getId()));
xml.append("' />\n");
node.getId();
}
writeTags(way);
xml.write("\t</way>\n");
}
private OsmObjectVisitor<String> getOsmObjectTypeName = new OsmObjectVisitor<String>() {
@Override
public String visit(Node node) {
return "node";
}
@Override
public String visit(Way way) {
return "way";
}
@Override
public String visit(Relation relation) {
return "relation";
}
};
public void write(Relation relation) throws IOException {
// <relation id='3146471' timestamp='2013-08-16T01:39:33Z' uid='194367' user='Karl Wettin' visible='true' version='1' changeset='17366616'>
writeObjectHead(relation);
xml.write(" >\n");
for (RelationMembership membership : relation.getMembers()) {
xml.write("\t\t<member type='");
xml.write(membership.getObject().accept(getOsmObjectTypeName));
xml.write("'");
xml.write(" ref='");
xml.write(String.valueOf(membership.getObject().getId()));
xml.write("'");
xml.write(" role='");
xml.write(membership.getRole());
xml.write("'");
xml.write(" />\n");
}
writeTags(relation);
xml.write("\t</relation>\n");
}
private void writeObjectHead(OsmObject osmObject) throws IOException {
xml.write("\t<");
xml.append(osmObject.accept(getOsmObjectTypeName));
xml.write(" ");
xml.write(" id='");
xml.write(String.valueOf(osmObject.getId()));
xml.write("'");
if (osmObject.getId() > -1) {
if (osmObject.getTimestamp() != null) {
xml.write(" timestamp='");
xml.write(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(new Date(osmObject.getTimestamp())));
xml.write("'");
}
if (osmObject.getUid() != null) {
xml.write(" uid='");
xml.write(String.valueOf(osmObject.getUid()));
xml.write("'");
}
if (osmObject.getUser() != null) {
xml.write(" user='");
xml.write(String.valueOf(osmObject.getUser()));
xml.write("'");
}
if (osmObject.getVersion() != null) {
xml.write(" version='");
xml.write(String.valueOf(osmObject.getVersion()));
xml.write("'");
}
if (osmObject.getChangeset() != null) {
xml.write(" changeset='");
xml.write(String.valueOf(osmObject.getChangeset()));
xml.write("'");
}
}
}
private boolean wroteHeader = false;
@Override
public synchronized void write(char[] cbuf, int off, int len) throws IOException {
if (!wroteHeader) {
wroteHeader = true;
writeHeader();
}
xml.write(cbuf, off, len);
}
@Override
public void flush() throws IOException {
xml.flush();
}
@Override
public void close() throws IOException {
writeFooter();
xml.close();
}
}