Changeset 2598 in josm


Ignore:
Timestamp:
2009-12-09T21:24:32+01:00 (12 years ago)
Author:
Gubaer
Message:

comment to follow in a later commit
Have to break up a commit because of SSL problem in SVN (filed a ticket - #4093)

Location:
trunk/src/org/openstreetmap/josm
Files:
1 deleted
12 edited

Legend:

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

    r2325 r2598  
    1515import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTaskList;
    1616import org.openstreetmap.josm.data.osm.DataSource;
     17import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    1718import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
    1819import org.openstreetmap.josm.tools.Shortcut;
     
    3839    protected void updateEnabledState() {
    3940        setEnabled(getEditLayer() != null);
     41    }
     42
     43    public void updateLayer(OsmDataLayer layer) {
     44       
    4045    }
    4146
  • trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java

    r2578 r2598  
    33
    44import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull;
    56import static org.openstreetmap.josm.tools.I18n.tr;
    67
    78import java.awt.event.ActionEvent;
    89import java.awt.event.KeyEvent;
    9 import java.io.IOException;
    1010import java.util.Collection;
    1111import java.util.Collections;
     
    1515import org.openstreetmap.josm.Main;
    1616import org.openstreetmap.josm.data.osm.DataSet;
    17 import org.openstreetmap.josm.data.osm.DataSetMerger;
    18 import org.openstreetmap.josm.data.osm.Node;
    1917import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2018import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    21 import org.openstreetmap.josm.data.osm.Relation;
    22 import org.openstreetmap.josm.data.osm.Way;
     19import org.openstreetmap.josm.data.osm.PrimitiveId;
    2320import org.openstreetmap.josm.gui.ExceptionDialogUtil;
    24 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     21import org.openstreetmap.josm.gui.io.UpdatePrimitivesTask;
    2522import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    26 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2723import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
    28 import org.openstreetmap.josm.io.OsmServerObjectReader;
    29 import org.openstreetmap.josm.io.OsmTransferException;
    3024import org.openstreetmap.josm.tools.Shortcut;
    31 import org.xml.sax.SAXException;
    3225
    3326/**
     
    4235     * @param id the primitive id
    4336     */
    44     protected void handlePrimitiveGoneException(long id, OsmPrimitiveType type) {
     37    public void handlePrimitiveGoneException(long id, OsmPrimitiveType type) {
    4538        MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
    4639        reader.append(getCurrentDataSet(),id, type);
     
    6255     */
    6356    public void updatePrimitives(final Collection<OsmPrimitive> selection) {
    64         UpdatePrimitivesTask task = new UpdatePrimitivesTask(selection);
     57        UpdatePrimitivesTask task = new UpdatePrimitivesTask(Main.main.getEditLayer(),selection);
    6558        Main.worker.submit(task);
    6659    }
     
    7063     * with the data currently kept on the server.
    7164     *
    72      * @param id  the id of a primitive in the {@see DataSet} of the current edit layer
     65     * @param id  the id of a primitive in the {@see DataSet} of the current edit layer. Must not be null.
     66     * @throws IllegalArgumentException thrown if id is null
    7367     * @exception IllegalStateException thrown if there is no primitive with <code>id</code> in
    7468     *   the current dataset
     
    7670     *
    7771     */
    78     public void updatePrimitive(OsmPrimitiveType type, long id) throws IllegalStateException{
     72    public void updatePrimitive(PrimitiveId id) throws IllegalStateException, IllegalArgumentException{
     73        ensureParameterNotNull(id, "id");
    7974        if (getEditLayer() == null)
    8075            throw new IllegalStateException(tr("No current dataset found"));
    81         OsmPrimitive primitive = getEditLayer().data.getPrimitiveById(id, type);
     76        OsmPrimitive primitive = getEditLayer().data.getPrimitiveById(id);
    8277        if (primitive == null)
    8378            throw new IllegalStateException(tr("Didn''t find an object with id {0} in the current dataset", id));
     
    132127        updatePrimitives(selection);
    133128    }
    134 
    135     /**
    136      * The asynchronous task for updating the data using multi fetch.
    137      *
    138      */
    139     static class UpdatePrimitivesTask extends PleaseWaitRunnable {
    140         //static private final Logger logger = Logger.getLogger(UpdatePrimitivesTask.class.getName());
    141 
    142         private DataSet ds;
    143         private boolean canceled;
    144         private Exception lastException;
    145         private Collection<? extends OsmPrimitive> toUpdate;
    146         private MultiFetchServerObjectReader reader;
    147 
    148         /**
    149          *
    150          * @param toUpdate a collection of primitives to update from the server
    151          */
    152         public UpdatePrimitivesTask(Collection<? extends OsmPrimitive> toUpdate) {
    153             super(tr("Update objects"), false /* don't ignore exception*/);
    154             canceled = false;
    155             this.toUpdate = toUpdate;
    156         }
    157 
    158         @Override
    159         protected void cancel() {
    160             canceled = true;
    161             if (reader != null) {
    162                 reader.cancel();
    163             }
    164         }
    165 
    166         @Override
    167         protected void finish() {
    168             if (canceled)
    169                 return;
    170             if (lastException != null) {
    171                 ExceptionDialogUtil.explainException(lastException);
    172                 return;
    173             }
    174             if (ds != null && Main.main.getEditLayer() != null) {
    175                 Main.main.getEditLayer().mergeFrom(ds);
    176                 Main.main.getEditLayer().onPostDownloadFromServer();
    177             }
    178         }
    179 
    180         protected void initMultiFetchReaderWithNodes(MultiFetchServerObjectReader reader) {
    181             for (OsmPrimitive primitive : toUpdate) {
    182                 if (primitive instanceof Node && !primitive.isNew()) {
    183                     reader.append((Node)primitive);
    184                 } else if (primitive instanceof Way) {
    185                     Way way = (Way)primitive;
    186                     for (Node node: way.getNodes()) {
    187                         if (!node.isNew()) {
    188                             reader.append(node);
    189                         }
    190                     }
    191                 }
    192             }
    193         }
    194 
    195         protected void initMultiFetchReaderWithWays(MultiFetchServerObjectReader reader) {
    196             for (OsmPrimitive primitive : toUpdate) {
    197                 if (primitive instanceof Way && !primitive.isNew()) {
    198                     reader.append((Way)primitive);
    199                 }
    200             }
    201         }
    202 
    203         protected void initMultiFetchReaderWithRelations(MultiFetchServerObjectReader reader) {
    204             for (OsmPrimitive primitive : toUpdate) {
    205                 if (primitive instanceof Relation && !primitive.isNew()) {
    206                     reader.append((Relation)primitive);
    207                 }
    208             }
    209         }
    210 
    211         @Override
    212         protected void realRun() throws SAXException, IOException, OsmTransferException {
    213             progressMonitor.indeterminateSubTask("");
    214             this.ds = new DataSet();
    215             DataSet theirDataSet;
    216             try {
    217                 reader = new MultiFetchServerObjectReader();
    218                 initMultiFetchReaderWithNodes(reader);
    219                 initMultiFetchReaderWithWays(reader);
    220                 initMultiFetchReaderWithRelations(reader);
    221                 theirDataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
    222                 DataSetMerger merger = new DataSetMerger(ds, theirDataSet);
    223                 merger.merge();
    224                 // a way loaded with MultiFetch may be incomplete because at least one of its
    225                 // nodes isn't present in the local data set. We therefore fully load all
    226                 // incomplete ways.
    227                 //
    228                 for (Way w : ds.getWays()) {
    229                     if (w.isIncomplete()) {
    230                         OsmServerObjectReader reader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
    231                         theirDataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
    232                         merger = new DataSetMerger(ds, theirDataSet);
    233                         merger.merge();
    234                     }
    235                 }
    236             } catch(Exception e) {
    237                 if (canceled)
    238                     return;
    239                 lastException = e;
    240             }
    241         }
    242     }
    243129}
  • trunk/src/org/openstreetmap/josm/actions/UploadAction.java

    r2569 r2598  
    77import java.awt.event.ActionEvent;
    88import java.awt.event.KeyEvent;
    9 import java.io.IOException;
    10 import java.net.HttpURLConnection;
    11 import java.text.SimpleDateFormat;
    12 import java.util.Collection;
    13 import java.util.Date;
    14 import java.util.HashSet;
    159import java.util.LinkedList;
    1610import java.util.logging.Logger;
    17 import java.util.regex.Matcher;
    18 import java.util.regex.Pattern;
    1911
    2012import javax.swing.JOptionPane;
     
    2416import org.openstreetmap.josm.actions.upload.RelationUploadOrderHook;
    2517import org.openstreetmap.josm.actions.upload.UploadHook;
    26 import org.openstreetmap.josm.actions.upload.UploadParameterHook;
    2718import org.openstreetmap.josm.data.APIDataSet;
    2819import org.openstreetmap.josm.data.conflict.ConflictCollection;
    29 import org.openstreetmap.josm.data.osm.Changeset;
    30 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    31 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    32 import org.openstreetmap.josm.gui.DefaultNameFormatter;
    33 import org.openstreetmap.josm.gui.ExceptionDialogUtil;
    34 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    35 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    36 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
    3720import org.openstreetmap.josm.gui.io.UploadDialog;
    38 import org.openstreetmap.josm.gui.io.UploadStrategySpecification;
     21import org.openstreetmap.josm.gui.io.UploadPrimitivesTask;
    3922import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    40 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    41 import org.openstreetmap.josm.io.ChangesetClosedException;
    42 import org.openstreetmap.josm.io.OsmApi;
    43 import org.openstreetmap.josm.io.OsmApiException;
    44 import org.openstreetmap.josm.io.OsmApiInitializationException;
    45 import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;
    46 import org.openstreetmap.josm.io.OsmServerWriter;
    47 import org.openstreetmap.josm.io.OsmTransferException;
    48 import org.openstreetmap.josm.tools.DateUtils;
    49 import org.openstreetmap.josm.tools.ImageProvider;
    5023import org.openstreetmap.josm.tools.Shortcut;
    51 import org.xml.sax.SAXException;
    5224
    5325/**
     
    8456         */
    8557        uploadHooks.add(new RelationUploadOrderHook());
    86 
    87         /**
    88          * Displays a screen where the actions that would be taken are displayed and
    89          * give the user the possibility to cancel the upload.
    90          */
    91         uploadHooks.add(new UploadParameterHook());
    9258    }
    9359
     
    168134        if (!checkPreUploadConditions(layer, apiData))
    169135            return;
     136
     137        final UploadDialog dialog = UploadDialog.getUploadDialog();
     138        dialog.setUploadedPrimitives(apiData);
     139        dialog.setVisible(true);
     140        if (dialog.isCanceled())
     141            return;
     142        dialog.rememberUserInput();
     143
    170144        Main.worker.execute(
    171145                new UploadPrimitivesTask(
    172146                        UploadDialog.getUploadDialog().getUploadStrategySpecification(),
    173147                        layer,
    174                         apiData.getPrimitives(),
    175                         UploadDialog.getUploadDialog().getChangeset(),
    176                         UploadDialog.getUploadDialog().isDoCloseAfterUpload()
     148                        apiData,
     149                        UploadDialog.getUploadDialog().getChangeset()
    177150                )
    178151        );
     
    194167        uploadData(Main.map.mapView.getEditLayer(), apiData);
    195168    }
    196 
    197     /**
    198      * Synchronizes the local state of an {@see OsmPrimitive} with its state on the
    199      * server. The method uses an individual GET for the primitive.
    200      *
    201      * @param id the primitive ID
    202      */
    203     protected void synchronizePrimitive(final OsmPrimitiveType type, final long id) {
    204         Main.worker.execute(new UpdatePrimitiveTask(type, id));
    205     }
    206 
    207     /**
    208      * Synchronizes the local state of the dataset with the state on the server.
    209      *
    210      * Reuses the functionality of {@see UpdateDataAction}.
    211      *
    212      * @see UpdateDataAction#actionPerformed(ActionEvent)
    213      */
    214     protected void synchronizeDataSet() {
    215         UpdateDataAction act = new UpdateDataAction();
    216         act.actionPerformed(new ActionEvent(this,0,""));
    217     }
    218 
    219     /**
    220      * Handles the case that a conflict in a specific {@see OsmPrimitive} was detected while
    221      * uploading
    222      *
    223      * @param primitiveType  the type of the primitive, either <code>node</code>, <code>way</code> or
    224      *    <code>relation</code>
    225      * @param id  the id of the primitive
    226      * @param serverVersion  the version of the primitive on the server
    227      * @param myVersion  the version of the primitive in the local dataset
    228      */
    229     protected void handleUploadConflictForKnownConflict(final OsmPrimitiveType primitiveType, final long id, String serverVersion, String myVersion) {
    230         String lbl = "";
    231         switch(primitiveType) {
    232         case NODE: lbl =  tr("Synchronize node {0} only", id); break;
    233         case WAY: lbl =  tr("Synchronize way {0} only", id); break;
    234         case RELATION: lbl =  tr("Synchronize relation {0} only", id); break;
    235         }
    236         ButtonSpec[] spec = new ButtonSpec[] {
    237                 new ButtonSpec(
    238                         lbl,
    239                         ImageProvider.get("updatedata"),
    240                         null,
    241                         null
    242                 ),
    243                 new ButtonSpec(
    244                         tr("Synchronize entire dataset"),
    245                         ImageProvider.get("updatedata"),
    246                         null,
    247                         null
    248                 ),
    249                 new ButtonSpec(
    250                         tr("Cancel"),
    251                         ImageProvider.get("cancel"),
    252                         null,
    253                         null
    254                 )
    255         };
    256         String msg =  tr("<html>Uploading <strong>failed</strong> because the server has a newer version of one<br>"
    257                 + "of your nodes, ways, or relations.<br>"
    258                 + "The conflict is caused by the <strong>{0}</strong> with id <strong>{1}</strong>,<br>"
    259                 + "the server has version {2}, your version is {3}.<br>"
    260                 + "<br>"
    261                 + "Click <strong>{4}</strong> to synchronize the conflicting primitive only.<br>"
    262                 + "Click <strong>{5}</strong> to synchronize the entire local dataset with the server.<br>"
    263                 + "Click <strong>{6}</strong> to abort and continue editing.<br></html>",
    264                 tr(primitiveType.getAPIName()), id, serverVersion, myVersion,
    265                 spec[0].text, spec[1].text, spec[2].text
    266         );
    267         int ret = HelpAwareOptionPane.showOptionDialog(
    268                 Main.parent,
    269                 msg,
    270                 tr("Conflicts detected"),
    271                 JOptionPane.ERROR_MESSAGE,
    272                 null,
    273                 spec,
    274                 spec[0],
    275                 "/Concepts/Conflict"
    276         );
    277         switch(ret) {
    278         case 0: synchronizePrimitive(primitiveType, id); break;
    279         case 1: synchronizeDataSet(); break;
    280         default: return;
    281         }
    282     }
    283 
    284     /**
    285      * Handles the case that a conflict was detected while uploading where we don't
    286      * know what {@see OsmPrimitive} actually caused the conflict (for whatever reason)
    287      *
    288      */
    289     protected void handleUploadConflictForUnknownConflict() {
    290         ButtonSpec[] spec = new ButtonSpec[] {
    291                 new ButtonSpec(
    292                         tr("Synchronize entire dataset"),
    293                         ImageProvider.get("updatedata"),
    294                         null,
    295                         null
    296                 ),
    297                 new ButtonSpec(
    298                         tr("Cancel"),
    299                         ImageProvider.get("cancel"),
    300                         null,
    301                         null
    302                 )
    303         };
    304         String msg =  tr("<html>Uploading <strong>failed</strong> because the server has a newer version of one<br>"
    305                 + "of your nodes, ways, or relations.<br>"
    306                 + "<br>"
    307                 + "Click <strong>{0}</strong> to synchronize the entire local dataset with the server.<br>"
    308                 + "Click <strong>{1}</strong> to abort and continue editing.<br></html>",
    309                 spec[0].text, spec[1].text
    310         );
    311         int ret = HelpAwareOptionPane.showOptionDialog(
    312                 Main.parent,
    313                 msg,
    314                 tr("Conflicts detected"),
    315                 JOptionPane.ERROR_MESSAGE,
    316                 null,
    317                 spec,
    318                 spec[0],
    319                 "Concepts/Conflict"
    320         );
    321         if (ret == 0) {
    322             synchronizeDataSet();
    323         }
    324     }
    325 
    326     /**
    327      * Handles the case that a conflict was detected while uploading where we don't
    328      * know what {@see OsmPrimitive} actually caused the conflict (for whatever reason)
    329      *
    330      */
    331     protected void handleUploadConflictForClosedChangeset(long changsetId, Date d) {
    332         String msg =  tr("<html>Uploading <strong>failed</strong> because you''ve been using<br>"
    333                 + "changeset {0} which was already closed at {1}.<br>"
    334                 + "Please upload again with a new or an existing open changeset.</html>",
    335                 changsetId, new SimpleDateFormat().format(d)
    336         );
    337         JOptionPane.showMessageDialog(
    338                 Main.parent,
    339                 msg,
    340                 tr("Changeset closed"),
    341                 JOptionPane.ERROR_MESSAGE
    342         );
    343     }
    344 
    345     /**
    346      * Handles the case where deleting a node failed because it is still in use in
    347      * a non-deleted way on the server.
    348      */
    349     protected void handleUploadConflictForNodeStillInUse(long nodeId, long wayId) {
    350         ButtonSpec[] options = new ButtonSpec[] {
    351                 new ButtonSpec(
    352                         tr("Prepare conflict resolution"),
    353                         ImageProvider.get("ok"),
    354                         tr("Click to download all parent ways for node {0}", nodeId),
    355                         null /* no specific help context */
    356                 ),
    357                 new ButtonSpec(
    358                         tr("Cancel"),
    359                         ImageProvider.get("cancel"),
    360                         tr("Click to cancel and to resume editing the map", nodeId),
    361                         null /* no specific help context */
    362                 )
    363         };
    364         String msg =  tr("<html>Uploading <strong>failed</strong> because you tried "
    365                 + "to delete node {0} which is still in use in way {1}.<br><br>"
    366                 + "Click <strong>{2}</strong> to download all parent ways of node {0}.<br>"
    367                 + "If necessary JOSM will create conflicts which you can resolve in the Conflict Resolution Dialog."
    368                 + "</html>",
    369                 nodeId, wayId, options[0].text
    370         );
    371 
    372         int ret = HelpAwareOptionPane.showOptionDialog(
    373                 Main.parent,
    374                 msg,
    375                 tr("Node still in use"),
    376                 JOptionPane.ERROR_MESSAGE,
    377                 null,
    378                 options,
    379                 options[0],
    380                 "/Action/Upload#NodeStillInUseInWay"
    381         );
    382         if (ret != 0) return;
    383         DownloadReferrersAction.downloadReferrers(Main.map.mapView.getEditLayer(), nodeId, OsmPrimitiveType.NODE);
    384     }
    385 
    386     /**
    387      * handles an upload conflict, i.e. an error indicated by a HTTP return code 409.
    388      *
    389      * @param e  the exception
    390      */
    391     protected void handleUploadConflict(OsmApiException e) {
    392         String pattern = "Version mismatch: Provided (\\d+), server had: (\\d+) of (\\S+) (\\d+)";
    393         Pattern p = Pattern.compile(pattern);
    394         Matcher m = p.matcher(e.getErrorHeader());
    395         if (m.matches()) {
    396             handleUploadConflictForKnownConflict(OsmPrimitiveType.from(m.group(3)), Long.parseLong(m.group(4)), m.group(2),m.group(1));
    397             return;
    398         }
    399         pattern ="The changeset (\\d+) was closed at (.*)";
    400         p = Pattern.compile(pattern);
    401         m = p.matcher(e.getErrorHeader());
    402         if (m.matches()) {
    403             handleUploadConflictForClosedChangeset(Long.parseLong(m.group(1)), DateUtils.fromString(m.group(2)));
    404             return;
    405         }
    406         pattern = "Node (\\d+) is still used by way (\\d+).";
    407         p = Pattern.compile(pattern);
    408         m = p.matcher(e.getErrorHeader());
    409         if (m.matches()) {
    410             handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));
    411             return;
    412         }
    413         logger.warning(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));
    414         handleUploadConflictForUnknownConflict();
    415     }
    416 
    417     /**
    418      * handles an precondition failed conflict, i.e. an error indicated by a HTTP return code 412.
    419      *
    420      * @param e  the exception
    421      */
    422     protected void handlePreconditionFailed(OsmApiException e) {
    423         String pattern = "Precondition failed: Node (\\d+) is still used by way (\\d+).";
    424         Pattern p = Pattern.compile(pattern);
    425         Matcher m = p.matcher(e.getErrorHeader());
    426         if (m.matches()) {
    427             handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));
    428             return;
    429         }
    430         logger.warning(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));
    431         ExceptionDialogUtil.explainPreconditionFailed(e);
    432     }
    433 
    434     /**
    435      * Handles an error due to a delete request on an already deleted
    436      * {@see OsmPrimitive}, i.e. a HTTP response code 410, where we know what
    437      * {@see OsmPrimitive} is responsible for the error.
    438      *
    439      *  Reuses functionality of the {@see UpdateSelectionAction} to resolve
    440      *  conflicts due to mismatches in the deleted state.
    441      *
    442      * @param primitiveType the type of the primitive
    443      * @param id the id of the primitive
    444      *
    445      * @see UpdateSelectionAction#handlePrimitiveGoneException(long)
    446      */
    447     protected void handleGoneForKnownPrimitive(OsmPrimitiveType primitiveType, long id) {
    448         UpdateSelectionAction act = new UpdateSelectionAction();
    449         act.handlePrimitiveGoneException(id,primitiveType);
    450     }
    451 
    452     /**
    453      * Handles an error which is caused by a delete request for an already deleted
    454      * {@see OsmPrimitive} on the server, i.e. a HTTP response code of 410.
    455      * Note that an <strong>update</strong> on an already deleted object results
    456      * in a 409, not a 410.
    457      *
    458      * @param e the exception
    459      */
    460     protected void handleGone(OsmApiPrimitiveGoneException e) {
    461         if (e.isKnownPrimitive()) {
    462             handleGoneForKnownPrimitive(e.getPrimitiveType(), e.getPrimitiveId());
    463         } else {
    464             ExceptionDialogUtil.explainGoneForUnknownPrimitive(e);
    465         }
    466     }
    467 
    468     /**
    469      * error handler for any exception thrown during upload
    470      *
    471      * @param e the exception
    472      */
    473     protected void handleFailedUpload(Exception e) {
    474         // API initialization failed. Notify the user and return.
    475         //
    476         if (e instanceof OsmApiInitializationException) {
    477             ExceptionDialogUtil.explainOsmApiInitializationException((OsmApiInitializationException)e);
    478             return;
    479         }
    480 
    481         if (e instanceof OsmApiPrimitiveGoneException) {
    482             handleGone((OsmApiPrimitiveGoneException)e);
    483             return;
    484         }
    485         if (e instanceof OsmApiException) {
    486             OsmApiException ex = (OsmApiException)e;
    487             // There was an upload conflict. Let the user decide whether
    488             // and how to resolve it
    489             //
    490             if(ex.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) {
    491                 handleUploadConflict(ex);
    492                 return;
    493             }
    494             // There was a precondition failed. Notify the user.
    495             //
    496             else if (ex.getResponseCode() == HttpURLConnection.HTTP_PRECON_FAILED) {
    497                 handlePreconditionFailed(ex);
    498                 return;
    499             }
    500             // Tried to update or delete a primitive which never existed on
    501             // the server?
    502             //
    503             else if (ex.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
    504                 ExceptionDialogUtil.explainNotFound(ex);
    505                 return;
    506             }
    507         }
    508 
    509         ExceptionDialogUtil.explainException(e);
    510     }
    511 
    512     /**
    513      * The asynchronous task to update a specific id
    514      *
    515      */
    516     class UpdatePrimitiveTask extends  PleaseWaitRunnable {
    517 
    518         private boolean uploadCancelled = false;
    519         private boolean uploadFailed = false;
    520         private Exception lastException = null;
    521         private long id;
    522         private OsmPrimitiveType type;
    523 
    524         public UpdatePrimitiveTask(OsmPrimitiveType type, long id) {
    525             super(tr("Updating primitive"),false /* don't ignore exceptions */);
    526             this.id = id;
    527             this.type = type;
    528         }
    529 
    530         @Override protected void realRun() throws SAXException, IOException {
    531             try {
    532                 UpdateSelectionAction act = new UpdateSelectionAction();
    533                 act.updatePrimitive(type, id);
    534             } catch (Exception sxe) {
    535                 if (uploadCancelled) {
    536                     System.out.println("Ignoring exception caught because upload is canceled. Exception is: " + sxe.toString());
    537                     return;
    538                 }
    539                 uploadFailed = true;
    540                 lastException = sxe;
    541             }
    542         }
    543 
    544         @Override protected void finish() {
    545             if (uploadFailed) {
    546                 handleFailedUpload(lastException);
    547             }
    548         }
    549 
    550         @Override protected void cancel() {
    551             OsmApi.getOsmApi().cancel();
    552             uploadCancelled = true;
    553         }
    554     }
    555 
    556     /**
    557      * The task for uploading a collection of primitives
    558      *
    559      */
    560     public class UploadPrimitivesTask extends  PleaseWaitRunnable {
    561         private boolean uploadCancelled = false;
    562         private Exception lastException = null;
    563         private Collection <OsmPrimitive> toUpload;
    564         private OsmServerWriter writer;
    565         private OsmDataLayer layer;
    566         private Changeset changeset;
    567         private boolean closeChangesetAfterUpload;
    568         private HashSet<OsmPrimitive> processedPrimitives;
    569         private UploadStrategySpecification strategy;
    570 
    571         /**
    572          * Creates the task
    573          * @param strategy the upload strategy
    574          * @param layer  the OSM data layer for which data is uploaded
    575          * @param toUpload the collection of primitives to upload
    576          * @param changeset the changeset to use for uploading
    577          * @param closeChangesetAfterUpload true, if the changeset is to be closed after uploading
    578          */
    579         private UploadPrimitivesTask(UploadStrategySpecification strategy, OsmDataLayer layer, Collection <OsmPrimitive> toUpload, Changeset changeset, boolean closeChangesetAfterUpload) {
    580             super(tr("Uploading data for layer ''{0}''", layer.getName()),false /* don't ignore exceptions */);
    581             this.toUpload = toUpload;
    582             this.layer = layer;
    583             this.changeset = changeset;
    584             this.strategy = strategy;
    585             this.closeChangesetAfterUpload = closeChangesetAfterUpload;
    586             this.processedPrimitives = new HashSet<OsmPrimitive>();
    587         }
    588 
    589         protected OsmPrimitive getPrimitive(OsmPrimitiveType type, long id) {
    590             for (OsmPrimitive p: toUpload) {
    591                 if (OsmPrimitiveType.from(p).equals(type) && p.getId() == id)
    592                     return p;
    593             }
    594             return null;
    595         }
    596 
    597         /**
    598          * Retries to recover the upload operation from an exception which was thrown because
    599          * an uploaded primitive was already deleted on the server.
    600          *
    601          * @param e the exception throw by the API
    602          * @param monitor a progress monitor
    603          * @throws OsmTransferException  thrown if we can't recover from the exception
    604          */
    605         protected void recoverFromGoneOnServer(OsmApiPrimitiveGoneException e, ProgressMonitor monitor) throws OsmTransferException{
    606             if (!e.isKnownPrimitive()) throw e;
    607             OsmPrimitive p = getPrimitive(e.getPrimitiveType(), e.getPrimitiveId());
    608             if (p == null) throw e;
    609             if (p.isDeleted()) {
    610                 // we tried to delete an already deleted primitive.
    611                 //
    612                 System.out.println(tr("Warning: object ''{0}'' is already deleted on the server. Skipping this object and retrying to upload.", p.getDisplayName(DefaultNameFormatter.getInstance())));
    613                 monitor.appendLogMessage(tr("Object ''{0}'' is already deleted. Skipping object in upload.",p.getDisplayName(DefaultNameFormatter.getInstance())));
    614                 processedPrimitives.addAll(writer.getProcessedPrimitives());
    615                 processedPrimitives.add(p);
    616                 toUpload.removeAll(processedPrimitives);
    617                 return;
    618             }
    619             // exception was thrown because we tried to *update* an already deleted
    620             // primitive. We can't resolve this automatically. Re-throw exception,
    621             // a conflict is going to be created later.
    622             throw e;
    623         }
    624 
    625         @Override protected void realRun() throws SAXException, IOException {
    626             writer = new OsmServerWriter();
    627             try {
    628                 while(true) {
    629                     try {
    630                         getProgressMonitor().subTask(tr("Uploading {0} objects ...", toUpload.size()));
    631                         writer.uploadOsm(strategy, toUpload, changeset, getProgressMonitor().createSubTaskMonitor(1, false));
    632                         processedPrimitives.addAll(writer.getProcessedPrimitives());
    633                         // if we get here we've successfully uploaded the data. Exit the loop.
    634                         //
    635                         break;
    636                     } catch(OsmApiPrimitiveGoneException e) {
    637                         // try to recover from the 410 Gone
    638                         recoverFromGoneOnServer(e, getProgressMonitor());
    639                     }
    640                 }
    641                 // if required close the changeset
    642                 //
    643                 if (closeChangesetAfterUpload) {
    644                     if (changeset != null && changeset.getId() > 0) {
    645                         OsmApi.getOsmApi().closeChangeset(changeset, progressMonitor.createSubTaskMonitor(0,false));
    646                     }
    647                 }
    648             } catch (Exception e) {
    649                 if (uploadCancelled) {
    650                     System.out.println(tr("Ignoring caught exception because upload is canceled. Exception is: {0}", e.toString()));
    651                     return;
    652                 }
    653                 lastException = e;
    654             }
    655         }
    656 
    657         @Override protected void finish() {
    658             if (uploadCancelled)
    659                 return;
    660 
    661             // we always clean up the data, even in case of errors. It's possible the data was
    662             // partially uploaded
    663             //
    664             layer.cleanupAfterUpload(processedPrimitives);
    665             layer.fireDataChange();
    666             if (lastException != null) {
    667                 handleFailedUpload(lastException);
    668             }
    669             layer.onPostUploadToServer();
    670             if (lastException != null && lastException instanceof ChangesetClosedException) {
    671                 UploadDialog.getUploadDialog().removeChangeset(changeset);
    672             } else {
    673                 UploadDialog.getUploadDialog().setOrUpdateChangeset(changeset);
    674             }
    675         }
    676 
    677         @Override protected void cancel() {
    678             uploadCancelled = true;
    679             if (writer != null) {
    680                 writer.cancel();
    681             }
    682         }
    683     }
    684169}
  • trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java

    r2569 r2598  
    2323        OsmApi api = OsmApi.getOsmApi();
    2424        try {
     25            // FIXME: this should run asynchronously and a progress monitor
     26            // should be displayed.
    2527            api.initialize(NullProgressMonitor.INSTANCE);
    2628            long maxNodes = 0;
     
    2830                maxNodes = api.getCapabilities().getLong("waynodes","maximum");
    2931            }
    30             long maxElements = 0;
    31             if (api.getCapabilities().isDefined("changesets", "maximum_elements")) {
    32                 maxElements = api.getCapabilities().getLong("changesets", "maximum_elements");
    33             }
    34 
    3532            if (maxNodes > 0) {
    3633                if( !checkMaxNodes(apiData.getPrimitivesToAdd(), maxNodes))
     
    4037                if( !checkMaxNodes(apiData.getPrimitivesToDelete(), maxNodes))
    4138                    return false;
    42             }
    43 
    44             if (maxElements  > 0) {
    45                 int total = 0;
    46                 total = apiData.getPrimitivesToAdd().size() + apiData.getPrimitivesToUpdate().size() + apiData.getPrimitivesToDelete().size();
    47                 if(total > maxElements) {
    48                     JOptionPane.showMessageDialog(
    49                             Main.parent,
    50                             tr("Current number of changes exceeds the max. number of changes, current is {0}, max is {1}",
    51                                     total,
    52                                     maxElements
    53                             ),
    54                             tr("API Capabilities Violation"),
    55                             JOptionPane.ERROR_MESSAGE
    56                     );
    57                     return false;
    58                 }
    5939            }
    6040        } catch (OsmApiInitializationException e) {
  • trunk/src/org/openstreetmap/josm/data/APIDataSet.java

    r2512 r2598  
    1414import java.util.logging.Logger;
    1515
     16import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException;
    1617import org.openstreetmap.josm.data.osm.DataSet;
    1718import org.openstreetmap.josm.data.osm.Node;
     
    2122import org.openstreetmap.josm.data.osm.Way;
    2223
    23 import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException;
    24 
    2524/**
    2625 * Represents a collection of {@see OsmPrimitive}s which should be uploaded to the
    2726 * API.
    28  * The collection is derived from the modified primitives of an {@see DataSet}.
     27 * The collection is derived from the modified primitives of an {@see DataSet} and it provides methods
     28 * for sorting the objects in upload order.
    2929 *
    3030 */
     
    212212
    213213    /**
     214     * Replies the number of objects to upload
     215     *
     216     * @return the number of objects to upload
     217     */
     218    public int getSize() {
     219        return toAdd.size() + toUpdate.size() + toDelete.size();
     220    }
     221
     222    public void removeProcessed(Collection<OsmPrimitive> processed) {
     223        if (processed == null) return;
     224        toAdd.removeAll(processed);
     225        toUpdate.removeAll(processed);
     226        toDelete.removeAll(processed);
     227    }
     228
     229    /**
    214230     * Adjusts the upload order for new relations. Child relations are uploaded first,
    215231     * parent relations second.
  • trunk/src/org/openstreetmap/josm/data/osm/Changeset.java

    r2512 r2598  
    11// License: GPL. Copyright 2007 by Martijn van Oosterhout and others
    22package org.openstreetmap.josm.data.osm;
    3 
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    53
    64import java.util.Collection;
     
    10098    }
    10199
    102     public String getLocalName(){
    103         return tr("Changeset {0}",getId());
    104     }
    105 
    106100    public String getDisplayName(NameFormatter formatter) {
    107101        return formatter.format(this);
     
    308302        return tags.keySet();
    309303    }
     304
     305    public boolean isNew() {
     306        return id <= 0;
     307    }
    310308}
  • trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java

    r2512 r2598  
    173173    }
    174174
     175    public boolean isNew() {
     176        return id <= 0;
     177    }
    175178}
  • trunk/src/org/openstreetmap/josm/data/osm/PrimitiveId.java

    r2399 r2598  
    55
    66    long getUniqueId();
    7 
    87    OsmPrimitiveType getType();
    98
     9    /**
     10     * Replies true if this id represents a new primitive.
     11     *
     12     * @return true if this id represents a new primitive.
     13     */
     14    boolean isNew();
     15
    1016}
  • trunk/src/org/openstreetmap/josm/data/osm/RelationMember.java

    r2399 r2598  
    171171        return member.getUniqueId();
    172172    }
     173
     174    public boolean isNew() {
     175        return member.isNew();
     176    }
    173177}
  • trunk/src/org/openstreetmap/josm/data/osm/RelationMemberData.java

    r2404 r2598  
    5151    }
    5252
     53    public boolean isNew() {
     54        return memberId <= 0;
     55    }
    5356}
  • trunk/src/org/openstreetmap/josm/data/osm/SimplePrimitiveId.java

    r2448 r2598  
    1818    public long getUniqueId() {
    1919        return id;
     20    }
     21
     22    public boolean isNew() {
     23        return id <= 0;
    2024    }
    2125
  • trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java

    r2512 r2598  
    5959                tr("Error"),
    6060                JOptionPane.ERROR_MESSAGE,
    61                 ht("/ErrorMessages#ChangesetClosedException")
     61                ht("/Action/Upload#ChangesetClosed")
    6262        );
    6363    }
Note: See TracChangeset for help on using the changeset viewer.