Ticket #21427: 21427.patch

File 21427.patch, 75.0 KB (added by marcello@…, 3 years ago)
  • src/org/openstreetmap/josm/actions/UploadAction.java

     
    3535import org.openstreetmap.josm.io.UploadStrategySpecification;
    3636import org.openstreetmap.josm.spi.preferences.Config;
    3737import org.openstreetmap.josm.tools.ImageProvider;
     38import org.openstreetmap.josm.tools.Logging;
    3839import org.openstreetmap.josm.tools.Shortcut;
    3940import org.openstreetmap.josm.tools.Utils;
    4041
     
    239240        ChangesetUpdater.check();
    240241
    241242        final UploadDialog dialog = UploadDialog.getUploadDialog();
     243        dialog.setUploadedPrimitives(apiData);
    242244        dialog.initLifeCycle(layer.getDataSet());
    243         dialog.setUploadedPrimitives(apiData);
    244245        dialog.setVisible(true);
    245246        dialog.rememberUserInput();
    246247        if (dialog.isCanceled()) {
     
    266267        }
    267268
    268269        UploadStrategySpecification uploadStrategySpecification = dialog.getUploadStrategySpecification();
     270        Logging.info("Starting upload with tags {0}", changesetTags);
     271        Logging.info(uploadStrategySpecification.toString());
     272        Logging.info(cs.toString());
    269273        dialog.clean();
    270274
    271275        if (Config.getPref().getBoolean(IS_ASYNC_UPLOAD_ENABLED, true)) {
  • src/org/openstreetmap/josm/data/osm/Changeset.java

     
    317317                .ifPresent(value -> {
    318318                throw new IllegalArgumentException("Changeset tag value is too long: "+value);
    319319        });
    320         this.tags = keys;
     320        this.tags = new HashMap<>(keys);
    321321    }
    322322
    323323    /**
  • src/org/openstreetmap/josm/data/osm/ChangesetCache.java

     
    1212import java.util.stream.Collectors;
    1313
    1414import org.openstreetmap.josm.data.UserIdentityManager;
     15import org.openstreetmap.josm.io.ChangesetQuery;
     16import org.openstreetmap.josm.io.OsmServerChangesetReader;
     17import org.openstreetmap.josm.io.OsmTransferException;
    1518import org.openstreetmap.josm.spi.preferences.Config;
    1619import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
    1720import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
     21import org.openstreetmap.josm.tools.Logging;
    1822import org.openstreetmap.josm.tools.SubclassFilteredCollection;
    1923import org.openstreetmap.josm.tools.Utils;
    2024
     
    254258        }
    255259    }
    256260
     261    /**
     262     * Refreshes the changesets from the server.
     263     * <p>
     264     * The server automatically closes changesets after a timeout.  We don't get notified of this
     265     * fact when it happens.  This method requests a fresh list from the server and updates the
     266     * local list.  Calling this method reduces (but does not eliminate) the probability of
     267     * attempting an upload to an already closed changeset.
     268     *
     269     * @throws OsmTransferException on server error
     270     */
     271    public void refreshChangesetsFromServer() throws OsmTransferException {
     272        OsmServerChangesetReader reader;
     273        synchronized (this) {
     274            reader = new OsmServerChangesetReader();
     275        }
     276        List<Changeset> server = reader.queryChangesets(ChangesetQuery.forCurrentUser().beingOpen(true), null);
     277        Logging.info("{0} Open changesets on server", server.size());
     278
     279        DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
     280        // flag timed out changesets
     281        for (Changeset cs : getOpenChangesetsForCurrentUser()) {
     282            if (!server.contains(cs))
     283                remove(cs.getId(), e);
     284        }
     285        for (Changeset cs: server) {
     286            update(cs, e);
     287        }
     288        fireChangesetCacheEvent(e);
     289    }
     290
    257291    /* ------------------------------------------------------------------------- */
    258292    /* interface PreferenceChangedListener                                       */
    259293    /* ------------------------------------------------------------------------- */
  • src/org/openstreetmap/josm/gui/io/BasicUploadSettingsPanel.java

     
    102102        build();
    103103    }
    104104
     105    protected void build() {
     106        setLayout(new GridBagLayout());
     107        setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
     108        GBC gbc = GBC.eop().fill(GBC.HORIZONTAL);
     109        add(buildUploadCommentPanel(), gbc);
     110        add(buildUploadSourcePanel(), gbc);
     111        add(pnlUploadParameterSummary, gbc);
     112        if (Config.getPref().getBoolean("upload.show.review.request", true)) {
     113            add(cbRequestReview, gbc);
     114            cbRequestReview.addItemListener(this);
     115        }
     116        add(areaValidatorFeedback, gbc);
     117        add(new JPanel(), GBC.std().fill(GBC.BOTH));
     118    }
     119
    105120    protected JPanel buildUploadCommentPanel() {
    106121        JPanel pnl = new JPanel(new GridBagLayout());
    107122        pnl.setBorder(BorderFactory.createTitledBorder(tr("Provide a brief comment for the changes you are uploading:")));
     
    113128        editor.addKeyListener(this);
    114129        editor.addFocusListener(this);
    115130        editor.addActionListener(this);
    116         pnl.add(hcbUploadComment, GBC.eol().fill(GBC.HORIZONTAL));
    117         pnl.add(uploadCommentFeedback, GBC.eol().insets(0, 3, 0, 0).fill(GBC.HORIZONTAL));
     131        GBC gbc = GBC.eol().insets(3).fill(GBC.HORIZONTAL);
     132        pnl.add(hcbUploadComment, gbc);
     133        pnl.add(uploadCommentFeedback, gbc);
    118134        return pnl;
    119135    }
    120136
     
    141157        obtainSource.add(obtainSourceAutomatically, GBC.std().anchor(GBC.WEST));
    142158        obtainSource.add(obtainSourceOnce, GBC.std().anchor(GBC.WEST));
    143159        obtainSource.add(new JLabel(), GBC.eol().fill(GBC.HORIZONTAL));
    144         if (Config.getPref().getBoolean("upload.show.automatic.source", true)) {
    145             pnl.add(obtainSource, GBC.eol().insets(0, 0, 10, 3).fill(GBC.HORIZONTAL));
    146         }
    147160
    148161        hcbUploadSource.setToolTipText(tr("Enter a source"));
    149162        hcbUploadSource.getEditorComponent().setMaxTextLength(Changeset.MAX_CHANGESET_TAG_LENGTH);
     
    152165        editor.addKeyListener(this);
    153166        editor.addFocusListener(this);
    154167        editor.addActionListener(this);
    155         pnl.add(hcbUploadSource, GBC.eol().fill(GBC.HORIZONTAL));
    156         pnl.add(hcbUploadSourceFeedback, GBC.eol().insets(0, 3, 0, 0).fill(GBC.HORIZONTAL));
    157 
     168        GBC gbc = GBC.eol().insets(3).fill(GBC.HORIZONTAL);
     169        if (Config.getPref().getBoolean("upload.show.automatic.source", true)) {
     170            pnl.add(obtainSource, gbc);
     171        }
     172        pnl.add(hcbUploadSource, gbc);
     173        pnl.add(hcbUploadSourceFeedback, gbc);
    158174        return pnl;
    159175    }
    160176
     
    161177    /**
    162178     * Initializes this life cycle of the panel.
    163179     *
    164      * Adds any changeset tags to the map.
     180     * Adds the comment and source tags from history, and/or obtains the source from the layer if
     181     * the user said so.
    165182     *
    166183     * @param map Map where tags are added to.
    167184     * @since 18173
     
    178195        hcbUploadComment.discardAllUndoableEdits();
    179196        hcbUploadSource.getModel().prefs().load(SOURCE_HISTORY_KEY, getDefaultSources());
    180197        hcbUploadSource.discardAllUndoableEdits();
     198        hcbUploadComment.getEditorComponent().requestFocusInWindow();
     199        uploadCommentValidator.validate();
     200        uploadSourceValidator.validate();
    181201    }
    182202
    183203    /**
     
    234254        return Arrays.asList(areaValidator, uploadCommentValidator, uploadSourceValidator);
    235255    }
    236256
    237     protected void build() {
    238         setLayout(new GridBagLayout());
    239         setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
    240         GBC gbc = GBC.eol().insets(0, 0, 0, 20).fill(GBC.HORIZONTAL);
    241         add(buildUploadCommentPanel(), gbc);
    242         add(buildUploadSourcePanel(), gbc);
    243         add(pnlUploadParameterSummary, gbc);
    244         if (Config.getPref().getBoolean("upload.show.review.request", true)) {
    245             add(cbRequestReview, gbc);
    246             cbRequestReview.addItemListener(this);
    247         }
    248         add(areaValidatorFeedback, gbc);
    249         add(new JPanel(), GBC.std().fill(GBC.BOTH));
    250     }
    251 
    252257    /**
    253258     * Remembers the user input in the preference settings
    254259     */
     
    268273    }
    269274
    270275    /**
    271      * Initializes the panel for user input
    272      */
    273     public void startUserInput() {
    274         hcbUploadComment.getEditorComponent().requestFocusInWindow();
    275         uploadCommentValidator.validate();
    276         uploadSourceValidator.validate();
    277     }
    278 
    279     /**
    280276     * Initializes editing of upload comment.
    281277     */
    282278    public void initEditingOfUploadComment() {
  • src/org/openstreetmap/josm/gui/io/ChangesetCellRenderer.java

     
    6262        }
    6363        if (cs != null) {
    6464            setIcon(icon);
    65             StringBuilder sb = new StringBuilder();
    66             String comment = cs.getComment();
    67             if (!comment.isEmpty()) {
    68                 sb.append(cs.getId()).append(" - ").append(comment);
    69             } else if (cs.get("name") != null) {
    70                 sb.append(cs.getId()).append(" - ").append(cs.get("name"));
     65            if (cs.getId() == 0) {
     66                setText("New changeset");
    7167            } else {
    72                 sb.append(tr("Changeset {0}", cs.getId()));
     68                StringBuilder sb = new StringBuilder();
     69                String comment = cs.getComment();
     70                if (!comment.isEmpty()) {
     71                    sb.append(cs.getId()).append(" - ").append(comment);
     72                } else if (cs.get("name") != null) {
     73                    sb.append(cs.getId()).append(" - ").append(cs.get("name"));
     74                } else {
     75                    sb.append(tr("Changeset {0}", cs.getId()));
     76                }
     77                setText(sb.toString());
    7378            }
    74             setText(sb.toString());
    7579            setToolTipText(buildToolTipText(cs));
    7680        } else {
    77             setText(tr("No open changesets"));
     81            setIcon(null);
     82            setText("");
    7883        }
    7984        return this;
    8085    }
  • src/org/openstreetmap/josm/gui/io/ChangesetManagementPanel.java

     
    1111import java.awt.event.ItemEvent;
    1212import java.awt.event.ItemListener;
    1313import java.util.Collections;
     14import java.util.Optional;
    1415
    1516import javax.swing.AbstractAction;
    1617import javax.swing.BorderFactory;
    17 import javax.swing.ButtonGroup;
    1818import javax.swing.JButton;
    1919import javax.swing.JCheckBox;
    2020import javax.swing.JPanel;
    21 import javax.swing.JRadioButton;
    22 import javax.swing.event.ListDataEvent;
    23 import javax.swing.event.ListDataListener;
     21import javax.swing.SwingUtilities;
    2422
    2523import org.openstreetmap.josm.data.osm.Changeset;
    2624import org.openstreetmap.josm.data.osm.ChangesetCache;
     25import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
     26import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
    2727import org.openstreetmap.josm.gui.MainApplication;
    2828import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    2929import org.openstreetmap.josm.gui.widgets.JosmComboBox;
     30import org.openstreetmap.josm.gui.widgets.JosmComboBoxModel;
     31import org.openstreetmap.josm.io.OsmTransferException;
    3032import org.openstreetmap.josm.spi.preferences.Config;
    3133import org.openstreetmap.josm.tools.ImageProvider;
    3234
     
    4446 *   whether the changeset should be closed after the next upload</li>
    4547 * </ul>
    4648 */
    47 public class ChangesetManagementPanel extends JPanel implements ListDataListener {
     49public class ChangesetManagementPanel extends JPanel implements ItemListener, ChangesetCacheListener {
    4850    static final String SELECTED_CHANGESET_PROP = ChangesetManagementPanel.class.getName() + ".selectedChangeset";
    4951    static final String CLOSE_CHANGESET_AFTER_UPLOAD = ChangesetManagementPanel.class.getName() + ".closeChangesetAfterUpload";
    5052
    51     private JRadioButton rbUseNew;
    52     private JRadioButton rbExisting;
    5353    private JosmComboBox<Changeset> cbOpenChangesets;
     54    private JosmComboBoxModel<Changeset> model;
    5455    private JCheckBox cbCloseAfterUpload;
    55     private OpenChangesetComboBoxModel model;
     56    private JButton btnClose;
    5657
    57     /** the changeset comment model */
    58     private final transient UploadDialogModel uploadDialogModel;
    59 
    6058    /**
    6159     * Constructs a new {@code ChangesetManagementPanel}.
    6260     *
    63      * @param uploadDialogModel The tag editor model.
    64      *
    65      * @since 18173 (signature)
     61     * @since xxx (signature)
    6662     */
    67     public ChangesetManagementPanel(UploadDialogModel uploadDialogModel) {
    68         this.uploadDialogModel = uploadDialogModel;
     63    public ChangesetManagementPanel() {
    6964        build();
    70         refreshGUI();
    7165    }
    7266
    7367    /**
     68     * Initializes this life cycle of the panel.
     69     *
     70     * @since xxx
     71     */
     72    public void initLifeCycle() {
     73        refreshChangesets();
     74    }
     75
     76    /**
     77     * Returns the model in use.
     78     * @return the model
     79     */
     80    public JosmComboBoxModel<Changeset> getModel() {
     81        return model;
     82    }
     83
     84    /**
    7485     * builds the GUI
    7586     */
    7687    protected void build() {
    7788        setLayout(new GridBagLayout());
     89        setBorder(BorderFactory.createTitledBorder(tr("Please select a changeset:")));
     90
    7891        GridBagConstraints gc = new GridBagConstraints();
    79         setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
    80 
    81         ButtonGroup bgUseNewOrExisting = new ButtonGroup();
    82 
    83         gc.gridwidth = 4;
    8492        gc.gridx = 0;
    8593        gc.gridy = 0;
    86         gc.fill = GridBagConstraints.HORIZONTAL;
    8794        gc.weightx = 1.0;
    8895        gc.weighty = 0.0;
    89         gc.insets = new Insets(0, 0, 5, 0);
    90         add(new JMultilineLabel(
    91                 tr("Please decide what changeset the data is uploaded to and whether to close the changeset after the next upload.")), gc);
    92 
    93         gc.gridwidth = 4;
    94         gc.gridy = 1;
    9596        gc.fill = GridBagConstraints.HORIZONTAL;
    96         gc.weightx = 1.0;
    97         gc.weighty = 0.0;
    98         gc.insets = new Insets(0, 0, 0, 0);
    99         gc.anchor = GridBagConstraints.FIRST_LINE_START;
    100         rbUseNew = new JRadioButton(tr("Upload to a new changeset"));
    101         rbUseNew.setToolTipText(tr("Open a new changeset and use it in the next upload"));
    102         bgUseNewOrExisting.add(rbUseNew);
    103         add(rbUseNew, gc);
     97        gc.anchor = GridBagConstraints.NORTHWEST;
     98        gc.insets = new Insets(3, 3, 3, 3);
    10499
    105         gc.gridx = 0;
    106         gc.gridy = 2;
    107         gc.gridwidth = 1;
    108         gc.weightx = 0.0;
    109         gc.fill = GridBagConstraints.HORIZONTAL;
    110         rbExisting = new JRadioButton(tr("Upload to an existing changeset"));
    111         rbExisting.setToolTipText(tr("Upload data to an already existing and open changeset"));
    112         bgUseNewOrExisting.add(rbExisting);
    113         add(rbExisting, gc);
     100        gc.gridwidth = 3;
     101        add(new JMultilineLabel(tr(
     102            "Please select which changeset the data shall be uploaded to and whether to close that changeset after the next upload."
     103            )), gc);
    114104
    115         gc.gridx = 1;
    116         gc.gridy = 2;
    117105        gc.gridwidth = 1;
    118         gc.weightx = 1.0;
    119         model = new OpenChangesetComboBoxModel();
    120         ChangesetCache.getInstance().addChangesetCacheListener(model);
     106        gc.gridy++;
     107        model = new JosmComboBoxModel<>();
    121108        cbOpenChangesets = new JosmComboBox<>(model);
    122         cbOpenChangesets.setToolTipText(tr("Select an open changeset"));
     109        cbOpenChangesets.setToolTipText(tr("Select a changeset"));
    123110        cbOpenChangesets.setRenderer(new ChangesetCellRenderer());
    124         cbOpenChangesets.addItemListener(new ChangesetListItemStateListener());
    125111        Dimension d = cbOpenChangesets.getPreferredSize();
    126112        d.width = 200;
    127113        cbOpenChangesets.setPreferredSize(d);
    128114        d.width = 100;
    129115        cbOpenChangesets.setMinimumSize(d);
    130         model.addListDataListener(this);
    131116        add(cbOpenChangesets, gc);
     117        int h = cbOpenChangesets.getPreferredSize().height;
     118        Dimension prefSize = new Dimension(h, h);
    132119
    133         gc.gridx = 2;
    134         gc.gridy = 2;
     120        gc.gridx++;
    135121        gc.weightx = 0.0;
    136         gc.gridwidth = 1;
    137         gc.weightx = 0.0;
    138122        JButton btnRefresh = new JButton(new RefreshAction());
    139         btnRefresh.setMargin(new Insets(0, 0, 0, 0));
     123        btnRefresh.setPreferredSize(prefSize);
     124        btnRefresh.setMinimumSize(prefSize);
    140125        add(btnRefresh, gc);
    141126
    142         gc.gridx = 3;
    143         gc.gridy = 2;
    144         gc.gridwidth = 1;
     127        gc.gridx++;
    145128        CloseChangesetAction closeChangesetAction = new CloseChangesetAction();
    146         JButton btnClose = new JButton(closeChangesetAction);
    147         btnClose.setMargin(new Insets(0, 0, 0, 0));
    148         cbOpenChangesets.addItemListener(closeChangesetAction);
    149         rbExisting.addItemListener(closeChangesetAction);
     129        btnClose = new JButton(closeChangesetAction);
     130        btnClose.setPreferredSize(prefSize);
     131        btnClose.setMinimumSize(prefSize);
    150132        add(btnClose, gc);
    151133
     134        gc.gridy++;
    152135        gc.gridx = 0;
    153         gc.gridy = 3;
    154         gc.gridwidth = 4;
     136        gc.gridwidth = 3;
    155137        gc.weightx = 1.0;
    156138        cbCloseAfterUpload = new JCheckBox(tr("Close changeset after upload"));
    157139        cbCloseAfterUpload.setToolTipText(tr("Select to close the changeset after the next upload"));
    158140        add(cbCloseAfterUpload, gc);
     141
     142        cbOpenChangesets.addItemListener(this);
     143        cbOpenChangesets.addItemListener(closeChangesetAction);
     144
    159145        cbCloseAfterUpload.setSelected(Config.getPref().getBoolean("upload.changeset.close", true));
    160146        cbCloseAfterUpload.addItemListener(new CloseAfterUploadItemStateListener());
    161147
    162         rbUseNew.getModel().addItemListener(new RadioButtonHandler());
    163         rbExisting.getModel().addItemListener(new RadioButtonHandler());
     148        ChangesetCache.getInstance().addChangesetCacheListener(this);
    164149    }
    165150
    166     protected void refreshGUI() {
    167         rbExisting.setEnabled(model.getSize() > 0);
    168         if (model.getSize() == 0 && !rbUseNew.isSelected()) {
    169             rbUseNew.setSelected(true);
    170         }
    171         cbOpenChangesets.setEnabled(model.getSize() > 0 && rbExisting.isSelected());
    172     }
    173 
    174151    /**
    175152     * Sets the changeset to be used in the next upload
     153     * <p>
     154     * Note: The changeset may be a new changeset that was automatically opened because the old
     155     * changeset overflowed.  In that case it was already added to the changeset cache and the
     156     * combobox.
    176157     *
    177158     * @param cs the changeset
     159     * @see UploadPrimitivesTask#handleChangesetFullResponse
    178160     */
    179161    public void setSelectedChangesetForNextUpload(Changeset cs) {
    180         int idx = model.getIndexOf(cs);
    181         if (idx >= 0) {
    182             rbExisting.setSelected(true);
    183             model.setSelectedItem(cs);
    184         }
     162        model.setSelectedItem(cs);
    185163    }
    186164
    187165    /**
    188      * Replies the currently selected changeset. null, if no changeset is
    189      * selected or if the user has chosen to use a new changeset.
     166     * Returns the currently selected changeset or an empty new one.
    190167     *
    191      * @return the currently selected changeset. null, if no changeset is
    192      * selected.
     168     * @return the currently selected changeset
    193169     */
    194170    public Changeset getSelectedChangeset() {
    195         if (rbUseNew.isSelected())
    196             return null;
    197         return (Changeset) cbOpenChangesets.getSelectedItem();
     171        return Optional.ofNullable((Changeset) model.getSelectedItem()).orElse(new Changeset());
    198172    }
    199173
    200174    /**
     
    205179        return cbCloseAfterUpload.isSelected();
    206180    }
    207181
    208     /* ---------------------------------------------------------------------------- */
    209     /* Interface ListDataListener                                                   */
    210     /* ---------------------------------------------------------------------------- */
    211     @Override
    212     public void contentsChanged(ListDataEvent e) {
    213         refreshGUI();
    214     }
    215 
    216     @Override
    217     public void intervalAdded(ListDataEvent e) {
    218         refreshGUI();
    219     }
    220 
    221     @Override
    222     public void intervalRemoved(ListDataEvent e) {
    223         refreshGUI();
    224     }
    225 
    226182    /**
    227183     * Listens to changes in the selected changeset and fires property change events.
    228184     */
    229     class ChangesetListItemStateListener implements ItemListener {
    230         @Override
    231         public void itemStateChanged(ItemEvent e) {
    232             Changeset cs = (Changeset) cbOpenChangesets.getSelectedItem();
    233             if (cs == null) return;
    234             if (rbExisting.isSelected()) {
    235                 firePropertyChange(SELECTED_CHANGESET_PROP, null, cs);
    236             }
    237         }
     185    @Override
     186    public void itemStateChanged(ItemEvent e) {
     187        firePropertyChange(SELECTED_CHANGESET_PROP, null, model.getSelectedItem());
    238188    }
    239189
    240190    /**
     
    260210    }
    261211
    262212    /**
    263      * Listens to changes in the two radio buttons rbUseNew and rbUseExisting.
    264      */
    265     class RadioButtonHandler implements ItemListener {
    266         @Override
    267         public void itemStateChanged(ItemEvent e) {
    268             if (rbUseNew.isSelected()) {
    269                 cbOpenChangesets.setEnabled(false);
    270                 firePropertyChange(SELECTED_CHANGESET_PROP, null, null);
    271             } else if (rbExisting.isSelected()) {
    272                 cbOpenChangesets.setEnabled(true);
    273                 if (cbOpenChangesets.getSelectedItem() == null) {
    274                     model.selectFirstChangeset();
    275                 }
    276                 Changeset cs = (Changeset) cbOpenChangesets.getSelectedItem();
    277                 if (cs == null) return;
    278                 uploadDialogModel.putAll(cs.getKeys());
    279                 firePropertyChange(SELECTED_CHANGESET_PROP, null, cs);
    280             }
    281         }
    282     }
    283 
    284     /**
    285213     * Refreshes the list of open changesets
    286214     */
    287215    class RefreshAction extends AbstractAction {
     
    314242        }
    315243
    316244        protected void refreshEnabledState() {
    317             setEnabled(
    318                     cbOpenChangesets.getModel().getSize() > 0
    319                     && cbOpenChangesets.getSelectedItem() != null
    320                     && rbExisting.isSelected()
    321             );
     245            setEnabled(!getSelectedChangeset().isNew());
    322246        }
    323247
    324248        @Override
     
    326250            refreshEnabledState();
    327251        }
    328252    }
     253
     254    /**
     255     * Refreshes the changesets combobox form the server.
     256     * <p>
     257     * Note: This calls into {@link #refreshCombo} through {@link #changesetCacheUpdated}
     258     *
     259     * @see ChangesetCache#refreshChangesetsFromServer
     260     */
     261    protected void refreshChangesets() {
     262        try {
     263            ChangesetCache.getInstance().refreshChangesetsFromServer();
     264        } catch (OsmTransferException e) {
     265            return;
     266        }
     267    }
     268
     269    private void refreshCombo() {
     270        Changeset selected = (Changeset) cbOpenChangesets.getSelectedItem();
     271        model.removeAllElements();
     272        model.addElement(new Changeset());
     273        model.addAllElements(ChangesetCache.getInstance().getOpenChangesetsForCurrentUser());
     274        cbOpenChangesets.setSelectedItem(selected != null && model.getIndexOf(selected) != -1 ? selected : model.getElementAt(0));
     275    }
     276
     277    @Override
     278    public void changesetCacheUpdated(ChangesetCacheEvent event) {
     279        // This listener might have been called by a background task.
     280        SwingUtilities.invokeLater(() -> refreshCombo());
     281    }
    329282}
  • src/org/openstreetmap/josm/gui/io/OpenChangesetComboBoxModel.java

     
    1 // License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.io;
    3 
    4 import java.util.ArrayList;
    5 import java.util.List;
    6 
    7 import org.openstreetmap.josm.data.osm.Changeset;
    8 import org.openstreetmap.josm.data.osm.ChangesetCache;
    9 import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
    10 import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
    11 import org.openstreetmap.josm.gui.util.GuiHelper;
    12 import org.openstreetmap.josm.gui.widgets.JosmComboBoxModel;
    13 import org.openstreetmap.josm.tools.Utils;
    14 
    15 /**
    16  * A combobox model for the list of open changesets. The model is populated with the list
    17  * of open changesets kept in the {@link ChangesetCache}.
    18  *
    19  */
    20 public class OpenChangesetComboBoxModel extends JosmComboBoxModel<Changeset> implements ChangesetCacheListener {
    21     private final transient List<Changeset> changesets;
    22     private transient Changeset selectedChangeset;
    23 
    24     protected Changeset getChangesetById(long id) {
    25         return changesets.stream().filter(cs -> cs.getId() == id)
    26                 .findFirst().orElse(null);
    27     }
    28 
    29     /**
    30      * Constructs a new {@code OpenChangesetComboBoxModel}.
    31      */
    32     public OpenChangesetComboBoxModel() {
    33         this.changesets = new ArrayList<>();
    34     }
    35 
    36     /**
    37      * Refreshes the content of the combobox model with the current list of open
    38      * changesets from the {@link ChangesetCache}.
    39      */
    40     public void refresh() {
    41         changesets.clear();
    42         changesets.addAll(ChangesetCache.getInstance().getOpenChangesetsForCurrentUser());
    43         fireContentsChanged(this, 0, getSize());
    44         int idx = changesets.indexOf(selectedChangeset);
    45         if (idx < 0) {
    46             selectFirstChangeset();
    47         } else {
    48             setSelectedItem(changesets.get(idx));
    49         }
    50     }
    51 
    52     /**
    53      * Selects the first changeset in the current list of open changesets
    54      */
    55     public void selectFirstChangeset() {
    56         if (Utils.isEmpty(changesets)) {
    57             setSelectedItem(null);
    58         } else {
    59             setSelectedItem(changesets.get(0));
    60         }
    61     }
    62 
    63     /* ------------------------------------------------------------------------------------ */
    64     /* ChangesetCacheListener                                                               */
    65     /* ------------------------------------------------------------------------------------ */
    66     @Override
    67     public void changesetCacheUpdated(ChangesetCacheEvent event) {
    68         GuiHelper.runInEDT(this::refresh);
    69     }
    70 
    71     /* ------------------------------------------------------------------------------------ */
    72     /* ComboBoxModel                                                                        */
    73     /* ------------------------------------------------------------------------------------ */
    74     @Override
    75     public Changeset getElementAt(int index) {
    76         return changesets.get(index);
    77     }
    78 
    79     @Override
    80     public int getIndexOf(Changeset anObject) {
    81         return changesets.indexOf(anObject);
    82     }
    83 
    84     @Override
    85     public int getSize() {
    86         return changesets.size();
    87     }
    88 
    89     @Override
    90     public Object getSelectedItem() {
    91         return selectedChangeset;
    92     }
    93 
    94     @Override
    95     public void setSelectedItem(Object anObject) {
    96         if (anObject == null) {
    97             this.selectedChangeset = null;
    98             super.setSelectedItem(null);
    99             return;
    100         }
    101         if (!(anObject instanceof Changeset)) return;
    102         Changeset cs = (Changeset) anObject;
    103         if (cs.getId() == 0 || !cs.isOpen()) return;
    104         Changeset candidate = getChangesetById(cs.getId());
    105         if (candidate == null) return;
    106         this.selectedChangeset = candidate;
    107         super.setSelectedItem(selectedChangeset);
    108     }
    109 }
  • src/org/openstreetmap/josm/gui/io/UploadDialog.java

    Property changes on: src/org/openstreetmap/josm/gui/io/OpenChangesetComboBoxModel.java
    ___________________________________________________________________
    Deleted: svn:eol-style
    ## -1 +0,0 ##
    -native
    \ No newline at end of property
     
    99import java.awt.Component;
    1010import java.awt.Dimension;
    1111import java.awt.FlowLayout;
     12import java.awt.GridBagConstraints;
    1213import java.awt.GridBagLayout;
    1314import java.awt.event.ActionEvent;
    1415import java.awt.event.WindowAdapter;
     
    2324import java.util.Locale;
    2425import java.util.Map;
    2526import java.util.Map.Entry;
    26 import java.util.Optional;
    2727import java.util.stream.Collectors;
    2828
    2929import javax.swing.AbstractAction;
     
    3333import javax.swing.JPanel;
    3434import javax.swing.JSplitPane;
    3535import javax.swing.JTabbedPane;
    36 import javax.swing.border.TitledBorder;
    3736
    3837import org.openstreetmap.josm.data.APIDataSet;
    3938import org.openstreetmap.josm.data.osm.Changeset;
     
    5756import org.openstreetmap.josm.tools.GBC;
    5857import org.openstreetmap.josm.tools.ImageProvider;
    5958import org.openstreetmap.josm.tools.InputMapUtils;
    60 import org.openstreetmap.josm.tools.Logging;
    6159import org.openstreetmap.josm.tools.Utils;
    6260
    6361/**
     
    6563 * the upload changeset and the strategy for opening/closing a changeset.
    6664 * @since 2025
    6765 */
    68 public class UploadDialog extends AbstractUploadDialog implements PropertyChangeListener, PreferenceChangedListener {
     66public class UploadDialog extends AbstractUploadDialog implements PreferenceChangedListener, PropertyChangeListener {
    6967    /** the unique instance of the upload dialog */
    7068    private static UploadDialog uploadDialog;
    7169
    7270    /** the panel with the objects to upload */
    7371    private UploadedObjectsSummaryPanel pnlUploadedObjects;
    74     /** the panel to select the changeset used */
    75     private ChangesetManagementPanel pnlChangesetManagement;
    7672
     73    /** the "description" tab */
    7774    private BasicUploadSettingsPanel pnlBasicUploadSettings;
    7875
     76    /** the panel to select the changeset used */
     77    private ChangesetManagementPanel pnlChangesetManagement;
     78    /** the panel to select the upload strategy */
    7979    private UploadStrategySelectionPanel pnlUploadStrategySelectionPanel;
    8080
    81     private TitledBorder tagSettingsBorder;
    82     /** a border around the tag editor panel */
    83     private JPanel pnlTagEditorBorder;
    8481    /** the tag editor panel */
    8582    private TagEditorPanel pnlTagEditor;
    8683    /** the tabbed pane used below of the list of primitives  */
     
    9693    /**
    9794     * Constructs a new {@code UploadDialog}.
    9895     */
    99     public UploadDialog() {
     96    protected UploadDialog() {
    10097        super(GuiHelper.getFrameForComponent(MainApplication.getMainFrame()), ModalityType.DOCUMENT_MODAL);
    10198        build();
    10299        pack();
     
    138135        tpConfigPanels.setToolTipTextAt(0, tr("Describe the changes you made"));
    139136
    140137        JPanel pnlSettings = new JPanel(new GridBagLayout());
    141         pnlTagEditorBorder = new JPanel(new BorderLayout());
    142         tagSettingsBorder = BorderFactory.createTitledBorder(tr("Tags of new changeset"));
    143         pnlTagEditorBorder.setBorder(tagSettingsBorder);
     138        pnlSettings.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
     139        JPanel pnlTagEditorBorder = new JPanel(new BorderLayout());
     140        pnlTagEditorBorder.setBorder(BorderFactory.createTitledBorder(tr("Changeset tags:")));
    144141        pnlTagEditor = new TagEditorPanel(model, null, Changeset.MAX_CHANGESET_TAG_LENGTH);
    145142        pnlTagEditorBorder.add(pnlTagEditor, BorderLayout.CENTER);
    146143
    147         pnlChangesetManagement = new ChangesetManagementPanel(model);
     144        pnlChangesetManagement = new ChangesetManagementPanel();
    148145        pnlUploadStrategySelectionPanel = new UploadStrategySelectionPanel();
    149         pnlSettings.add(pnlChangesetManagement, GBC.eop().fill(GBC.HORIZONTAL));
    150         pnlSettings.add(pnlUploadStrategySelectionPanel, GBC.eop().fill(GBC.HORIZONTAL));
    151         pnlSettings.add(pnlTagEditorBorder, GBC.eol().fill(GBC.BOTH));
     146        pnlSettings.add(pnlChangesetManagement, GBC.eop().fill(GridBagConstraints.HORIZONTAL));
     147        pnlSettings.add(pnlUploadStrategySelectionPanel, GBC.eop().fill(GridBagConstraints.HORIZONTAL));
     148        pnlSettings.add(pnlTagEditorBorder, GBC.eol().fill(GridBagConstraints.BOTH));
    152149
    153150        tpConfigPanels.add(pnlSettings);
    154151        tpConfigPanels.setTitleAt(1, tr("Settings"));
     
    196193
    197194        addWindowListener(new WindowEventHandler());
    198195
    199         // make sure the configuration panels listen to each other changes
     196        // make sure the configuration panels listen to each others changes
    200197        //
     198        UploadParameterSummaryPanel sp = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
     199        // the summary panel must know everything
     200        pnlChangesetManagement.addPropertyChangeListener(sp);
     201        pnlUploadedObjects.addPropertyChangeListener(sp);
     202        pnlUploadStrategySelectionPanel.addPropertyChangeListener(sp);
     203
     204        // update tags from selected changeset
    201205        pnlChangesetManagement.addPropertyChangeListener(this);
    202         pnlChangesetManagement.addPropertyChangeListener(
    203                 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
    204         );
    205         pnlUploadedObjects.addPropertyChangeListener(pnlUploadStrategySelectionPanel);
    206         pnlUploadedObjects.addPropertyChangeListener(
    207                 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
    208         );
    209         pnlUploadStrategySelectionPanel.addPropertyChangeListener(this);
    210         pnlUploadStrategySelectionPanel.addPropertyChangeListener(
    211                 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
    212         );
    213206
    214207        // users can click on either of two links in the upload parameter
    215208        // summary handler. This installs the handler for these two events.
     
    241234        Map<String, String> map = new HashMap<>();
    242235        this.dataSet = dataSet;
    243236        pnlBasicUploadSettings.initLifeCycle(map);
     237        pnlChangesetManagement.initLifeCycle();
    244238        model.clear();
    245         model.putAll(map);
    246         model.putAll(this.dataSet);
     239        model.putAll(map);          // init with tags from history
     240        model.putAll(this.dataSet); // overwrite with tags from the dataset
     241
     242        tpConfigPanels.setSelectedIndex(0);
     243        pnlTagEditor.initAutoCompletion(MainApplication.getLayerManager().getEditLayer());
     244        pnlUploadStrategySelectionPanel.initFromPreferences();
     245
     246        // update the summary
     247        UploadParameterSummaryPanel sumPnl = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
     248        sumPnl.setUploadStrategySpecification(pnlUploadStrategySelectionPanel.getUploadStrategySpecification());
     249        sumPnl.setCloseChangesetAfterNextUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
    247250    }
    248251
    249252    /**
     
    254257     *
    255258     */
    256259    public void setUploadedPrimitives(APIDataSet toUpload) {
     260        UploadParameterSummaryPanel sumPnl = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
    257261        if (toUpload == null) {
    258262            if (pnlUploadedObjects != null) {
    259263                List<OsmPrimitive> emptyList = Collections.emptyList();
    260264                pnlUploadedObjects.setUploadedPrimitives(emptyList, emptyList, emptyList);
     265                sumPnl.setNumObjects(0);
    261266            }
    262267            return;
    263268        }
    264         pnlBasicUploadSettings.setUploadedPrimitives(toUpload.getPrimitives());
     269        List<OsmPrimitive> l = toUpload.getPrimitives();
     270        pnlBasicUploadSettings.setUploadedPrimitives(l);
    265271        pnlUploadedObjects.setUploadedPrimitives(
    266272                toUpload.getPrimitivesToAdd(),
    267273                toUpload.getPrimitivesToUpdate(),
    268274                toUpload.getPrimitivesToDelete()
    269275        );
     276        sumPnl.setNumObjects(l.size());
     277        pnlUploadStrategySelectionPanel.setNumUploadedObjects(l.size());
    270278    }
    271279
    272280    /**
     
    284292    }
    285293
    286294    /**
    287      * Initializes the panel for user input
    288      */
    289     public void startUserInput() {
    290         tpConfigPanels.setSelectedIndex(0);
    291         pnlBasicUploadSettings.startUserInput();
    292         pnlTagEditor.initAutoCompletion(MainApplication.getLayerManager().getEditLayer());
    293         pnlUploadStrategySelectionPanel.initFromPreferences();
    294         UploadParameterSummaryPanel pnl = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
    295         pnl.setUploadStrategySpecification(pnlUploadStrategySelectionPanel.getUploadStrategySpecification());
    296         pnl.setCloseChangesetAfterNextUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
    297         pnl.setNumObjects(pnlUploadedObjects.getNumObjectsToUpload());
    298     }
    299 
    300     /**
    301      * Replies the current changeset
     295     * Returns the changeset to use complete with tags
    302296     *
    303      * @return the current changeset
     297     * @return the changeset to use
    304298     */
    305299    public Changeset getChangeset() {
    306         Changeset cs = Optional.ofNullable(pnlChangesetManagement.getSelectedChangeset()).orElseGet(Changeset::new);
    307         cs.setKeys(model.getTags(false));
     300        Changeset cs = pnlChangesetManagement.getSelectedChangeset();
     301        cs.setKeys(getTags(true));
    308302        return cs;
    309303    }
    310304
     
    336330
    337331    @Override
    338332    public String getUploadComment() {
    339         return model.getValue("comment");
     333        return model.getValue(UploadDialogModel.COMMENT);
    340334    }
    341335
    342336    @Override
    343337    public String getUploadSource() {
    344         return model.getValue("source");
     338        return model.getValue(UploadDialogModel.SOURCE);
    345339    }
    346340
    347341    @Override
     
    354348                            new Dimension(800, 600)
    355349                    )
    356350            ).applySafe(this);
    357             startUserInput();
    358351        } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
    359352            new WindowGeometry(this).remember(getClass().getName() + ".geometry");
    360353        }
     
    436429        @Override
    437430        public void actionPerformed(ActionEvent e) {
    438431            Map<String, String> tags = dialog.getTags(true);
    439             Logging.info("Starting upload with tags {0}", tags);
    440432
    441             /* test for empty tags in the changeset metadata and proceed only after user's confirmation.
    442              * though, accept if key and value are empty (cf. xor). */
     433            // If there are empty tags in the changeset proceed only after user's confirmation.
    443434            List<String> emptyChangesetTags = new ArrayList<>();
    444435            for (final Entry<String, String> i : tags.entrySet()) {
    445436                final boolean isKeyEmpty = Utils.isStripEmpty(i.getKey());
    446437                final boolean isValueEmpty = Utils.isStripEmpty(i.getValue());
    447                 final boolean ignoreKey = "comment".equals(i.getKey()) || "source".equals(i.getKey());
    448                 if ((isKeyEmpty ^ isValueEmpty) && !ignoreKey) {
     438                final boolean ignoreKey = UploadDialogModel.COMMENT.equals(i.getKey()) || UploadDialogModel.SOURCE.equals(i.getKey());
     439                if ((isKeyEmpty || isValueEmpty) && !ignoreKey) {
    449440                    emptyChangesetTags.add(tr("{0}={1}", i.getKey(), i.getValue()));
    450441                }
    451442            }
     
    527518    @Override
    528519    public void propertyChange(PropertyChangeEvent evt) {
    529520        if (evt.getPropertyName().equals(ChangesetManagementPanel.SELECTED_CHANGESET_PROP)) {
     521            // put the tags from the newly selected changeset into the model
    530522            Changeset cs = (Changeset) evt.getNewValue();
    531             if (cs == null) {
    532                 tagSettingsBorder.setTitle(tr("Tags of new changeset"));
    533             } else {
    534                 tagSettingsBorder.setTitle(tr("Tags of changeset {0}", cs.getId()));
     523            if (cs != null) {
     524                for (Map.Entry<String, String> entry : cs.getKeys().entrySet()) {
     525                    String key = entry.getKey();
     526                    // do NOT overwrite comment and source when selecting a changeset, it is
     527                    // confusing
     528                    if (!UploadDialogModel.COMMENT.equals(key) && !UploadDialogModel.SOURCE.equals(key))
     529                        model.put(key, entry.getValue());
     530                }
    535531            }
    536532        }
    537533    }
  • src/org/openstreetmap/josm/gui/io/UploadDialogModel.java

     
    2323public class UploadDialogModel extends TagEditorModel {
    2424    /** the "created_by" changeset OSM key */
    2525    private static final String CREATED_BY = "created_by";
     26    /** the "comment" changeset OSM key */
     27    public static final String COMMENT = "comment";
     28    /** the "source" changeset OSM key */
     29    public static final String SOURCE = "source";
    2630    /** the user-agent */
    2731    private final String agent = Version.getInstance().getAgentString(false);
    2832    /** whether to extract hashtags from comment */
     
    3842                locked = true;
    3943                // add "hashtags" if any
    4044                if (hashtags) {
    41                     put("hashtags", findHashTags(getValue("comment")));
     45                    put("hashtags", findHashTags(getValue(COMMENT)));
    4246                }
    4347                // add/update "created_by"
    4448                final String createdBy = getValue(CREATED_BY);
     
    7175     * @return the hashtags separated by ";" or null
    7276     */
    7377    String findHashTags(String comment) {
    74         String hashtags = String.join(";",
     78        String hashTags = String.join(";",
    7579            Arrays.stream(comment.split("\\s", -1))
    7680                .map(s -> Utils.strip(s, ",;"))
    7781                .filter(s -> s.matches("#[a-zA-Z0-9][-_a-zA-Z0-9]+"))
    7882                .collect(Collectors.toList()));
    79         return hashtags.isEmpty() ? null : hashtags;
     83        return hashTags.isEmpty() ? null : hashTags;
    8084    }
    8185
    8286    /**
     
    115119        List<TagModel> l = tags.stream().filter(tm -> tm.getName().equals(key)).collect(Collectors.toList());
    116120        if (!l.isEmpty()) {
    117121            if (value != null)
    118                 l.get(0).setValue(value);
     122                for (TagModel tm : l) {
     123                    tm.setValue(value);
     124                }
    119125            else
    120                 tags.remove(l.get(0));
     126                tags.removeIf(tm -> tm.getName().equals(key));
    121127        } else if (value != null) {
    122128            tags.add(new TagModel(key, value));
    123129        }
     
    162168    public void putAll(DataSet dataSet) {
    163169        if (dataSet != null) {
    164170            putAll(dataSet.getChangeSetTags());
    165             put("comment", addHashTagsFromDataSet(getValue("comment"), dataSet));
     171            put(COMMENT, addHashTagsFromDataSet(getValue(COMMENT), dataSet));
    166172        }
    167173    }
    168174}
  • src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java

     
    5353        if (selectedChangeset == null || selectedChangeset.isNew()) {
    5454            return tr("Objects are uploaded to a <strong>new changeset</strong>.");
    5555        } else {
    56             return tr("Objects are uploaded to the <strong>open changeset</strong> {0} with upload comment ''{1}''.",
     56            return tr("Objects are uploaded to the <strong>open changeset</strong> {0} ''{1}''.",
    5757                    selectedChangeset.getId(),
    5858                    selectedChangeset.getComment()
    5959            );
     
    199199        } else if (evt.getPropertyName().equals(ChangesetManagementPanel.CLOSE_CHANGESET_AFTER_UPLOAD)) {
    200200            closeChangesetAfterNextUpload = (Boolean) evt.getNewValue();
    201201            updateSummary();
    202         } else if (evt.getPropertyName().equals(UploadedObjectsSummaryPanel.NUM_OBJECTS_TO_UPLOAD_PROP)) {
    203             numObjects = (Integer) evt.getNewValue();
    204             updateSummary();
    205202        } else if (evt.getPropertyName().equals(UploadStrategySelectionPanel.UPLOAD_STRATEGY_SPECIFICATION_PROP)) {
    206203            this.spec = (UploadStrategySpecification) evt.getNewValue();
    207204            updateSummary();
  • src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java

     
    8282        this.processedPrimitives = new HashSet<>();
    8383    }
    8484
    85     protected MaxChangesetSizeExceededPolicy askMaxChangesetSizeExceedsPolicy() {
     85    /**
     86     * Prompt the user about how to proceed.
     87     *
     88     * @return the policy selected by the user
     89     */
     90    protected MaxChangesetSizeExceededPolicy promptUserForPolicy() {
    8691        ButtonSpec[] specs = {
    8792                new ButtonSpec(
    8893                        tr("Continue uploading"),
     
    145150    }
    146151
    147152    /**
    148      * Opens a new changeset.
     153     * Handles a server changeset full response.
     154     * <p>
     155     * Handles a server changeset full response by either aborting or opening a new changeset, if the
     156     * user requested it so.
     157     *
     158     * @return true if the upload process should continue with the new changeset, false if the
     159     *         upload should be interrupted
     160     * @throws OsmTransferException "if something goes wrong."
    149161     */
    150     protected void openNewChangeset() {
    151         // make sure the current changeset is removed from the upload dialog.
    152         ChangesetCache.getInstance().update(changeset);
    153         Changeset newChangeSet = new Changeset();
    154         newChangeSet.setKeys(this.changeset.getKeys());
    155         this.changeset = newChangeSet;
    156     }
    157 
    158     protected boolean recoverFromChangesetFullException() throws OsmTransferException {
    159         if (toUpload.getSize() - processedPrimitives.size() == 0) {
     162    protected boolean handleChangesetFullResponse() throws OsmTransferException {
     163        if (processedPrimitives.size() == toUpload.getSize()) {
    160164            strategy.setPolicy(MaxChangesetSizeExceededPolicy.ABORT);
    161165            return false;
    162166        }
    163167        if (strategy.getPolicy() == null || strategy.getPolicy() == MaxChangesetSizeExceededPolicy.ABORT) {
    164             strategy.setPolicy(askMaxChangesetSizeExceedsPolicy());
     168            strategy.setPolicy(promptUserForPolicy());
    165169        }
    166170        switch(strategy.getPolicy()) {
    167171        case AUTOMATICALLY_OPEN_NEW_CHANGESETS:
    168             // prepare the state of the task for a next iteration in uploading.
    169             closeChangesetIfRequired();
    170             openNewChangeset();
     172            Changeset newChangeSet = new Changeset();
     173            newChangeSet.setKeys(changeset.getKeys());
     174            closeChangeset();
     175            this.changeset = newChangeSet;
    171176            toUpload.removeProcessed(processedPrimitives);
    172177            return true;
    173178        case ABORT:
     
    259264                        writer = new OsmServerWriter();
    260265                    }
    261266                    writer.uploadOsm(strategy, toUpload.getPrimitives(), changeset, getProgressMonitor().createSubTaskMonitor(1, false));
    262 
     267                    // If the changeset was new, now it is open.
     268                    ChangesetCache.getInstance().update(changeset);
    263269                    // if we get here we've successfully uploaded the data. Exit the loop.
    264270                    break;
    265271                } catch (OsmTransferCanceledException e) {
     
    276282                    switch(e.getSource()) {
    277283                    case UPLOAD_DATA:
    278284                        // Most likely the changeset is full. Try to recover and continue
    279                         // with a new changeset, but let the user decide first (see
    280                         // recoverFromChangesetFullException)
    281                         if (recoverFromChangesetFullException()) {
     285                        // with a new changeset, but let the user decide first.
     286                        if (handleChangesetFullResponse()) {
    282287                            continue;
    283288                        }
    284289                        lastException = e;
    285290                        break uploadloop;
     291                    case UPDATE_CHANGESET:
     292                    case CLOSE_CHANGESET:
    286293                    case UNSPECIFIED:
    287                     case UPDATE_CHANGESET:
    288294                    default:
    289295                        // The changeset was closed when we tried to update it. Probably, our
    290296                        // local list of open changesets got out of sync with the server state.
     
    291297                        // The user will have to select another open changeset.
    292298                        // Rethrow exception - this will be handled later.
    293299                        changeset.setOpen(false);
     300                        ChangesetCache.getInstance().update(changeset);
    294301                        throw e;
    295302                    }
    296303                } finally {
     
    319326        cleanupAfterUpload();
    320327    }
    321328
     329    /**
     330     * Closes the changeset on the server and locally.
     331     *
     332     * @throws OsmTransferException "if something goes wrong."
     333     */
     334    private void closeChangeset() throws OsmTransferException {
     335        if (changeset != null && !changeset.isNew() && changeset.isOpen()) {
     336            // CHECKSTYLE.OFF: EmptyBlock
     337            try {
     338                OsmApi.getOsmApi().closeChangeset(changeset, progressMonitor.createSubTaskMonitor(0, false));
     339            } catch (ChangesetClosedException e) {
     340                // Do not raise a stink, probably the changeset timed out.
     341            } finally {
     342                changeset.setOpen(false);
     343                ChangesetCache.getInstance().update(changeset);
     344            }
     345            // CHECKSTYLE.ON: EmptyBlock
     346        }
     347    }
     348
    322349    private void closeChangesetIfRequired() throws OsmTransferException {
    323         if (strategy.isCloseChangesetAfterUpload() && changeset != null && !changeset.isNew() && changeset.isOpen()) {
    324             OsmApi.getOsmApi().closeChangeset(changeset, progressMonitor.createSubTaskMonitor(0, false));
     350        if (strategy.isCloseChangesetAfterUpload()) {
     351            closeChangeset();
    325352        }
    326353    }
    327354
    328     @Override protected void finish() {
    329 
    330         // depending on the success of the upload operation and on the policy for
    331         // multi changeset uploads this will sent the user back to the appropriate
    332         // place in JOSM, either
    333         // - to an error dialog
    334         // - to the Upload Dialog
    335         // - to map editing
     355    /**
     356     * Depending on the success of the upload operation and on the policy for
     357     * multi changeset uploads this will send the user back to the appropriate
     358     * place in JOSM, either:
     359     * <ul>
     360     * <li>to an error dialog,
     361     * <li>to the Upload Dialog, or
     362     * <li>to map editing.
     363     * </ul>
     364     */
     365    @Override
     366    protected void finish() {
    336367        GuiHelper.runInEDT(() -> {
    337368            // if the changeset is still open after this upload we want it to be selected on the next upload
    338369            ChangesetCache.getInstance().update(changeset);
  • src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java

     
    1010import java.awt.Insets;
    1111import java.awt.event.ActionEvent;
    1212import java.awt.event.ActionListener;
    13 import java.awt.event.FocusAdapter;
    1413import java.awt.event.FocusEvent;
     14import java.awt.event.FocusListener;
    1515import java.awt.event.ItemEvent;
    1616import java.awt.event.ItemListener;
    17 import java.beans.PropertyChangeEvent;
    18 import java.beans.PropertyChangeListener;
    1917import java.util.EnumMap;
    2018import java.util.Map;
    2119import java.util.Map.Entry;
     
    4442 * Clients can listen for property change events for the property
    4543 * {@link #UPLOAD_STRATEGY_SPECIFICATION_PROP}.
    4644 */
    47 public class UploadStrategySelectionPanel extends JPanel implements PropertyChangeListener {
     45public class UploadStrategySelectionPanel extends JPanel {
    4846
    4947    /**
    5048     * The property for the upload strategy
     
    5654    private transient Map<UploadStrategy, JLabel> lblNumRequests;
    5755    private final JosmTextField tfChunkSize = new JosmTextField(4);
    5856    private final JPanel pnlMultiChangesetPolicyPanel = new JPanel(new GridBagLayout());
    59     private final JRadioButton rbFillOneChangeset = new JRadioButton(
    60             tr("Fill up one changeset and return to the Upload Dialog"));
    61     private final JRadioButton rbUseMultipleChangesets = new JRadioButton(
    62             tr("Open and use as many new changesets as necessary"));
     57    private final JRadioButton rbFillOneChangeset = new JRadioButton();
     58    private final JRadioButton rbUseMultipleChangesets = new JRadioButton();
    6359    private JMultilineLabel lblMultiChangesetPoliciesHeader;
    6460
    6561    private long numUploadedObjects;
     
    7369
    7470    protected JPanel buildUploadStrategyPanel() {
    7571        JPanel pnl = new JPanel(new GridBagLayout());
    76         pnl.setBorder(BorderFactory.createTitledBorder(tr("Please select the upload strategy:")));
     72        pnl.setBorder(BorderFactory.createTitledBorder(tr("Please select an upload strategy:")));
    7773        ButtonGroup bgStrategies = new ButtonGroup();
    7874        rbStrategy = new EnumMap<>(UploadStrategy.class);
    7975        lblNumRequests = new EnumMap<>(UploadStrategy.class);
     
    9187        gc.weighty = 0.0;
    9288        gc.gridwidth = 1;
    9389        gc.fill = GridBagConstraints.HORIZONTAL;
    94         gc.insets = new Insets(0, 0, 3, 0);
     90        gc.insets = new Insets(3, 3, 3, 3);
    9591        gc.anchor = GridBagConstraints.FIRST_LINE_START;
    9692        JRadioButton radioButton = rbStrategy.get(UploadStrategy.SINGLE_REQUEST_STRATEGY);
    97         radioButton.setText(tr("Upload data in one request"));
     93        radioButton.setText(tr("Upload all objects in one request"));
    9894        pnl.add(radioButton, gc);
    99         gc.gridx = 3;
    100         gc.gridy = 1;
     95        gc.gridx = 2;
    10196        gc.weightx = 1.0;
    102         gc.weighty = 0.0;
    103         gc.gridwidth = 1;
    10497        pnl.add(lblNumRequests.get(UploadStrategy.SINGLE_REQUEST_STRATEGY), gc);
    10598
    10699        // -- chunked dataset strategy
     100        gc.gridy++;
    107101        gc.gridx = 0;
    108         gc.gridy = 2;
    109102        gc.weightx = 0.0;
    110         gc.weighty = 0.0;
    111103        radioButton = rbStrategy.get(UploadStrategy.CHUNKED_DATASET_STRATEGY);
    112         radioButton.setText(tr("Upload data in chunks of objects. Chunk size: "));
     104        radioButton.setText(tr("Upload objects in chunks of size: "));
    113105        pnl.add(radioButton, gc);
     106        gc.gridx = 1;
     107        pnl.add(tfChunkSize, gc);
    114108        gc.gridx = 2;
    115         gc.gridy = 2;
    116         gc.weightx = 0.0;
    117         gc.weighty = 0.0;
    118         gc.gridwidth = 1;
    119         pnl.add(tfChunkSize, gc);
    120         gc.gridx = 3;
    121         gc.gridy = 2;
    122         gc.weightx = 0.0;
    123         gc.weighty = 0.0;
    124         gc.gridwidth = 1;
    125109        pnl.add(lblNumRequests.get(UploadStrategy.CHUNKED_DATASET_STRATEGY), gc);
    126110
    127111        // -- single request strategy
     112        gc.gridy++;
    128113        gc.gridx = 0;
    129         gc.gridy = 3;
    130         gc.weightx = 0.0;
    131         gc.weighty = 0.0;
    132114        radioButton = rbStrategy.get(UploadStrategy.INDIVIDUAL_OBJECTS_STRATEGY);
    133115        radioButton.setText(tr("Upload each object individually"));
    134116        pnl.add(radioButton, gc);
    135         gc.gridx = 3;
    136         gc.gridy = 3;
    137         gc.weightx = 0.0;
    138         gc.weighty = 0.0;
    139         gc.gridwidth = 1;
     117        gc.gridx = 2;
    140118        pnl.add(lblNumRequests.get(UploadStrategy.INDIVIDUAL_OBJECTS_STRATEGY), gc);
    141119
    142         tfChunkSize.addFocusListener(new TextFieldFocusHandler());
    143120        new ChunkSizeValidator(tfChunkSize);
    144121
    145122        StrategyChangeListener strategyChangeListener = new StrategyChangeListener();
     
    158135        gc.gridy = 0;
    159136        gc.fill = GridBagConstraints.HORIZONTAL;
    160137        gc.anchor = GridBagConstraints.FIRST_LINE_START;
     138        gc.insets = new Insets(3, 3, 3, 3);
    161139        gc.weightx = 1.0;
    162140        lblMultiChangesetPoliciesHeader = new JMultilineLabel(
    163                 tr("<html>There are <strong>multiple changesets</strong> necessary in order to upload {0} objects. " +
    164                    "Which strategy do you want to use?</html>",
     141                tr("<html><strong>Multiple changesets</strong> are necessary to upload {0} objects. " +
     142                   "Please select a strategy:</html>",
    165143                        numUploadedObjects));
    166144        pnlMultiChangesetPolicyPanel.add(lblMultiChangesetPoliciesHeader, gc);
    167         gc.gridy = 1;
     145        gc.gridy++;
     146        rbFillOneChangeset.setText(tr("Fill up one changeset and return to the Upload Dialog"));
    168147        pnlMultiChangesetPolicyPanel.add(rbFillOneChangeset, gc);
    169         gc.gridy = 2;
     148        gc.gridy++;
     149        rbUseMultipleChangesets.setText(tr("Open and use as many new changesets as necessary"));
    170150        pnlMultiChangesetPolicyPanel.add(rbUseMultipleChangesets, gc);
    171151
    172152        ButtonGroup bgMultiChangesetPolicies = new ButtonGroup();
     
    184164        gc.weightx = 1.0;
    185165        gc.weighty = 0.0;
    186166        gc.anchor = GridBagConstraints.NORTHWEST;
    187         gc.insets = new Insets(3, 3, 3, 3);
    188167
    189168        add(buildUploadStrategyPanel(), gc);
    190169        gc.gridy = 1;
    191170        add(buildMultiChangesetPolicyPanel(), gc);
    192171
    193         // consume remaining space
    194         gc.gridy = 2;
    195         gc.fill = GridBagConstraints.BOTH;
    196         gc.weightx = 1.0;
    197         gc.weighty = 1.0;
    198         add(new JPanel(), gc);
    199 
    200172        Capabilities capabilities = OsmApi.getOsmApi().getCapabilities();
    201173        int maxChunkSize = capabilities != null ? capabilities.getMaxChangesetSize() : -1;
    202174        pnlMultiChangesetPolicyPanel.setVisible(
     
    312284        if (maxChunkSize > 0 && numUploadedObjects > maxChunkSize) {
    313285            rbStrategy.get(UploadStrategy.SINGLE_REQUEST_STRATEGY).setEnabled(false);
    314286            JRadioButton lbl = rbStrategy.get(UploadStrategy.SINGLE_REQUEST_STRATEGY);
    315             lbl.setText(tr("Upload in one request not possible (too many objects to upload)"));
     287            lbl.setEnabled(false);
    316288            lbl.setToolTipText(tr("<html>Cannot upload {0} objects in one request because the<br>"
    317289                    + "max. changeset size {1} on server ''{2}'' is exceeded.</html>",
    318290                    numUploadedObjects, maxChunkSize, OsmApi.getOsmApi().getBaseUrl()
     
    333305        } else {
    334306            rbStrategy.get(UploadStrategy.SINGLE_REQUEST_STRATEGY).setEnabled(true);
    335307            JRadioButton lbl = rbStrategy.get(UploadStrategy.SINGLE_REQUEST_STRATEGY);
    336             lbl.setText(tr("Upload data in one request"));
     308            lbl.setEnabled(true);
    337309            lbl.setToolTipText(null);
    338310            lblNumRequests.get(UploadStrategy.SINGLE_REQUEST_STRATEGY).setVisible(true);
    339311
     
    368340        tfChunkSize.requestFocusInWindow();
    369341    }
    370342
    371     @Override
    372     public void propertyChange(PropertyChangeEvent evt) {
    373         if (evt.getPropertyName().equals(UploadedObjectsSummaryPanel.NUM_OBJECTS_TO_UPLOAD_PROP)) {
    374             setNumUploadedObjects((Integer) evt.getNewValue());
    375         }
    376     }
    377 
    378     static class TextFieldFocusHandler extends FocusAdapter {
    379         @Override
    380         public void focusGained(FocusEvent e) {
    381             Component c = e.getComponent();
    382             if (c instanceof JosmTextField) {
    383                 JosmTextField tf = (JosmTextField) c;
    384                 tf.selectAll();
    385             }
    386         }
    387     }
    388 
    389343    class ChunkSizeValidator extends AbstractTextComponentValidator {
    390344        ChunkSizeValidator(JTextComponent tc) {
    391345            super(tc);
     
    423377        }
    424378    }
    425379
    426     class StrategyChangeListener extends FocusAdapter implements ItemListener, ActionListener {
     380    class StrategyChangeListener implements FocusListener, ItemListener, ActionListener {
    427381
    428382        protected void notifyStrategy() {
    429383            firePropertyChange(UPLOAD_STRATEGY_SPECIFICATION_PROP, null, getUploadStrategySpecification());
     
    446400        }
    447401
    448402        @Override
     403        public void focusGained(FocusEvent e) {
     404            Component c = e.getComponent();
     405            if (c instanceof JosmTextField) {
     406                JosmTextField tf = (JosmTextField) c;
     407                tf.selectAll();
     408            }
     409        }
     410
     411        @Override
    449412        public void focusLost(FocusEvent e) {
    450413            notifyStrategy();
    451414        }
  • src/org/openstreetmap/josm/gui/io/UploadedObjectsSummaryPanel.java

     
    2828 * @since 2599
    2929 */
    3030public class UploadedObjectsSummaryPanel extends JPanel {
    31     /**
    32      * The swing property name for the number of objects to upload
    33      */
    34     public static final String NUM_OBJECTS_TO_UPLOAD_PROP = UploadedObjectsSummaryPanel.class.getName() + ".numObjectsToUpload";
    35 
    3631    /** the list with the added primitives */
    3732    private PrimitiveList lstAdd;
    3833    private JLabel lblAdd;
     
    145140            gcList.gridy = y;
    146141            add(spDelete, gcList);
    147142        }
    148 
    149         firePropertyChange(NUM_OBJECTS_TO_UPLOAD_PROP, 0, getNumObjectsToUpload());
     143        revalidate();
    150144    }
    151145
    152146    /**
  • src/org/openstreetmap/josm/gui/tagging/TagEditorModel.java

     
    3030import org.openstreetmap.josm.data.osm.Tagged;
    3131import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType;
    3232import org.openstreetmap.josm.tools.CheckParameterUtil;
     33import org.openstreetmap.josm.tools.Utils;
    3334
    3435/**
    3536 * TagEditorModel is a table model to use with {@link TagEditorPanel}.
     
    5354
    5455    private transient OsmPrimitive primitive;
    5556
    56     private EndEditListener endEditListener;
     57    private transient EndEditListener endEditListener;
    5758
    5859    /**
    5960     * Creates a new tag editor model. Internally allocates two selection models
     
    278279     * @param tagIndices a list of tag indices
    279280     */
    280281    public void deleteTagNames(int... tagIndices) {
    281         if (tags == null)
    282             return;
    283282        commitPendingEdit();
    284283        for (int tagIdx : tagIndices) {
    285284            TagModel tag = tags.get(tagIdx);
     
    297296     * @param tagIndices the lit of tag indices
    298297     */
    299298    public void deleteTagValues(int... tagIndices) {
    300         if (tags == null)
    301             return;
    302299        commitPendingEdit();
    303300        for (int tagIdx : tagIndices) {
    304301            TagModel tag = tags.get(tagIdx);
     
    332329     * @param tagIndices the list of tag indices
    333330     */
    334331    public void deleteTags(int... tagIndices) {
    335         if (tags == null)
    336             return;
    337332        commitPendingEdit();
    338333        List<TagModel> toDelete = Arrays.stream(tagIndices).mapToObj(tags::get).filter(Objects::nonNull).collect(Collectors.toList());
    339334        toDelete.forEach(tags::remove);
     
    441436            if (tag.getValueCount() > 1) {
    442437                continue;
    443438            }
     439            boolean isKeyEmpty = Utils.isStripEmpty(tag.getName());
     440            boolean isValueEmpty = Utils.isStripEmpty(tag.getValue());
    444441
     442            // just the empty line at the bottom of the JTable
     443            if (isKeyEmpty && isValueEmpty) {
     444                continue;
     445            }
     446
    445447            // tag name holds an empty key. Don't apply it to the selection.
    446             if (!keepEmpty && (tag.getName().trim().isEmpty() || tag.getValue().trim().isEmpty())) {
     448            if (!keepEmpty && (isKeyEmpty || isValueEmpty)) {
    447449                continue;
    448450            }
    449             result.put(tag.getName().trim(), tag.getValue().trim());
     451            result.put(Utils.strip(tag.getName()), Utils.strip(tag.getValue()));
    450452        }
    451453        return result;
    452454    }
     
    496498
    497499        // tag name holds an empty key. Don't apply it to the selection.
    498500        //
    499         if (tag.getName().trim().isEmpty())
     501        if (Utils.isStripEmpty(tag.getName()))
    500502            return null;
    501503
    502504        return new ChangePropertyCommand(primitives, tag.getName(), tag.getValue());
     
    528530     */
    529531    public List<String> getKeys() {
    530532        return tags.stream()
    531                 .filter(tag -> !tag.getName().trim().isEmpty())
     533                .filter(tag -> !Utils.isStripEmpty(tag.getName()))
    532534                .map(TagModel::getName)
    533535                .collect(Collectors.toList());
    534536    }
  • src/org/openstreetmap/josm/gui/tagging/TagTable.java

     
    3535import org.openstreetmap.josm.gui.widgets.JosmTable;
    3636import org.openstreetmap.josm.tools.ImageProvider;
    3737import org.openstreetmap.josm.tools.Logging;
     38import org.openstreetmap.josm.tools.Utils;
    3839
    3940/**
    4041 * This is the tabular editor component for OSM tags.
     
    8889            } else if (col == 1 && row == getRowCount()-1) {
    8990                // we are at the end. Append an empty row and move the focus to its second column
    9091                String key = ((TagModel) model.getValueAt(row, 0)).getName();
    91                 if (!key.trim().isEmpty()) {
     92                if (!Utils.isStripEmpty(key)) {
    9293                    model.appendNewTag();
    9394                    col = 0;
    9495                    row++;
     
    242243                cEditor.stopCellEditing();
    243244            }
    244245            final int rowIdx = model.getRowCount()-1;
    245             if (rowIdx < 0 || !((TagModel) model.getValueAt(rowIdx, 0)).getName().trim().isEmpty()) {
     246            if (rowIdx < 0 || !Utils.isStripEmpty(((TagModel) model.getValueAt(rowIdx, 0)).getName())) {
    246247                model.appendNewTag();
    247248            }
    248249            requestFocusInCell(model.getRowCount()-1, 0);
  • src/org/openstreetmap/josm/gui/widgets/JosmComboBoxModel.java

     
    5454     * {@link javax.swing.DefaultComboBoxModel}.
    5555     *
    5656     * @param element the element to get the index of
    57      * @return an int representing the index position, where 0 is the first position
     57     * @return the index of the first occurrence of the specified element in this model,
     58     *         or -1 if this model does not contain the element
    5859     */
    5960    public int getIndexOf(E element) {
    6061        return elements.indexOf(element);
    6162    }
    6263
     64    protected void doAddElement(E element) {
     65        if (element != null && (maxSize == -1 || getSize() < maxSize)) {
     66            elements.add(element);
     67        }
     68    }
     69
    6370    //
    6471    // interface java.lang.Iterable
    6572    //
     
    7885     */
    7986    @Override
    8087    public void addElement(E element) {
    81         if (element != null && (maxSize == -1 || getSize() < maxSize)) {
    82             elements.add(element);
    83         }
     88        doAddElement(element);
     89        fireIntervalAdded(this, elements.size() - 1, elements.size() - 1);
    8490    }
    8591
    8692    @Override
    8793    public void removeElement(Object elem) {
    88         elements.remove(elem);
     94        int index = elements.indexOf(elem);
     95        if (elem == selected) {
     96            if (index == 0) {
     97                setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1));
     98            } else {
     99                setSelectedItem(getElementAt(index - 1));
     100            }
     101        }
     102        if (elements.remove(elem))
     103            fireIntervalRemoved(this, index, index);
    89104    }
    90105
    91106    @Override
     
    114129            removeElementAt(getSize() - 1);
    115130        }
    116131        elements.add(index, element);
     132        fireIntervalAdded(this, index, index);
    117133    }
    118134
    119135    //
     
    166182     * @param elems The elements to add.
    167183     */
    168184    public void addAllElements(Collection<E> elems) {
    169         elems.forEach(e -> addElement(e));
     185        int index0 = elements.size();
     186        elems.forEach(e -> doAddElement(e));
     187        int index1 = elements.size() - 1;
     188        if (index0 <= index1)
     189            fireIntervalAdded(this, index0, index1);
    170190    }
    171191
    172192    /**
     
    177197     *               {@code String}.
    178198     */
    179199    public void addAllElements(Collection<String> strings, Function<String, E> buildE) {
    180         strings.forEach(s -> addElement(buildE.apply(s)));
     200        int index0 = elements.size();
     201        strings.forEach(s -> doAddElement(buildE.apply(s)));
     202        int index1 = elements.size() - 1;
     203        if (index0 <= index1)
     204            fireIntervalAdded(this, index0, index1);
    181205    }
    182206
    183207    /**
     
    204228     */
    205229    public void removeAllElements() {
    206230        if (!elements.isEmpty()) {
    207             int firstIndex = 0;
    208231            int lastIndex = elements.size() - 1;
    209232            elements.clear();
    210233            selected = null;
    211             fireIntervalRemoved(this, firstIndex, lastIndex);
     234            fireIntervalRemoved(this, 0, lastIndex);
    212235        } else {
    213236            selected = null;
    214237        }
  • src/org/openstreetmap/josm/io/ChangesetClosedException.java

    Property changes on: src/org/openstreetmap/josm/gui/widgets/JosmComboBoxModel.java
    ___________________________________________________________________
    Deleted: svn:eol-style
    ## -1 +0,0 ##
    -native
    \ No newline at end of property
     
    4343         */
    4444        UPLOAD_DATA,
    4545        /**
     46         * The exception was thrown when we tried to close a changeset.  Probably the changeset
     47         * already timed out on the server.
     48         */
     49        CLOSE_CHANGESET,
     50        /**
    4651         * Unspecified source
    4752         */
    4853        UNSPECIFIED
  • src/org/openstreetmap/josm/io/OsmApi.java

     
    387387                    ((OsmPrimitive) osm).getDataSet().lock();
    388388                }
    389389            }
     390        } catch (ChangesetClosedException e) {
     391            e.setSource(ChangesetClosedException.Source.UPDATE_CHANGESET);
     392            throw e;
    390393        } catch (NumberFormatException e) {
    391394            throw new OsmTransferException(errHandler.apply(ret), e);
    392395        }
     
    528531            initialize(monitor);
    529532            // send "\r\n" instead of empty string, so we don't send zero payload - workaround bugs in proxy software
    530533            sendPutRequest("changeset/" + changeset.getId() + "/close", "\r\n", monitor);
     534        } catch (ChangesetClosedException e) {
     535            e.setSource(ChangesetClosedException.Source.CLOSE_CHANGESET);
     536            throw e;
     537        } finally {
    531538            changeset.setOpen(false);
    532         } finally {
    533539            monitor.finishTask();
    534540        }
    535541    }
     
    564570    public Collection<OsmPrimitive> uploadDiff(Collection<? extends OsmPrimitive> list, ProgressMonitor monitor)
    565571            throws OsmTransferException {
    566572        try {
     573            ensureValidChangeset();
    567574            monitor.beginTask("", list.size() * 2);
    568             if (changeset == null)
    569                 throw new OsmTransferException(tr("No changeset present for diff upload."));
    570575
    571576            initialize(monitor);
    572577
     
    593598                    getChangeset(),
    594599                    monitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)
    595600            );
    596         } catch (OsmTransferException e) {
     601        } catch (ChangesetClosedException e) {
     602            e.setSource(ChangesetClosedException.Source.UPLOAD_DATA);
    597603            throw e;
    598604        } catch (XmlParsingException e) {
    599605            throw new OsmTransferException(e);
     
    751757                    throw new OsmApiPrimitiveGoneException(errorHeader, errorBody);
    752758                case HttpURLConnection.HTTP_CONFLICT:
    753759                    if (ChangesetClosedException.errorHeaderMatchesPattern(errorHeader))
    754                         throw new ChangesetClosedException(errorBody, ChangesetClosedException.Source.UPLOAD_DATA);
     760                        throw new ChangesetClosedException(errorBody, ChangesetClosedException.Source.UNSPECIFIED);
    755761                    else
    756762                        throw new OsmApiException(retCode, errorHeader, errorBody);
    757763                case HttpURLConnection.HTTP_UNAUTHORIZED:
  • src/org/openstreetmap/josm/io/UploadStrategySpecification.java

     
    150150    }
    151151
    152152    @Override
     153    public String toString() {
     154        return String.format("Strategy: %s, ChunkSize: %d, Policy: %s, Close after: %b",
     155            strategy.toString(), chunkSize, policy == null ? "none" : policy.toString(), closeChangesetAfterUpload);
     156    }
     157
     158    @Override
    153159    public int hashCode() {
    154160        return Objects.hash(strategy, chunkSize, policy, closeChangesetAfterUpload);
    155161    }
  • test/unit/org/openstreetmap/josm/data/osm/ChangesetCacheTest.java

     
    1818import org.junit.jupiter.api.extension.RegisterExtension;
    1919import org.openstreetmap.josm.data.UserIdentityManager;
    2020import org.openstreetmap.josm.testutils.JOSMTestRules;
     21import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    2122import org.openstreetmap.josm.tools.Logging;
    2223
    2324import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    2526/**
    2627 * Unit test of {@link ChangesetCache}
    2728 */
     29@BasicPreferences
    2830class ChangesetCacheTest {
    2931
    3032    /**
  • test/unit/org/openstreetmap/josm/gui/io/ChangesetManagementPanelTest.java

     
    1717     */
    1818    @Test
    1919    void testChangesetManagementPanel() {
    20         assertNotNull(new ChangesetManagementPanel(new UploadDialogModel()));
     20        assertNotNull(new ChangesetManagementPanel());
    2121    }
    2222}