package aimax.osm.writer;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import aimax.osm.data.BoundingBox;
import aimax.osm.data.OsmMap;
import aimax.osm.data.entities.EntityAttribute;
import aimax.osm.data.entities.MapNode;
import aimax.osm.data.entities.MapWay;
import aimax.osm.reader.OsmRuntimeException;
/**
* Writes a map to file using the standard osm XML format.
* @author Ruediger Lunde
*/
public class OsmWriter implements MapWriter {
private static Logger LOG = Logger.getLogger("aimax.osm");
/**
* Writes all data from <code>mapData</code> to file.
*/
public void writeMap(File file, OsmMap map, BoundingBox bb) {
try {
FileOutputStream fs = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter
(new BufferedOutputStream(fs), "UTF-8");
writeMap(writer, map, bb);
} catch (FileNotFoundException fnfe) {
LOG.warning("File does not exist "+file);
} catch (UnsupportedEncodingException fnfe) {
LOG.warning("UTF-8 encoding not supported, sorry.");
}
}
/**
* Writes all data from <code>mapData</code> to a stream.
*/
public void writeMap(OutputStreamWriter writer, OsmMap map, BoundingBox bb) {
try {
StringBuffer text = new StringBuffer();
text.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
text.append("<osm version=\"0.6\" generator=\"aimax-osm-writer\">\n");
text.append("<bound box=\"");
text.append(bb.getLatMin() + ",");
text.append(bb.getLonMin() + ",");
text.append(bb.getLatMax() + ",");
text.append(bb.getLonMax());
text.append("\" origin=\"?\"/>\n");
writer.write(text.toString());
HashSet<MapNode> nodeHash = new HashSet<MapNode>();
Collection<MapWay> ways = map.getWays(bb);
for (MapWay way : ways)
for (MapNode node : way.getNodes())
if (!nodeHash.contains(node)) {
writeNode(writer, node);
nodeHash.add(node);
}
for (MapNode poi : map.getPois(bb))
if (!nodeHash.contains(poi)) {
writeNode(writer, poi);
nodeHash.add(poi);
}
for (MapWay way : ways)
writeWay(writer, way);
writer.write("</osm>\n");
} catch (IOException e) {
throw new OsmRuntimeException("Unable to write XML output to file.", e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
LOG.log(Level.SEVERE, "Unable to close output stream.", e);
}
}
}
}
public String[] fileFormatDescriptions() {
return new String[] {"OSM File (osm)"};
}
public String[] fileFormatExtensions() {
return new String[] {"osm"};
}
protected void writeNode(OutputStreamWriter writer, MapNode node) throws IOException {
StringBuffer text = new StringBuffer();
text.append("<node id=\"");
text.append(node.getId());
text.append("\" lat=\"");
text.append(node.getLat());
text.append("\" lon=\"");
text.append(node.getLon());
if (node.getAttributes().length == 0) {
text.append("\"/>\n");
} else {
text.append("\">\n");
addTags(text, node.getName(), node.getAttributes());
text.append("</node>\n");
}
writer.append(text.toString());
}
/*<node id="83551472" lat="38.8353186" lon="20.7118425" user="aitolos" uid="653" visible="true" version="2" changeset="4440307" timestamp="2010-04-16T16:35:48Z"/>*/
protected void writeWay(OutputStreamWriter writer, MapWay way) throws IOException {
StringBuffer text = new StringBuffer();
text.append("<way id=\"");
text.append(way.getId());
text.append("\">\n");
for (MapNode node : way.getNodes()) {
text.append(" <nd ref=\"");
text.append(node.getId());
text.append("\"/>\n");
}
addTags(text, way.getName(), way.getAttributes());
text.append("</way>\n");
writer.append(text.toString());
}
/*<way id="25264669" user="mimis" uid="59074" visible="true" version="4" changeset="1973025" timestamp="2009-07-29T08:54:03Z">
<nd ref="275294269"/>
<nd ref="275294230"/>
<nd ref="275294794"/>
<nd ref="275294203"/>
<nd ref="275294281"/>
<nd ref="275294351"/>
<tag k="highway" v="tertiary"/>
<tag k="name" v="xy"/>
</way>*/
protected void addTags(StringBuffer text, String name, EntityAttribute[] atts) {
if (name != null) {
text.append(" <tag k=\"name\" v=\"");
text.append(convertToXML(name));
text.append("\"/>\n");
}
for (EntityAttribute att : atts) {
text.append(" <tag k=\"");
text.append(att.getKey());
text.append("\" v=\"");
text.append(convertToXML(att.getValue()));
text.append("\"/>\n");
}
}
/**
* & is replaced by &
* < is replaced by <
* > is replaced by >
* " is replaced by "
*/
protected String convertToXML(String text) {
text = text.replace("&", "&");
text = text.replace("<", "<");
text = text.replace(">", ">");
text = text.replace("\"", """);
return text;
}
}