Changeset 2604 in josm for trunk/src/org


Ignore:
Timestamp:
2009-12-10T18:42:41+01:00 (15 years ago)
Author:
Gubaer
Message:

New: JOSM reading, writing, merging changeset attribute
fixed #4090: Add changeset:* search option to JOSM's search engine

Location:
trunk/src/org/openstreetmap/josm
Files:
9 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java

    r2567 r2604  
    126126                    + "<li>"+tr("<b>user:anonymous</b> - all objects changed by anonymous users")+"</li>"
    127127                    + "<li>"+tr("<b>id:</b>... - object with given ID (0 for new objects)")+"</li>"
     128                    + "<li>"+tr("<b>changeset:</b>... - object with given changeset id (0 objects without assigned changeset)")+"</li>"
    128129                    + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes")+"</li>"
    129130                    + "<li>"+tr("<b>tags:</b>... - object with given number of tags (tags:count or tags:min-max)")+"</li>"
  • trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java

    r2578 r2604  
    8585        }
    8686        @Override public String toString() {return "id="+id;}
     87    }
     88
     89    private static class ChangesetId extends Match {
     90        private long changesetid;
     91        public ChangesetId(long changesetid) {this.changesetid = changesetid;}
     92        @Override public boolean match(OsmPrimitive osm) {
     93            return osm.getChangesetId() == changesetid;
     94        }
     95        @Override public String toString() {return "changeset="+changesetid;}
    8796    }
    8897
     
    693702                throw new ParseError(tr("Incorrect value of id operator: {0}. Number is expected.", value));
    694703            }
     704        } else if (key.equals("changeset")) {
     705            try {
     706                return new ChangesetId(Integer.parseInt(value));
     707            } catch (NumberFormatException x) {
     708                throw new ParseError(tr("Incorrect value of changeset operator: {0}. Number is expected.", value));
     709            }
    695710        } else
    696711            return new KeyValue(key, value, regexSearch, caseSensitive);
  • trunk/src/org/openstreetmap/josm/data/osm/Changeset.java

    r2598 r2604  
    1717public final class Changeset implements Tagged {
    1818    /** the changeset id */
    19     private long id;
     19    private int id;
    2020    /** the user who owns the changeset */
    2121    private User user;
     
    5050     * @param id the id
    5151     */
    52     public Changeset(long id) {
     52    public Changeset(int id) {
    5353        this.id = id;
    5454        this.incomplete = id > 0;
     
    9090
    9191    public int compareTo(Changeset other) {
    92         return Long.valueOf(getId()).compareTo(other.getId());
     92        return Integer.valueOf(getId()).compareTo(other.getId());
    9393    }
    9494
     
    102102    }
    103103
    104     public long getId() {
     104    public int getId() {
    105105        return id;
    106106    }
    107107
    108     public void setId(long id) {
     108    public void setId(int id) {
    109109        this.id = id;
    110110    }
     
    234234        final int prime = 31;
    235235        int result = 1;
    236         result = prime * result + (int) (id ^ (id >>> 32));
     236        result = prime * result + (id ^ (id >>> 32));
    237237        if (id > 0)
    238238            return prime * result + getClass().hashCode();
     
    306306        return id <= 0;
    307307    }
     308
     309    public void mergeFrom(Changeset other) {
     310        if (other == null)
     311            return;
     312        if (id != other.id)
     313            return;
     314        this.user = other.user;
     315        this.createdAt = other.createdAt;
     316        this.closedAt = other.closedAt;
     317        this.open  = other.open;
     318        this.min = other.min;
     319        this.max = other.max;
     320        this.tags.clear();
     321        this.tags.putAll(other.tags);
     322    }
    308323}
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r2603 r2604  
    238238
    239239    /**
     240     * The id of the changeset this primitive was last uploaded to.
     241     * 0 if it wasn't uploaded to a changeset yet of if the changeset
     242     * id isn't known.
     243     */
     244    private int changesetId;
     245
     246    /**
    240247     * Creates a new primitive for the given id. If the id > 0, the primitive is marked
    241248     * as incomplete.
     
    577584    public void setUser(User user) {
    578585        this.user = user;
     586    }
     587
     588
     589    /**
     590     * Replies the id of the changeset this primitive was last uploaded to.
     591     * 0 if this primitive wasn't uploaded to a changeset yet or if the
     592     * changeset isn't known.
     593     *
     594     * @return the id of the changeset this primitive was last uploaded to.
     595     */
     596    public int getChangesetId() {
     597        return changesetId;
     598    }
     599
     600
     601    /**
     602     * Sets the changeset id of this primitive. Can't be set on a new
     603     * primitive.
     604     *
     605     * @param changesetId the id. >= 0 required.
     606     * @throws IllegalStateException thrown if this primitive is new.
     607     * @throws IllegalArgumentException thrown if id < 0
     608     */
     609    public void setChangesetId(int changesetId) throws IllegalStateException, IllegalArgumentException {
     610        if (changesetId < 0)
     611            throw new IllegalArgumentException(tr("Parameter ''{0}'' >= 0 expected, got {1}", "changesetId", changesetId));
     612        if (isNew() && changesetId > 0)
     613            throw new IllegalStateException(tr("Can''t assign a changesetId > 0 to a new primitive. Value of changesetId is {0}", changesetId));
     614        this.changesetId = changesetId;
    579615    }
    580616
     
    916952     * use this only in the data initializing phase
    917953     */
    918     public void cloneFrom(OsmPrimitive osm) {
    919         setKeys(osm.getKeys());
    920         id = osm.id;
    921         timestamp = osm.timestamp;
    922         version = osm.version;
    923         setIncomplete(osm.isIncomplete());
    924         flags = osm.flags;
    925         user= osm.user;
     954    public void cloneFrom(OsmPrimitive other) {
     955        setKeys(other.getKeys());
     956        id = other.id;
     957        timestamp = other.timestamp;
     958        version = other.version;
     959        setIncomplete(other.isIncomplete());
     960        flags = other.flags;
     961        user= other.user;
     962        changesetId = other.changesetId;
    926963        clearCached();
    927964    }
     
    951988        flags = other.flags;
    952989        user= other.user;
     990        changesetId = other.changesetId;
    953991    }
    954992
     
    10001038        && version == other.version
    10011039        && isVisible() == other.isVisible()
    1002         && (user == null ? other.user==null : user==other.user);
     1040        && (user == null ? other.user==null : user==other.user)
     1041        && changesetId == other.changesetId;
    10031042    }
    10041043
     
    10981137        timestamp = data.getTimestamp();
    10991138        user = data.getUser();
     1139        changesetId = data.getChangesetId();
    11001140        setDeleted(data.isDeleted());
    11011141        setModified(data.isModified());
     
    11181158        data.setModified(isModified());
    11191159        data.setVisible(isVisible());
     1160        data.setChangesetId(changesetId);
    11201161    }
    11211162
  • trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java

    r2598 r2604  
    4646    private int version;
    4747    private int timestamp;
     48    private int changesetId;
    4849
    4950    public boolean isModified() {
     
    8990        this.timestamp = timestamp;
    9091    }
     92
     93    public int getChangesetId() {
     94        return changesetId;
     95    }
     96
     97    public void setChangesetId(int changesetId) {
     98        this.changesetId = changesetId;
     99    }
     100
    91101    public Map<String, String> getKeys() {
    92102        return keys;
  • trunk/src/org/openstreetmap/josm/io/DiffResultProcessor.java

    r2600 r2604  
    77import java.io.StringReader;
    88import java.util.Collection;
     9import java.util.Collections;
    910import java.util.HashMap;
     11import java.util.HashSet;
    1012import java.util.Map;
     13import java.util.Set;
    1114
    1215import javax.xml.parsers.ParserConfigurationException;
    1316import javax.xml.parsers.SAXParserFactory;
    1417
    15 import org.openstreetmap.josm.data.osm.Node;
     18import org.openstreetmap.josm.data.osm.Changeset;
    1619import org.openstreetmap.josm.data.osm.OsmPrimitive;
    17 import org.openstreetmap.josm.data.osm.Relation;
    18 import org.openstreetmap.josm.data.osm.Way;
    19 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
     20import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     21import org.openstreetmap.josm.data.osm.PrimitiveId;
     22import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
     23import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    2024import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2125import org.xml.sax.Attributes;
    2226import org.xml.sax.InputSource;
     27import org.xml.sax.Locator;
    2328import org.xml.sax.SAXException;
    2429import org.xml.sax.helpers.DefaultHandler;
    2530
    26 /**
    27  */
    28 public class DiffResultReader extends AbstractVisitor {
     31public class DiffResultProcessor  {
    2932
    30     /**
    31      * mapping from old id to new id/version
    32      */
    33     private Map<String, Long[]> versions = new HashMap<String, Long[]>();
    34     private Collection<OsmPrimitive> processed;
    35     private Map<OsmPrimitive,Long> newIdMap;
    36 
    37     /**
    38      * List of protocol versions that will be accepted on reading
    39      */
    40 
    41     private class Parser extends DefaultHandler {
    42 
    43         @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    44             try {
    45                 if (qName.equals("osm")) {
    46                 } else if (qName.equals("node") || qName.equals("way") || qName.equals("relation")) {
    47                     String key = qName + ":" + atts.getValue("old_id");
    48                     String newid = atts.getValue("new_id");
    49                     String newver = atts.getValue("new_version");
    50                     Long[] value = new Long[] { newid == null ? null : new Long(newid), newver == null ? null : new Long(newver) };
    51                     versions.put(key, value);
    52                 }
    53             } catch (NumberFormatException x) {
    54                 x.printStackTrace(); // SAXException does not chain correctly
    55                 throw new SAXException(x.getMessage(), x);
    56             } catch (NullPointerException x) {
    57                 x.printStackTrace(); // SAXException does not chain correctly
    58                 throw new SAXException(tr("NullPointerException, possibly some missing tags."), x);
    59             }
    60         }
     33    static private class DiffResultEntry {
     34        public long new_id;
     35        public int new_version;
    6136    }
    6237
    6338    /**
    64      * Parse the given input source and return the dataset.
     39     * mapping from old id to new id and version, the result of parsing the diff result
     40     * replied by the server
    6541     */
    66     public static void parseDiffResult(String source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, ProgressMonitor progressMonitor)
    67     throws SAXException, IOException {
     42    private Map<PrimitiveId, DiffResultEntry> diffResults = new HashMap<PrimitiveId, DiffResultEntry>();
     43    /**
     44     * the set of processed primitives *after* the new id, the new version and the new changeset id
     45     * is set
     46     */
     47    private Set<OsmPrimitive> processed;
     48    /**
     49     * the collection of primitives being uploaded
     50     */
     51    private Collection<OsmPrimitive> primitives;
    6852
    69         progressMonitor.beginTask(tr("Preparing data..."));
     53    /**
     54     * Creates a diff result reader
     55     *
     56     * @param primitives the collection of primitives which have been uploaded. If null,
     57     * assumes an empty collection.
     58     */
     59    public DiffResultProcessor(Collection<OsmPrimitive> primitives) {
     60        if (primitives == null) {
     61            primitives = Collections.emptyList();
     62        }
     63        this.primitives = primitives;
     64        this.processed = new HashSet<OsmPrimitive>();
     65    }
     66
     67    /**
     68     * Parse the response from a diff upload to the OSM API.
     69     *
     70     * @param diffUploadResponse the response. Must not be null.
     71     * @param progressMonitor a progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null
     72     * @throws IllegalArgumentException thrown if diffUploadRequest is null
     73     * @throws OsmDataParsingException thrown if the diffUploadRequest can't be parsed successfully
     74     *
     75     */
     76    public  void parse(String diffUploadResponse, ProgressMonitor progressMonitor) throws OsmDataParsingException {
     77        if (progressMonitor == null) {
     78            progressMonitor = NullProgressMonitor.INSTANCE;
     79        }
     80        if (diffUploadResponse == null)
     81            throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "source"));
    7082        try {
    71 
    72             DiffResultReader drr = new DiffResultReader();
    73             drr.processed = processed;
    74             drr.newIdMap = newIdMap;
    75             InputSource inputSource = new InputSource(new StringReader(source));
    76             try {
    77                 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, drr.new Parser());
    78             } catch (ParserConfigurationException e1) {
    79                 e1.printStackTrace(); // broken SAXException chaining
    80                 throw new SAXException(e1);
    81             }
    82 
    83             for (OsmPrimitive p : osm) {
    84                 //System.out.println("old: "+ p);
    85                 p.visit(drr);
    86                 //System.out.println("new: "+ p);
    87                 //System.out.println("");
    88             }
     83            progressMonitor.beginTask(tr("Parsing response from server..."));
     84            InputSource inputSource = new InputSource(new StringReader(diffUploadResponse));
     85            SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new Parser());
     86        } catch(IOException e) {
     87            throw new OsmDataParsingException(e);
     88        } catch(ParserConfigurationException e) {
     89            throw new OsmDataParsingException(e);
     90        } catch(OsmDataParsingException e) {
     91            throw e;
     92        } catch(SAXException e) {
     93            throw new OsmDataParsingException(e);
    8994        } finally {
    9095            progressMonitor.finishTask();
     
    9297    }
    9398
    94     public void visit(Node n) {
    95         String key = "node:" + (newIdMap.containsKey(n) ? newIdMap.get(n) : n.getId());
    96         Long[] nv = versions.get(key);
    97         if (nv != null) {
    98             processed.add(n);
    99             if (!n.isDeleted()) {
    100                 n.setOsmId(nv[0], nv[1].intValue());
     99    /**
     100     * Postprocesses the diff result read and parsed from the server.
     101     *
     102     * Uploaded objects are assigned their new id (if they got assigned a new
     103     * id by the server), their new version (if the version was incremented),
     104     * and the id of the changeset to which they were uploaded.
     105     *
     106     * @param cs the current changeset. Ignored if null.
     107     * @param monitor the progress monitor. Set to {@see NullProgressMonitor#INSTANCE} if null
     108     * @return the collection of processed primitives
     109     */
     110    protected Set<OsmPrimitive> postProcess(Changeset cs,ProgressMonitor monitor) {
     111        if (monitor == null) {
     112            monitor = NullProgressMonitor.INSTANCE;
     113        }
     114        try {
     115            monitor.beginTask("Postprocessing uploaded data ...");
     116            monitor.setTicksCount(primitives.size());
     117            monitor.setTicks(0);
     118            for (OsmPrimitive p: primitives) {
     119                monitor.worked(1);
     120                DiffResultEntry entry = diffResults.get(p.getPrimitiveId());
     121                if (entry == null) {
     122                    continue;
     123                }
     124                processed.add(p);
     125                if (!p.isDeleted()) {
     126                    p.setOsmId(entry.new_id, entry.new_version);
     127                }
     128                if (cs != null && !cs.isNew()) {
     129                    p.setChangesetId(cs.getId());
     130                }
    101131            }
     132            return processed;
     133        } finally {
     134            monitor.finishTask();
    102135        }
    103136    }
    104     public void visit(Way w) {
    105         String key = "way:" + (newIdMap.containsKey(w) ? newIdMap.get(w) : w.getId());
    106         Long[] nv = versions.get(key);
    107         if (nv != null) {
    108             processed.add(w);
    109             if (!w.isDeleted()) {
    110                 w.setOsmId(nv[0], nv[1].intValue());
    111             }
     137
     138    private class Parser extends DefaultHandler {
     139        private Locator locator;
     140
     141        @Override
     142        public void setDocumentLocator(Locator locator) {
     143            this.locator = locator;
    112144        }
    113     }
    114     public void visit(Relation r) {
    115         String key = "relation:" + (newIdMap.containsKey(r) ? newIdMap.get(r) : r.getId());
    116         Long[] nv = versions.get(key);
    117         if (nv != null) {
    118             processed.add(r);
    119             if (!r.isDeleted()) {
    120                 r.setOsmId(nv[0], nv[1].intValue());
     145
     146        protected void throwException(String msg) throws OsmDataParsingException{
     147            throw new OsmDataParsingException(msg).rememberLocation(locator);
     148        }
     149
     150        @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
     151            try {
     152                if (qName.equals("diffResult")) {
     153                    // the root element, ignore
     154                } else if (qName.equals("node") || qName.equals("way") || qName.equals("relation")) {
     155
     156                    PrimitiveId id  = new SimplePrimitiveId(
     157                            Long.parseLong(atts.getValue("old_id")),
     158                            OsmPrimitiveType.fromApiTypeName(qName)
     159                    );
     160                    DiffResultEntry entry = new DiffResultEntry();
     161                    if (atts.getValue("new_id") != null) {
     162                        entry.new_id = Long.parseLong(atts.getValue("new_id"));
     163                    }
     164                    if (atts.getValue("new_version") != null) {
     165                        entry.new_version = Integer.parseInt(atts.getValue("new_version"));
     166                    }
     167                    diffResults.put(id, entry);
     168                } else {
     169                    throwException(tr("Unexpected XML element with name ''{0}''", qName));
     170                }
     171            } catch (NumberFormatException e) {
     172                throw new OsmDataParsingException(e).rememberLocation(locator);
    121173            }
    122174        }
  • trunk/src/org/openstreetmap/josm/io/OsmApi.java

    r2599 r2604  
    1919import java.net.URL;
    2020import java.net.UnknownHostException;
    21 import java.util.ArrayList;
    2221import java.util.Collection;
    2322import java.util.Collections;
     
    3029import org.openstreetmap.josm.data.osm.OsmPrimitive;
    3130import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    32 import org.openstreetmap.josm.data.osm.visitor.CreateOsmChangeVisitor;
    3331import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    3432import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     
    240238            ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/create", toXml(osm, true),monitor);
    241239            osm.setOsmId(Long.parseLong(ret.trim()), 1);
     240            osm.setChangesetId(getChangeset().getId());
    242241        } catch(NumberFormatException e){
    243242            throw new OsmTransferException(tr("Unexpected format of ID replied by the server. Got ''{0}''.", ret));
     
    260259            ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/" + osm.getId(), toXml(osm, true), monitor);
    261260            osm.setOsmId(osm.getId(), Integer.parseInt(ret.trim()));
     261            osm.setChangesetId(getChangeset().getId());
    262262        } catch(NumberFormatException e) {
    263263            throw new OsmTransferException(tr("Unexpected format of new version of modified primitive ''{0}''. Got ''{1}''.", osm.getId(), ret));
     
    301301            try {
    302302                ret = sendRequest("PUT", "changeset/create", toXml(changeset),progressMonitor);
    303                 changeset.setId(Long.parseLong(ret.trim()));
     303                changeset.setId(Integer.parseInt(ret.trim()));
    304304                changeset.setOpen(true);
    305305            } catch(NumberFormatException e){
     
    398398
    399399            initialize(monitor);
    400             final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
    401 
    402             CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, OsmApi.this);
    403 
    404             monitor.subTask(tr("Preparing..."));
    405             for (OsmPrimitive osm : list) {
    406                 osm.visit(duv);
    407                 monitor.worked(1);
    408             }
    409             monitor.indeterminateSubTask(tr("Uploading..."));
    410 
    411             String diff = duv.getDocument();
    412             String diffresult = sendRequest("POST", "changeset/" + changeset.getId() + "/upload", diff,monitor);
    413             DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(),
    414                     monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
    415             return processed;
     400
     401            // prepare upload request
     402            //
     403            OsmChangeBuilder changeBuilder = new OsmChangeBuilder(changeset);
     404            monitor.subTask(tr("Preparing upload request..."));
     405            changeBuilder.start();
     406            changeBuilder.append(list);
     407            changeBuilder.finish();
     408            String diffUploadRequest = changeBuilder.getDocument();
     409
     410            // Upload to the server
     411            //
     412            monitor.indeterminateSubTask(tr("Uploading {0} objects...", list.size()));
     413            String diffUploadResponse = sendRequest("POST", "changeset/" + changeset.getId() + "/upload", diffUploadRequest,monitor);
     414
     415            // Process the response from the server
     416            //
     417            DiffResultProcessor reader = new DiffResultProcessor(list);
     418            reader.parse(diffUploadResponse, monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
     419            return reader.postProcess(
     420                    getChangeset(),
     421                    monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)
     422            );
    416423        } catch(OsmTransferException e) {
    417424            throw e;
    418         } catch(Exception e) {
     425        } catch(OsmDataParsingException e) {
    419426            throw new OsmTransferException(e);
    420427        } finally {
  • trunk/src/org/openstreetmap/josm/io/OsmChangeBuilder.java

    r2600 r2604  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.data.osm.visitor;
     2package org.openstreetmap.josm.io;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    35
    46import java.io.PrintWriter;
    57import java.io.StringWriter;
    6 import java.util.Map;
     8import java.util.Collection;
    79
    810import org.openstreetmap.josm.data.osm.Changeset;
    9 import org.openstreetmap.josm.data.osm.Node;
    1011import org.openstreetmap.josm.data.osm.OsmPrimitive;
    11 import org.openstreetmap.josm.data.osm.Relation;
    12 import org.openstreetmap.josm.data.osm.Way;
    13 import org.openstreetmap.josm.io.OsmApi;
    14 import org.openstreetmap.josm.io.OsmWriter;
    1512
    1613/**
     
    1916 * OsmChange format.
    2017 *
    21  * @author fred
    22  *
    2318 */
    24 public class CreateOsmChangeVisitor extends AbstractVisitor {
     19public class OsmChangeBuilder {
     20    static public final String DEFAULT_API_VERSION = "0.6";
    2521
    2622    private String currentMode;
     
    2824    private StringWriter swriter;
    2925    private OsmWriter osmwriter;
    30     private OsmApi api;
     26    private String apiVersion = DEFAULT_API_VERSION;
     27    private boolean prologWritten = false;
    3128
    32     public CreateOsmChangeVisitor(Changeset changeset, OsmApi api) {
     29    public OsmChangeBuilder(Changeset changeset) {
     30        this(changeset, null /* default api version */);
     31    }
     32
     33    public OsmChangeBuilder(Changeset changeset, String apiVersion) {
     34        this.apiVersion = apiVersion == null ? DEFAULT_API_VERSION : apiVersion;
    3335        writer = new PrintWriter(swriter = new StringWriter());
    34         writer.write("<osmChange version=\"");
    35         writer.write(api.getVersion());
    36         writer.write("\" generator=\"JOSM\">\n");
    37         this.api = api;
    38         // need to set osmConform = false here so that negative IDs get transmitted.
    39         // this also enables unnecessary and (if the API were more strict) potentially
    40         // harmful action="..." attributes.
    41         osmwriter = new OsmWriter(writer, false, api.getVersion());
     36        osmwriter = new OsmWriter(writer, false, apiVersion);
    4237        osmwriter.setChangeset(changeset);
    4338    }
    4439
    45     // FIXME: This should really NOT use a visitor pattern, it looks
    46     // stupid. Just have one method named "write" instead of three "visit"s.
    47 
    48     public void visit(Node n) {
    49         if (n.isDeleted()) {
     40    protected void write(OsmPrimitive p) {
     41        if (p.isDeleted()) {
    5042            switchMode("delete");
    5143            osmwriter.setWithBody(false);
    52             osmwriter.visit(n);
     44            p.visit(osmwriter);
    5345        } else {
    54             switchMode(n.isNew() ? "create" : "modify");
     46            switchMode(p.isNew() ? "create" : "modify");
    5547            osmwriter.setWithBody(true);
    56             osmwriter.visit(n);
    57         }
    58     }
    59     public void visit(Way w) {
    60         if (w.isDeleted()) {
    61             switchMode("delete");
    62             osmwriter.setWithBody(false);
    63             osmwriter.visit(w);
    64         } else {
    65             switchMode(w.isNew() ? "create" : "modify");
    66             osmwriter.setWithBody(true);
    67             osmwriter.visit(w);
    68         }
    69     }
    70     public void visit(Relation r) {
    71         if (r.isDeleted()) {
    72             switchMode("delete");
    73             osmwriter.setWithBody(false);
    74             osmwriter.visit(r);
    75         } else {
    76             switchMode(r.isNew() ? "create" : "modify");
    77             osmwriter.setWithBody(true);
    78             osmwriter.visit(r);
     48            p.visit(osmwriter);
    7949        }
    8050    }
     
    8353        if ((newMode != null && !newMode.equals(currentMode))||(newMode == null && currentMode != null)) {
    8454            if (currentMode != null) {
    85                 writer.write("</");
    86                 writer.write(currentMode);
    87                 writer.write(">\n");
     55                writer.print("</");
     56                writer.print(currentMode);
     57                writer.println(">");
    8858            }
    8959            if (newMode != null) {
    90                 writer.write("<");
    91                 writer.write(newMode);
    92                 writer.write(" version=\"");
    93                 writer.write(api.getVersion());
    94                 writer.write("\" generator=\"JOSM\">\n");
     60                writer.print("<");
     61                writer.print(newMode);
     62                writer.println(">");
    9563            }
    9664            currentMode = newMode;
     
    9866    }
    9967
    100     public String getDocument() {
    101         switchMode(null);
    102         return swriter.toString() + "</osmChange>\n";
     68    /**
     69     * Writes the prolog of the OsmChange document
     70     *
     71     * @throws IllegalStateException thrown if the prologs has already been written
     72     */
     73    public void start() throws IllegalStateException{
     74        if (prologWritten)
     75            throw new IllegalStateException(tr("Prolog of OsmChange document already written. Please write only once."));
     76        writer.print("<osmChange version=\"");
     77        writer.print(apiVersion);
     78        writer.println("\" generator=\"JOSM\">");
     79        prologWritten=true;
    10380    }
    10481
    105     public Map<OsmPrimitive,Long> getNewIdMap() {
    106         return osmwriter.usedNewIds;
     82    /**
     83     * Appends a collection of {@see OsmPrimitive}s to the OsmChange document.
     84     *
     85     * @param primitives the collection of primitives. Ignored if null.
     86     * @throws IllegalStateException thrown if the prologs has not been written yet
     87     * @see #start()
     88     * @see #append(OsmPrimitive)
     89     */
     90    public void append(Collection<OsmPrimitive> primitives) throws IllegalStateException{
     91        if (primitives == null) return;
     92        if (!prologWritten)
     93            throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write frst."));
     94        for (OsmPrimitive p : primitives) {
     95            write(p);
     96        }
     97    }
     98
     99    /**
     100     * Appends an {@see OsmPrimitive} to the OsmChange document.
     101     *
     102     * @param p the primitive. Ignored if null.
     103     * @throws IllegalStateException thrown if the prologs has not been written yet
     104     * @see #start()
     105     * @see #append(Collection)
     106
     107     */
     108    public void append(OsmPrimitive p) {
     109        if (p == null) return;
     110        if (!prologWritten)
     111            throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write frst."));
     112        write(p);
     113    }
     114
     115    /**
     116     * Writes the epilog of the OsmChange document
     117     *
     118     * @throws IllegalStateException thrown if the prologs has not been written yet
     119     */
     120    public void finish() throws IllegalStateException {
     121        if (!prologWritten)
     122            throw new IllegalStateException(tr("Prolog of OsmChange document not written yet. Please write frst."));
     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();
    107133    }
    108134}
  • trunk/src/org/openstreetmap/josm/io/OsmChangesetParser.java

    r2512 r2604  
    7272                throwException(tr("Missing mandatory attribute ''{0}''.", "id"));
    7373            }
    74             long id = 0;
     74            int id = 0;
    7575            try {
    76                 id = Long.parseLong(value);
     76                id = Integer.parseInt(value);
    7777            } catch(NumberFormatException e) {
    7878                throwException(tr("Illegal value for attribute ''{0}''. Got ''{1}''.", "id", value));
  • trunk/src/org/openstreetmap/josm/io/OsmReader.java

    r2591 r2604  
    2525import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2626import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     27import org.openstreetmap.josm.data.osm.PrimitiveId;
    2728import org.openstreetmap.josm.data.osm.Relation;
    2829import org.openstreetmap.josm.data.osm.RelationMember;
     30import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
    2931import org.openstreetmap.josm.data.osm.User;
    3032import org.openstreetmap.josm.data.osm.Way;
     33import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    3134import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    3235import org.openstreetmap.josm.tools.DateUtils;
     
    6972     * </ul>
    7073     */
    71     private Map<String, OsmPrimitive> externalIdMap = new HashMap<String, OsmPrimitive>();
     74    private Map<PrimitiveId, OsmPrimitive> externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>();
    7275
    7376    /**
     
    7881     */
    7982    private OsmReader() {
    80         externalIdMap = new HashMap<String, OsmPrimitive>();
     83        externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>();
    8184    }
    8285
     
    9194        public LatLon latlon = new LatLon(0,0);
    9295        private OsmPrimitive primitive;
     96        private int changesetId;
    9397
    9498        public void copyTo(OsmPrimitive osm) {
     
    101105            osm.setTimestamp(timestamp);
    102106            osm.setUser(user);
    103             if (id > 0) {
     107            if (!osm.isNew() && changesetId > 0) {
     108                osm.setChangesetId(changesetId);
     109            } else if (osm.isNew() && changesetId > 0) {
     110                System.out.println(tr("Warning: ignoring changeset id {0} for new object with external id {1} and internal id {2}",
     111                        changesetId,
     112                        id,
     113                        osm.getUniqueId()
     114                ));
     115            }
     116            if (! osm.isNew()) {
    104117                // ignore visible attribute for objects not yet known to the server
    105118                //
     
    218231                readCommon(atts, current);
    219232                Node n = current.createNode();
    220                 externalIdMap.put("n"+current.id, n);
     233                externalIdMap.put(new SimplePrimitiveId(current.id, OsmPrimitiveType.NODE), n);
    221234            } else if (qName.equals("way")) {
    222235                current = new OsmPrimitiveData();
    223236                readCommon(atts, current);
    224237                Way w = current.createWay();
    225                 externalIdMap.put("w"+current.id, w);
     238                externalIdMap.put(new SimplePrimitiveId(current.id, OsmPrimitiveType.WAY), w);
    226239                ways.put(current.id, new ArrayList<Long>());
    227240            } else if (qName.equals("nd")) {
     
    251264                readCommon(atts, current);
    252265                Relation r = current.createRelation();
    253                 externalIdMap.put("r"+current.id, r );
     266                externalIdMap.put(new SimplePrimitiveId(current.id, OsmPrimitiveType.RELATION), r);
    254267                relations.put(current.id, new LinkedList<RelationMemberData>());
    255268            } else if (qName.equals("member")) {
     
    386399
    387400            String action = atts.getValue("action");
    388             if (action == null)
    389                 return;
    390             if (action.equals("delete")) {
     401            if (action == null) {
     402                // do nothing
     403            } else if (action.equals("delete")) {
    391404                current.deleted = true;
    392             } else if (action.startsWith("modify")) {
     405            } else if (action.startsWith("modify")) { //FIXME: why startsWith()? why not equals()?
    393406                current.modified = true;
     407            }
     408
     409            String v = atts.getValue("changeset");
     410            if (v == null) {
     411                current.changesetId = 0;
     412            } else {
     413                try {
     414                    current.changesetId = Integer.parseInt(v);
     415                } catch(NumberFormatException e) {
     416                    if (current.id <= 0) {
     417                        // for a new primitive we just log a warning
     418                        System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.id));
     419                        current.changesetId = 0;
     420                    } else {
     421                        // for an existing primitive this is a problem
     422                        throwException(tr("Illegal value for attribute ''changeset''. Got {0}.", v));
     423                    }
     424                }
     425                if (current.changesetId <=0) {
     426                    if (current.id <= 0) {
     427                        // for a new primitive we just log a warning
     428                        System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.id));
     429                        current.changesetId = 0;
     430                    } else {
     431                        // for an existing primitive this is a problem
     432                        throwException(tr("Illegal value for attribute ''changeset''. Got {0}.", v));
     433                    }
     434                }
    394435            }
    395436        }
     
    417458    protected void processWaysAfterParsing() throws IllegalDataException{
    418459        for (Long externalWayId: ways.keySet()) {
    419             Way w = (Way)externalIdMap.get("w" + externalWayId);
     460            Way w = (Way)externalIdMap.get(new SimplePrimitiveId(externalWayId, OsmPrimitiveType.WAY));
    420461            List<Node> wayNodes = new ArrayList<Node>();
    421462            for (long id : ways.get(externalWayId)) {
    422                 Node n = (Node)externalIdMap.get("n" +id);
     463                Node n = (Node)externalIdMap.get(new SimplePrimitiveId(id, OsmPrimitiveType.NODE));
    423464                if (n == null) {
    424465                    if (id <= 0)
     
    476517    private void processRelationsAfterParsing() throws IllegalDataException {
    477518        for (Long externalRelationId : relations.keySet()) {
    478             Relation relation = (Relation) externalIdMap.get("r" +externalRelationId);
     519            Relation relation = (Relation) externalIdMap.get(
     520                    new SimplePrimitiveId(externalRelationId, OsmPrimitiveType.RELATION)
     521            );
    479522            List<RelationMember> relationMembers = new ArrayList<RelationMember>();
    480523            for (RelationMemberData rm : relations.get(externalRelationId)) {
     
    483526                // lookup the member from the map of already created primitives
    484527                //
    485                 if (rm.type.equals("node")) {
    486                     primitive = externalIdMap.get("n" + rm.id);
    487                 } else if (rm.type.equals("way")) {
    488                     primitive = externalIdMap.get("w" + rm.id);
    489                 } else if (rm.type.equals("relation")) {
    490                     primitive = externalIdMap.get("r" + rm.id);
    491                 } else
     528                try {
     529                    OsmPrimitiveType type = OsmPrimitiveType.fromApiTypeName(rm.type);
     530                    primitive = externalIdMap.get(new SimplePrimitiveId(rm.id, type));
     531                } catch(IllegalArgumentException e) {
    492532                    throw new IllegalDataException(
    493533                            tr("Unknown relation member type ''{0}'' in relation with external id ''{1}''.", rm.type,externalRelationId)
    494534                    );
     535                }
    495536
    496537                if (primitive == null) {
     
    523564                    }
    524565                    ds.addPrimitive(primitive);
    525 
    526                     if (rm.type.equals("node")) {
    527                         externalIdMap.put("n" + rm.id, primitive);
    528                     } else if (rm.type.equals("way")) {
    529                         externalIdMap.put("w" + rm.id, primitive);
    530                     } else if (rm.type.equals("relation")) {
    531                         externalIdMap.put("r" + rm.id, primitive);
    532                     }
    533 
     566                    externalIdMap.put(new SimplePrimitiveId(rm.id, OsmPrimitiveType.fromApiTypeName(rm.type)), primitive);
    534567                }
    535568                relationMembers.add(new RelationMember(rm.role, primitive));
     
    543576     * Parse the given input source and return the dataset.
    544577     *
    545      * @param source the source input stream
    546      * @param progressMonitor  the progress monitor
     578     * @param source the source input stream. Must not be null.
     579     * @param progressMonitor  the progress monitor. If null, {@see NullProgressMonitor#INSTANCE} is assumed
    547580     *
    548581     * @return the dataset with the parsed data
    549582     * @throws IllegalDataException thrown if the an error was found while parsing the data from the source
     583     * @throws IllegalArgumentException thrown if source is null
    550584     */
    551585    public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
     586        if (progressMonitor == null) {
     587            progressMonitor = NullProgressMonitor.INSTANCE;
     588        }
     589        if (source == null)
     590            throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "source"));
    552591        OsmReader reader = new OsmReader();
    553592        try {
  • trunk/src/org/openstreetmap/josm/io/OsmWriter.java

    r2578 r2604  
    22package org.openstreetmap.josm.io;
    33
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.io.PrintWriter;
    5 import java.util.HashMap;
    67import java.util.Map.Entry;
    78
     
    2930    public final String DEFAULT_API_VERSION = "0.6";
    3031
    31     /**
    32      * The counter for newly created objects. Starts at -1 and goes down.
    33      */
    34     private long newIdCounter = -1;
    35 
    36     /**
    37      * All newly created ids and their primitive that uses it. This is a back reference
    38      * map to allow references to use the correnct primitives.
    39      */
    40     public HashMap<OsmPrimitive, Long> usedNewIds = new HashMap<OsmPrimitive, Long>();
    41 
    4232    private boolean osmConform;
    4333    private boolean withBody = true;
     
    123113            out.println(">");
    124114            for (Node n : w.getNodes()) {
    125                 out.println("    <nd ref='"+getUsedId(n)+"' />");
     115                out.println("    <nd ref='"+n.getUniqueId()+"' />");
    126116            }
    127117            addTags(w, "way", false);
     
    139129                out.print("    <member type='");
    140130                out.print(OsmPrimitiveType.from(em.getMember()).getAPIName());
    141                 out.println("' ref='"+getUsedId(em.getMember())+"' role='" +
     131                out.println("' ref='"+em.getMember().getUniqueId()+"' role='" +
    142132                        XmlWriter.encode(em.getRole()) + "' />");
    143133            }
     
    172162    }
    173163
    174     /**
    175      * Return the id for the given osm primitive (may access the usedId map)
    176      */
    177     private long getUsedId(OsmPrimitive osm) {
    178         if (!osm.isNew())
    179             return osm.getId();
    180         if (usedNewIds.containsKey(osm))
    181             return usedNewIds.get(osm);
    182         usedNewIds.put(osm, newIdCounter);
    183         return osmConform ? 0 : newIdCounter--;
    184     }
    185 
    186164    private void addTags(Tagged osm, String tagname, boolean tagOpen) {
    187165        if (osm.hasKeys()) {
     
    208186     */
    209187    private void addCommon(OsmPrimitive osm, String tagname) {
    210         long id = getUsedId(osm);
    211188        out.print("  <"+tagname);
    212         if (id != 0) {
    213             out.print(" id='"+getUsedId(osm)+"'");
    214         }
     189        if (osm.getUniqueId() != 0) {
     190            out.print(" id='"+ osm.getUniqueId()+"'");
     191        } else
     192            throw new IllegalStateException(tr("Unexpected id 0 for osm primitive found"));
    215193        if (!osmConform) {
    216194            String action = null;
     
    243221        if (this.changeset != null && this.changeset.getId() != 0) {
    244222            out.print(" changeset='"+this.changeset.getId()+"'" );
     223        } else if (osm.getChangesetId() > 0 && !osm.isNew()) {
     224            out.print(" changeset='"+osm.getChangesetId()+"'" );
    245225        }
    246226    }
Note: See TracChangeset for help on using the changeset viewer.