// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.io;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import org.openstreetmap.josm.data.osm.Changeset;
import org.openstreetmap.josm.data.osm.IPrimitive;
/**
* Creates an OsmChange document from JOSM edits.
* See http://wiki.openstreetmap.org/index.php/OsmChange for a documentation of the OsmChange format.
* @since 1071
*/
public class OsmChangeBuilder {
/** Default OSM API version */
public static final String DEFAULT_API_VERSION = "0.6";
private String currentMode;
private final PrintWriter writer;
private final StringWriter swriter;
private final OsmWriter osmwriter;
private String apiVersion = DEFAULT_API_VERSION;
private boolean prologWritten;
/**
* Constructs a new {@code OsmChangeBuilder}.
* @param changeset changeset
*/
public OsmChangeBuilder(Changeset changeset) {
this(changeset, null /* default api version */);
}
/**
* Constructs a new {@code OsmChangeBuilder}.
* @param changeset changeset
* @param apiVersion OSM API version
*/
public OsmChangeBuilder(Changeset changeset, String apiVersion) {
this.apiVersion = apiVersion == null ? DEFAULT_API_VERSION : apiVersion;
swriter = new StringWriter();
writer = new PrintWriter(swriter);
osmwriter = OsmWriterFactory.createOsmWriter(writer, false, apiVersion);
osmwriter.setChangeset(changeset);
osmwriter.setIsOsmChange(true);
}
protected void write(IPrimitive p) {
if (p.isDeleted()) {
switchMode("delete");
osmwriter.setWithBody(false);
p.accept(osmwriter);
} else {
switchMode(p.isNew() ? "create" : "modify");
osmwriter.setWithBody(true);
p.accept(osmwriter);
}
}
private void switchMode(String newMode) {
if ((newMode != null && !newMode.equals(currentMode)) || (newMode == null && currentMode != null)) {
if (currentMode != null) {
writer.print("</");
writer.print(currentMode);
writer.println(">");
}
if (newMode != null) {
writer.print("<");
writer.print(newMode);
writer.println(">");
}
currentMode = newMode;
}
}
/**
* Writes the prolog of the OsmChange document
*
* @throws IllegalStateException if the prologs has already been written
*/
public void start() {
if (prologWritten)
throw new IllegalStateException(tr("Prolog of OsmChange document already written. Please write only once."));
writer.print("<osmChange version=\"");
writer.print(apiVersion);
writer.println("\" generator=\"JOSM\">");
prologWritten = true;
}
/**
* Appends a collection of Primitives to the OsmChange document.
*
* @param primitives the collection of primitives. Ignored if null.
* @throws IllegalStateException if the prologs has not been written yet
* @see #start()
* @see #append(IPrimitive)
*/
public void append(Collection<? extends IPrimitive> primitives) {
if (primitives == null)
return;
checkProlog();
for (IPrimitive p : primitives) {
write(p);
}
}
private void checkProlog() {
if (!prologWritten)
throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write first."));
}
/**
* Appends an Primitive to the OsmChange document.
*
* @param p the primitive. Ignored if null.
* @throws IllegalStateException if the prologs has not been written yet
* @see #start()
* @see #append(Collection)
*/
public void append(IPrimitive p) {
if (p == null)
return;
checkProlog();
write(p);
}
/**
* Writes the epilog of the OsmChange document
*
* @throws IllegalStateException if the prologs has not been written yet
*/
public void finish() {
checkProlog();
if (currentMode != null) {
writer.print("</");
writer.print(currentMode);
writer.println(">");
}
writer.println("</osmChange>");
}
/**
* Returns XML document.
* @return XML document
*/
public String getDocument() {
return swriter.toString();
}
}