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 OsmChange format. 016 * @since 1071 017 */ 018public class OsmChangeBuilder { 019 /** Default OSM API version */ 020 public static final String DEFAULT_API_VERSION = "0.6"; 021 022 private String currentMode; 023 private final PrintWriter writer; 024 private final StringWriter swriter; 025 private final OsmWriter osmwriter; 026 private String apiVersion = DEFAULT_API_VERSION; 027 private boolean prologWritten; 028 029 /** 030 * Constructs a new {@code OsmChangeBuilder}. 031 * @param changeset changeset 032 */ 033 public OsmChangeBuilder(Changeset changeset) { 034 this(changeset, null /* default api version */); 035 } 036 037 /** 038 * Constructs a new {@code OsmChangeBuilder}. 039 * @param changeset changeset 040 * @param apiVersion OSM API version 041 */ 042 public OsmChangeBuilder(Changeset changeset, String apiVersion) { 043 this.apiVersion = apiVersion == null ? DEFAULT_API_VERSION : apiVersion; 044 swriter = new StringWriter(); 045 writer = new PrintWriter(swriter); 046 osmwriter = OsmWriterFactory.createOsmWriter(writer, false, apiVersion); 047 osmwriter.setChangeset(changeset); 048 osmwriter.setIsOsmChange(true); 049 } 050 051 protected void write(IPrimitive p) { 052 if (p.isDeleted()) { 053 switchMode("delete"); 054 osmwriter.setWithBody(false); 055 p.accept(osmwriter); 056 } else { 057 switchMode(p.isNew() ? "create" : "modify"); 058 osmwriter.setWithBody(true); 059 p.accept(osmwriter); 060 } 061 } 062 063 private void switchMode(String newMode) { 064 if ((newMode != null && !newMode.equals(currentMode)) || (newMode == null && currentMode != null)) { 065 if (currentMode != null) { 066 writer.print("</"); 067 writer.print(currentMode); 068 writer.println(">"); 069 } 070 if (newMode != null) { 071 writer.print("<"); 072 writer.print(newMode); 073 writer.println(">"); 074 } 075 currentMode = newMode; 076 } 077 } 078 079 /** 080 * Writes the prolog of the OsmChange document 081 * 082 * @throws IllegalStateException if the prologs has already been written 083 */ 084 public void start() { 085 if (prologWritten) 086 throw new IllegalStateException(tr("Prolog of OsmChange document already written. Please write only once.")); 087 writer.print("<osmChange version=\""); 088 writer.print(apiVersion); 089 writer.println("\" generator=\"JOSM\">"); 090 prologWritten = true; 091 } 092 093 /** 094 * Appends a collection of Primitives to the OsmChange document. 095 * 096 * @param primitives the collection of primitives. Ignored if null. 097 * @throws IllegalStateException if the prologs has not been written yet 098 * @see #start() 099 * @see #append(IPrimitive) 100 */ 101 public void append(Collection<? extends IPrimitive> primitives) { 102 if (primitives == null) 103 return; 104 checkProlog(); 105 for (IPrimitive p : primitives) { 106 write(p); 107 } 108 } 109 110 private void checkProlog() { 111 if (!prologWritten) 112 throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write first.")); 113 } 114 115 /** 116 * Appends an Primitive to the OsmChange document. 117 * 118 * @param p the primitive. Ignored if null. 119 * @throws IllegalStateException if the prologs has not been written yet 120 * @see #start() 121 * @see #append(Collection) 122 */ 123 public void append(IPrimitive p) { 124 if (p == null) 125 return; 126 checkProlog(); 127 write(p); 128 } 129 130 /** 131 * Writes the epilog of the OsmChange document 132 * 133 * @throws IllegalStateException if the prologs has not been written yet 134 */ 135 public void finish() { 136 checkProlog(); 137 if (currentMode != null) { 138 writer.print("</"); 139 writer.print(currentMode); 140 writer.println(">"); 141 } 142 writer.println("</osmChange>"); 143 } 144 145 /** 146 * Returns XML document. 147 * @return XML document 148 */ 149 public String getDocument() { 150 return swriter.toString(); 151 } 152}