Ticket #8390: conflict-save-draft01.patch
File conflict-save-draft01.patch, 16.2 KB (added by , 11 years ago) |
---|
-
src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
804 804 dialog.showDialog(); 805 805 if (dialog.getValue() != 1) return false; 806 806 } 807 808 ConflictCollection conflicts = getConflicts();809 if (conflicts != null && !conflicts.isEmpty()) {810 ExtendedDialog dialog = new ExtendedDialog(811 Main.parent,812 /* I18N: Display title of the window showing conflicts */813 tr("Conflicts"),814 new String[] {tr("Reject Conflicts and Save"), tr("Cancel")}815 );816 dialog.setContent(tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"));817 dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});818 dialog.showDialog();819 if (dialog.getValue() != 1) return false;820 }821 807 return true; 822 808 } 823 809 -
src/org/openstreetmap/josm/io/OsmReader.java
18 18 import javax.xml.stream.XMLStreamReader; 19 19 20 20 import org.openstreetmap.josm.data.Bounds; 21 import org.openstreetmap.josm.data.conflict.Conflict; 22 import org.openstreetmap.josm.data.conflict.ConflictCollection; 21 23 import org.openstreetmap.josm.data.coor.LatLon; 22 24 import org.openstreetmap.josm.data.osm.Changeset; 23 25 import org.openstreetmap.josm.data.osm.DataSet; 24 26 import org.openstreetmap.josm.data.osm.DataSource; 25 27 import org.openstreetmap.josm.data.osm.Node; 26 28 import org.openstreetmap.josm.data.osm.NodeData; 29 import org.openstreetmap.josm.data.osm.OsmPrimitive; 27 30 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 28 31 import org.openstreetmap.josm.data.osm.PrimitiveData; 29 32 import org.openstreetmap.josm.data.osm.Relation; … … 131 134 if (parser.getLocalName().equals("bounds")) { 132 135 parseBounds(generator); 133 136 } else if (parser.getLocalName().equals("node")) { 134 parseNode(); 137 Node n = parseNode(false); 138 externalIdMap.put(n.getPrimitiveId(), n); 135 139 } else if (parser.getLocalName().equals("way")) { 136 140 parseWay(); 137 141 } else if (parser.getLocalName().equals("relation")) { … … 175 179 jumpToEnd(); 176 180 } 177 181 178 protected Node parseNode() throws XMLStreamException { 182 /** 183 * Parse a node. 184 * 185 * @param isConflict True, if the node participates in a conflict with 186 * role "their". False, if it is a regular node, that will be included 187 * in the DataSet. 188 * @return the parsed node 189 * @throws XMLStreamException 190 */ 191 protected Node parseNode(boolean isConflict) throws XMLStreamException { 179 192 NodeData nd = new NodeData(); 180 193 String lat = parser.getAttributeValue(null, "lat"); 181 194 String lon = parser.getAttributeValue(null, "lon"); … … 186 199 Node n = new Node(nd.getId(), nd.getVersion()); 187 200 n.setVisible(nd.isVisible()); 188 201 n.load(nd); 189 externalIdMap.put(nd.getPrimitiveId(), n);190 202 while (true) { 191 203 int event = parser.next(); 192 204 if (event == XMLStreamConstants.START_ELEMENT) { 193 205 if (parser.getLocalName().equals("tag")) { 194 206 parseTag(n); 207 } else if (!isConflict && parser.getLocalName().equals("conflict")) { 208 parseNodeConflict(n); 195 209 } else { 196 210 parseUnknown(); 197 211 } … … 200 214 } 201 215 } 202 216 217 protected void parseNodeConflict(Node my) throws XMLStreamException { 218 Node their = null; 219 while (true) { 220 int event = parser.next(); 221 if (event == XMLStreamConstants.START_ELEMENT) { 222 if (parser.getLocalName().equals("node")) { 223 their = parseNode(true); 224 conflicts.add(new Conflict(my, their)); 225 } else { 226 parseUnknown(); 227 } 228 } else if (event == XMLStreamConstants.END_ELEMENT) 229 return; 230 } 231 } 232 203 233 protected Way parseWay() throws XMLStreamException { 204 234 WayData wd = new WayData(); 205 235 readCommon(wd); … … 348 378 while (true) { 349 379 int event = parser.next(); 350 380 if (event == XMLStreamConstants.START_ELEMENT) { 351 parseUnknown(false); /* no more warning for inner elements */381 parseUnknown(false); /* no more warnings for inner elements */ 352 382 } else if (event == XMLStreamConstants.END_ELEMENT) 353 383 return; 354 384 } … … 556 586 } 557 587 } 558 588 559 p rotected DataSet doParseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {589 public DataSet parse(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException { 560 590 if (progressMonitor == null) { 561 591 progressMonitor = NullProgressMonitor.INSTANCE; 562 592 } … … 616 646 * @throws IllegalArgumentException thrown if source is null 617 647 */ 618 648 public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException { 619 return new OsmReader(). doParseDataSet(source, progressMonitor);649 return new OsmReader().parse(source, progressMonitor); 620 650 } 651 652 public ConflictCollection getConflicts() { 653 return conflicts; 654 } 655 621 656 } -
src/org/openstreetmap/josm/io/OsmWriter.java
11 11 import java.util.List; 12 12 import java.util.Map.Entry; 13 13 14 import org.openstreetmap.josm.data.conflict.Conflict; 15 import org.openstreetmap.josm.data.conflict.ConflictCollection; 14 16 import org.openstreetmap.josm.data.coor.CoordinateFormat; 15 17 import org.openstreetmap.josm.data.osm.Changeset; 16 18 import org.openstreetmap.josm.data.osm.DataSet; … … 42 44 private boolean isOsmChange; 43 45 private String version; 44 46 private Changeset changeset; 47 private ConflictCollection conflicts; 45 48 46 49 /** 47 50 * Do not call this directly. Use OsmWriterFactory instead. … … 52 55 this.version = (version == null ? DEFAULT_API_VERSION : version); 53 56 } 54 57 55 public void setWithBody(boolean wb) { 56 this.withBody = wb; 58 /** 59 * Set to false, if you want to skip the element body. 60 * 61 * If set to false, node coordinates, way nodes and relation members are 62 * omitted in the output. 63 * 64 * @param withBody false, if body should be skipped 65 */ 66 public void setWithBody(boolean withBody) { 67 this.withBody = withBody; 57 68 } 58 69 70 /** 71 * Set to true, if a .osmChange file is written. 72 * 73 * For upload of changes to the server, not all attributes that are 74 * normally written to a .osm file are needed. 75 * 76 * @param isOsmChange true, if a .osmChange file is written 77 */ 59 78 public void setIsOsmChange(boolean isOsmChange) { 60 79 this.isOsmChange = isOsmChange; 61 80 } … … 100 119 public void writeLayer(OsmDataLayer layer) { 101 120 header(!layer.isUploadDiscouraged()); 102 121 writeDataSources(layer.data); 122 conflicts = layer.getConflicts(); 103 123 writeContent(layer.data); 104 124 footer(); 105 125 } … … 123 143 } 124 144 125 145 protected boolean shouldWrite(OsmPrimitive osm) { 146 // FIXME: the following condition should be equivalent: 147 // !osm.isNew() || !osm.isDeleted(); 126 148 return !osm.isNewOrUndeleted() || !osm.isDeleted(); 127 149 } 128 150 … … 133 155 + s.bounds.getMin().lon()+"' maxlat='" 134 156 + s.bounds.getMax().lat()+"' maxlon='" 135 157 + s.bounds.getMax().lon() 136 +"' origin='"+XmlWriter.encode(s.origin)+"' 158 +"' origin='"+XmlWriter.encode(s.origin)+"'/>"); 137 159 } 138 160 } 139 161 … … 144 166 if (!withBody) { 145 167 out.println("/>"); 146 168 } else { 169 boolean hasInnerElements = false; 147 170 if (n.getCoor() != null) { 148 171 out.print(" lat='"+n.getCoor().lat()+"' lon='"+n.getCoor().lon()+"'"); 149 172 } 150 addTags(n, "node", true); 173 if (n.hasKeys()) { 174 out.println(">"); 175 hasInnerElements = true; 176 addTags(n, " "); 177 } 178 Conflict c = conflicts.getConflictForMy(n); 179 if (c != null) { 180 IPrimitive th = c.getTheir(); 181 if (th instanceof INode) { 182 INode nConflict = (INode) th; 183 if (!hasInnerElements) { 184 out.println(">"); 185 } 186 out.println(" <conflict>"); 187 // FIXME: add c.isMyDeleted and c.mergedMap 188 out.print(" "); 189 addCommon(th, "node"); 190 if (nConflict.getCoor() != null) { 191 out.print(" lat='"+nConflict.getCoor().lat()+"' lon='"+nConflict.getCoor().lon()+"'"); 192 } 193 if (nConflict.hasKeys()) { 194 out.println(">"); 195 addTags(nConflict, " "); 196 out.println(" </node>"); 197 } else { 198 out.println("/>"); 199 } 200 out.println(" </conflict>"); 201 hasInnerElements = true; 202 } 203 } 204 if (hasInnerElements) { 205 out.println(" </node>"); 206 } else { 207 out.println("/>"); 208 } 151 209 } 152 210 } 153 211 … … 216 274 } 217 275 }; 218 276 277 protected void addTags(Tagged osm, String inset) { 278 List<Entry<String, String>> entries = new ArrayList<Entry<String,String>>(osm.getKeys().entrySet()); 279 Collections.sort(entries, byKeyComparator); 280 for (Entry<String, String> e : entries) { 281 out.println(inset + "<tag k='"+ XmlWriter.encode(e.getKey()) + 282 "' v='"+XmlWriter.encode(e.getValue())+ "'/>"); 283 } 284 } 285 219 286 protected void addTags(Tagged osm, String tagname, boolean tagOpen) { 220 287 if (osm.hasKeys()) { 221 288 if (tagOpen) { -
src/org/openstreetmap/josm/io/OsmImporter.java
87 87 * associatedFile can be null if the stream does not come from a file. 88 88 */ 89 89 public OsmImporterData loadLayer(InputStream in, final File associatedFile, final String layerName, ProgressMonitor progressMonitor) throws IllegalDataException { 90 final DataSet dataSet = parseDataSet(in, progressMonitor); 90 OsmReader reader = new OsmReader(); 91 DataSet dataSet = reader.parse(in, progressMonitor); 91 92 if (dataSet == null) { 92 93 throw new IllegalDataException(tr("Invalid dataset")); 93 94 } 94 95 OsmDataLayer layer = createLayer(dataSet, associatedFile, layerName); 96 layer.getConflicts().add(reader.getConflicts()); 95 97 Runnable postLayerTask = createPostLayerTask(dataSet, associatedFile, layerName, layer); 96 98 return new OsmImporterData(layer, postLayerTask); 97 99 } 98 100 99 protected DataSet parseDataSet(InputStream in, ProgressMonitor progressMonitor) throws IllegalDataException {100 return OsmReader.parseDataSet(in, progressMonitor);101 }102 103 101 protected OsmDataLayer createLayer(final DataSet dataSet, final File associatedFile, final String layerName) { 104 102 return new OsmDataLayer(dataSet, layerName, associatedFile); 105 103 } -
src/org/openstreetmap/josm/io/OsmChangeReader.java
65 65 if (event == XMLStreamConstants.START_ELEMENT) { 66 66 OsmPrimitive p = null; 67 67 if (parser.getLocalName().equals("node")) { 68 p = parseNode( );68 p = parseNode(false); 69 69 } else if (parser.getLocalName().equals("way")) { 70 70 p = parseWay(); 71 71 } else if (parser.getLocalName().equals("relation")) { … … 97 97 * @throws IllegalArgumentException thrown if source is null 98 98 */ 99 99 public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException { 100 return new OsmChangeReader(). doParseDataSet(source, progressMonitor);100 return new OsmChangeReader().parse(source, progressMonitor); 101 101 } 102 102 } -
src/org/openstreetmap/josm/io/AbstractReader.java
9 9 import java.util.List; 10 10 import java.util.Map; 11 11 12 import org.openstreetmap.josm.data.conflict.ConflictCollection; 12 13 import org.openstreetmap.josm.data.osm.Changeset; 13 14 import org.openstreetmap.josm.data.osm.DataSet; 14 15 import org.openstreetmap.josm.data.osm.Node; … … 33 34 */ 34 35 protected DataSet ds = new DataSet(); 35 36 37 protected ConflictCollection conflicts = new ConflictCollection(); 38 36 39 protected Changeset uploadChangeset; 37 40 38 41 /** the map from external ids to read OsmPrimitives. External ids are … … 189 192 } 190 193 } 191 194 } 195 196 protected void processConflictsAfterParsing() { 197 // add conflict primitives with role "their" to a dummy dataset, 198 // because each primitive needs a parent dataset. 199 DataSet theirDataSet = new DataSet(); 200 for (OsmPrimitive their : conflicts.getTheirConflictParties()) { 201 theirDataSet.addPrimitive(their); 202 } 203 } 192 204 193 205 protected final void prepareDataSet() throws IllegalDataException { 194 206 try { -
src/org/openstreetmap/josm/data/conflict/Conflict.java
3 3 4 4 import java.util.Map; 5 5 6 import org.openstreetmap.josm.data.osm.IPrimitive; 6 7 import org.openstreetmap.josm.data.osm.OsmPrimitive; 7 8 import org.openstreetmap.josm.data.osm.PrimitiveId; 8 9 … … 45 46 return their; 46 47 } 47 48 48 public boolean isMatchingMy( OsmPrimitive my) {49 public boolean isMatchingMy(IPrimitive my) { 49 50 return this.my == my; 50 51 } 51 52 -
src/org/openstreetmap/josm/data/conflict/ConflictCollection.java
11 11 import java.util.Set; 12 12 import java.util.concurrent.CopyOnWriteArrayList; 13 13 14 import org.openstreetmap.josm.data.osm.IPrimitive; 14 15 import org.openstreetmap.josm.data.osm.OsmPrimitive; 15 16 import org.openstreetmap.josm.tools.CheckParameterUtil; 16 17 … … 151 152 * @return the conflict for the {@link OsmPrimitive} <code>my</code>, null 152 153 * if no such conflict exists. 153 154 */ 154 public Conflict<?> getConflictForMy( OsmPrimitive my) {155 public Conflict<?> getConflictForMy(IPrimitive my) { 155 156 for(Conflict<?> c : conflicts) { 156 157 if (c.isMatchingMy(my)) 157 158 return c;