001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.io.PrintWriter; 007import java.io.StringWriter; 008import java.util.Collection; 009 010import org.openstreetmap.josm.data.osm.Changeset; 011import org.openstreetmap.josm.data.osm.IPrimitive; 012 013/** 014 * Creates an OsmChange document from JOSM edits. 015 * See http://wiki.openstreetmap.org/index.php/OsmChange for a documentation of the 016 * OsmChange format. 017 * 018 */ 019public class OsmChangeBuilder { 020 public static final String DEFAULT_API_VERSION = "0.6"; 021 022 private String currentMode; 023 private PrintWriter writer; 024 private StringWriter swriter; 025 private OsmWriter osmwriter; 026 private String apiVersion = DEFAULT_API_VERSION; 027 private boolean prologWritten; 028 029 public OsmChangeBuilder(Changeset changeset) { 030 this(changeset, null /* default api version */); 031 } 032 033 public OsmChangeBuilder(Changeset changeset, String apiVersion) { 034 this.apiVersion = apiVersion == null ? DEFAULT_API_VERSION : apiVersion; 035 writer = new PrintWriter(swriter = new StringWriter()); 036 osmwriter = OsmWriterFactory.createOsmWriter(writer, false, apiVersion); 037 osmwriter.setChangeset(changeset); 038 osmwriter.setIsOsmChange(true); 039 } 040 041 protected void write(IPrimitive p) { 042 if (p.isDeleted()) { 043 switchMode("delete"); 044 osmwriter.setWithBody(false); 045 p.accept(osmwriter); 046 } else { 047 switchMode(p.isNew() ? "create" : "modify"); 048 osmwriter.setWithBody(true); 049 p.accept(osmwriter); 050 } 051 } 052 053 private void switchMode(String newMode) { 054 if ((newMode != null && !newMode.equals(currentMode)) || (newMode == null && currentMode != null)) { 055 if (currentMode != null) { 056 writer.print("</"); 057 writer.print(currentMode); 058 writer.println(">"); 059 } 060 if (newMode != null) { 061 writer.print("<"); 062 writer.print(newMode); 063 writer.println(">"); 064 } 065 currentMode = newMode; 066 } 067 } 068 069 /** 070 * Writes the prolog of the OsmChange document 071 * 072 * @throws IllegalStateException if the prologs has already been written 073 */ 074 public void start() { 075 if (prologWritten) 076 throw new IllegalStateException(tr("Prolog of OsmChange document already written. Please write only once.")); 077 writer.print("<osmChange version=\""); 078 writer.print(apiVersion); 079 writer.println("\" generator=\"JOSM\">"); 080 prologWritten = true; 081 } 082 083 /** 084 * Appends a collection of Primitives to the OsmChange document. 085 * 086 * @param primitives the collection of primitives. Ignored if null. 087 * @throws IllegalStateException if the prologs has not been written yet 088 * @see #start() 089 * @see #append(IPrimitive) 090 */ 091 public void append(Collection<? extends IPrimitive> primitives) { 092 if (primitives == null) return; 093 if (!prologWritten) 094 throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write first.")); 095 for (IPrimitive p : primitives) { 096 write(p); 097 } 098 } 099 100 /** 101 * Appends an Primitive to the OsmChange document. 102 * 103 * @param p the primitive. Ignored if null. 104 * @throws IllegalStateException if the prologs has not been written yet 105 * @see #start() 106 * @see #append(Collection) 107 */ 108 public void append(IPrimitive p) { 109 if (p == null) return; 110 if (!prologWritten) 111 throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write first.")); 112 write(p); 113 } 114 115 /** 116 * Writes the epilog of the OsmChange document 117 * 118 * @throws IllegalStateException if the prologs has not been written yet 119 */ 120 public void finish() { 121 if (!prologWritten) 122 throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write first.")); 123 if (currentMode != null) { 124 writer.print("</"); 125 writer.print(currentMode); 126 writer.println(">"); 127 } 128 writer.println("</osmChange>"); 129 } 130 131 public String getDocument() { 132 return swriter.toString(); 133 } 134}