Ticket #6251: multiDownload.patch

File multiDownload.patch, 18.0 KB (added by akks, 10 years ago)
  • src/org/openstreetmap/josm/actions/DownloadPrimitiveAction.java

     
    88import java.awt.GridBagLayout;
    99import java.awt.event.ActionEvent;
    1010import java.awt.event.KeyEvent;
     11import java.util.List;
     12import javax.swing.ComboBoxModel;
    1113
    1214import javax.swing.JCheckBox;
    1315import javax.swing.JLabel;
     
    1921import org.openstreetmap.josm.actions.downloadtasks.DownloadPrimitiveTask;
    2022import org.openstreetmap.josm.actions.downloadtasks.DownloadReferrersTask;
    2123import org.openstreetmap.josm.data.osm.DataSet;
     24import org.openstreetmap.josm.data.osm.Node;
    2225import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    2326import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
    2427import org.openstreetmap.josm.gui.ExtendedDialog;
     28import org.openstreetmap.josm.gui.io.DownloadPrimitivesTask;
    2529import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     30import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    2631import org.openstreetmap.josm.gui.widgets.OsmIdTextField;
    2732import org.openstreetmap.josm.gui.widgets.OsmPrimitiveTypesComboBox;
     33import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
    2834import org.openstreetmap.josm.tools.Shortcut;
    2935
    3036/**
     
    5157        GridBagConstraints gc = new GridBagConstraints();
    5258        gc.fill = GridBagConstraints.HORIZONTAL;
    5359        gc.anchor = GridBagConstraints.FIRST_LINE_START;
    54         gc.gridy = 0;
    55         gc.weightx = 0;
    56         all.add(new JLabel(tr("Object type:")), gc);
     60        gc.gridy = 0;   gc.gridwidth=0;   gc.weightx = 0;
     61        all.add(new HtmlPanel(tr("Please choose defalt primitive type and enter primitives numbers<br/>"
     62                + " Examples: <b><ul><li>1 2 5</li><li>1, 2, 5</li><li>123,v2 123,v1</li></ul><br/></b>"
     63                + " It is also possible to specify primitive types in the list: <b>w123, n110, w12, r15</b><br/>"
     64                + " v-words are ignored for copy-paste from openstreetmap.org<br/><br/>")), gc);
     65        gc.gridwidth=1;  gc.weightx = 0;  gc.gridy = 1; gc.gridx = 0;
     66        all.add(new JLabel(tr("Object type:")),gc);
    5767        OsmPrimitiveTypesComboBox cbType = new OsmPrimitiveTypesComboBox();
     68        cbType.addItem(new SimpleListItem("auto", tr("Auto")));
    5869        cbType.setToolTipText(tr("Choose the OSM object type"));
    59         gc.weightx = 1;
     70        gc.weightx = 1; gc.gridx = 1;
    6071        all.add(cbType, gc);
    61         gc.gridy = 1;
    62         gc.weightx = 0;
     72        gc.gridy = 2; gc.gridx = 0;   gc.weightx = 0;
    6373        all.add(new JLabel(tr("Object ID:")), gc);
    6474        OsmIdTextField tfId = new OsmIdTextField();
    6575        tfId.setToolTipText(tr("Enter the ID of the object that should be downloaded"));
    6676        // forward the enter key stroke to the download button
    6777        tfId.getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false));
    68         gc.weightx = 1;
     78        gc.gridx = 1;    gc.weightx = 1;
    6979        all.add(tfId, gc);
    70         gc.gridy = 2;
     80        gc.gridy = 3;    gc.gridx = 0;
    7181        gc.fill = GridBagConstraints.BOTH;
    72         gc.weighty = 1.0;
    73         gc.weightx = 0;
     82        gc.weighty = 1.0;  gc.weightx = 0;
    7483        all.add(referrers, gc);
    75         gc.gridy = 3;
     84        gc.gridy = 4;
    7685        all.add(layer, gc);
    7786        ExtendedDialog dialog = new ExtendedDialog(Main.parent,
    7887                tr("Download object"),
     
    92101        Main.pref.putInteger("downloadprimitive.lasttype", cbType.getSelectedIndex());
    93102        Main.pref.put("downloadprimitive.referrers", referrers.isSelected());
    94103        Main.pref.put("download.newlayer", layer.isSelected());
    95         int id = tfId.getOsmId();
    96         if(id <= 0)
     104
     105        tfId.setType(cbType.getType());
     106        if(tfId.readOsmIds()==false) {
    97107            JOptionPane.showMessageDialog(
    98108                    Main.parent,
    99                     tr("Invalid ID specified. Cannot download object."),
     109                    tr("Invalid ID list specified\n"
     110                    + " Cannot download object."),
    100111                    tr("Information"),
    101112                    JOptionPane.INFORMATION_MESSAGE
    102113            );
    103         else
    104             download(layer.isSelected(), cbType.getType(), id, referrers.isSelected());
     114            return;
     115        }
     116
     117        processItems(layer.isSelected(), cbType.getType(),tfId.getNodeIds(),
     118             tfId.getWayIds(), tfId.getRelIds(), referrers.isSelected());
    105119    }
    106 
    107     /**
    108      * Download the given primitive.
    109      */
    110     public void download(boolean newLayer, OsmPrimitiveType type, int id, boolean downloadReferrers) {
     120   
     121    void processItems(boolean newLayer, OsmPrimitiveType type,
     122            List<Long> nodeIds,List<Long> wayIds,List<Long> relIds,
     123            boolean downloadReferrers) {
     124        System.out.println(nodeIds);
     125        System.out.println(wayIds);
     126        System.out.println(relIds);
    111127        OsmDataLayer layer = getEditLayer();
    112         if ((layer == null) || newLayer) {
    113             layer = new OsmDataLayer(new DataSet(), OsmDataLayer.createNewName(), null);
    114             Main.main.addLayer(layer);
    115         }
    116         Main.worker.submit(new DownloadPrimitiveTask(new SimplePrimitiveId(id, type), layer));
    117         if (downloadReferrers) {
    118             Main.worker.submit(new DownloadReferrersTask(layer, id, type));
    119         }
     128            if ((layer == null) || newLayer) {
     129                layer = new OsmDataLayer(new DataSet(), OsmDataLayer.createNewName(), null);
     130                Main.main.addLayer(layer);
     131            }     
     132       Main.worker.submit(new DownloadPrimitivesTask(layer, nodeIds, wayIds, relIds,downloadReferrers));
    120133    }
     134
     135    private void processMixedItems(boolean selected, OsmPrimitiveType osmPrimitiveType, int[] type, boolean osmIds) {
     136        throw new UnsupportedOperationException("Not yet implemented");
     137    }
     138   
     139    private static class SimpleListItem  {
     140     final String data;
     141     final String text;
     142     public SimpleListItem(String data, String text) {  this.data = data;   this.text = text; }
     143     @Override public String toString() { return text; }
     144   }
    121145}
  • src/org/openstreetmap/josm/gui/widgets/OsmIdTextField.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.widgets;
    33
     4import java.util.ArrayList;
     5import java.util.Arrays;
     6import java.util.List;
     7import java.util.StringTokenizer;
    48import static org.openstreetmap.josm.tools.I18n.tr;
    59
    610import javax.swing.JTextField;
    711import javax.swing.text.JTextComponent;
     12import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    813
    914/**
    1015 * @author Matthias Julius
     
    1722        validator = OsmIdValidator.decorate(this);
    1823    }
    1924
    20     public int getOsmId() {
     25    public void setType(OsmPrimitiveType type) {
     26        validator.type = type;
     27    }
     28
     29    public long getOsmId() {
    2130        return validator.getOsmId();
    2231    }
    2332
    2433    /**
     34     * Get entered ID list - supports "1,2,3" "1 2   ,3" or even "1 2 3 v2 6 v8"
     35     * @return array of id's
     36     */
     37    public List<Long> getNodeIds() {
     38        return validator.nodeIds;
     39    }
     40
     41    public List<Long> getWayIds() {
     42        return validator.wayIds;
     43    }
     44
     45    public List<Long> getRelIds() {
     46        return validator.relIds;
     47    }
     48
     49    public boolean readOsmIds() {
     50        return validator.readOsmIds();
     51    }
     52
     53
     54    /**
    2555     * Validator for a changeset ID entered in a {@see JTextComponent}.
    2656     *
    2757     */
     
    3161            return new OsmIdValidator(tc);
    3262        }
    3363
     64        private List<Long> nodeIds=new ArrayList<Long>();
     65        private List<Long> wayIds=new ArrayList<Long>();
     66        private List<Long> relIds=new ArrayList<Long>();
     67        private OsmPrimitiveType type;
     68
    3469        public OsmIdValidator(JTextComponent tc) {
    3570            super(tc, false);
    3671        }
    3772
    3873        @Override
    3974        public boolean isValid() {
    40             return getOsmId() > 0;
     75            return getOsmId() > 0 || readOsmIds()!=false;
    4176        }
    4277
    4378        @Override
     
    4984            }
    5085        }
    5186
    52         public int getOsmId() {
     87        public long getOsmId() {
    5388            String value  = getComponent().getText();
    5489            if (value == null || value.trim().length() == 0) return 0;
    5590            try {
    56                 int osmId = Integer.parseInt(value.trim());
     91                long osmId = Long.parseLong(value.trim());
    5792                if (osmId > 0) return osmId;
    5893                return 0;
    5994            } catch(NumberFormatException e) {
    6095                return 0;
    6196            }
    6297        }
     98        public boolean readOsmIds() {
     99            String value  = getComponent().getText();
     100            char c;
     101            if (value == null || value.trim().length() == 0) return false;
     102            try {
     103                nodeIds.clear(); wayIds.clear(); relIds.clear();
     104                //String[] parts = value.split("[,\\.\\s\\t\\n]+");
     105                StringTokenizer st = new StringTokenizer(value,",.+/ \t\n");
     106                String s;
     107                while (st.hasMoreTokens()) {
     108                    s = st.nextToken();
     109                    // convert tokens to int skipping v-words (version v2 etc)
     110                    c = s.charAt(0);
     111                    if (c=='v') continue;
     112                    if (c=='n') nodeIds.add(Long.parseLong(s.substring(1))); else
     113                    if (c=='w') wayIds.add(Long.parseLong(s.substring(1))); else
     114                    if (c=='r') relIds.add(Long.parseLong(s.substring(1))); else
     115                    if (type==OsmPrimitiveType.NODE) nodeIds.add(Long.parseLong(s)); else
     116                    if (type==OsmPrimitiveType.WAY) wayIds.add(Long.parseLong(s)); else
     117                    if (type==OsmPrimitiveType.RELATION) relIds.add(Long.parseLong(s));
     118                    }
     119                return true;
     120            } catch(NumberFormatException e) {
     121                return false;
     122            }
     123        }
    63124    }
    64125}
  • src/org/openstreetmap/josm/gui/widgets/OsmPrimitiveTypesComboBox.java

     
    1818    }
    1919
    2020    public OsmPrimitiveType getType() {
    21         return (OsmPrimitiveType)this.getSelectedItem();
     21        try {
     22            return (OsmPrimitiveType)this.getSelectedItem();
     23        } catch (Exception e) {
     24            return null;
     25        }
    2226    }
    2327}
  • src/org/openstreetmap/josm/gui/io/DownloadPrimitivesTask.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.io;
     3
     4import static org.openstreetmap.josm.tools.CheckParameterUtil.ensureParameterNotNull;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6
     7import java.io.IOException;
     8import java.lang.reflect.InvocationTargetException;
     9import java.util.Collection;
     10import java.util.Collections;
     11import java.util.List;
     12import java.util.logging.Logger;
     13
     14import javax.swing.SwingUtilities;
     15
     16import org.openstreetmap.josm.data.osm.DataSet;
     17import org.openstreetmap.josm.data.osm.DataSetMerger;
     18import org.openstreetmap.josm.data.osm.Node;
     19import org.openstreetmap.josm.data.osm.OsmPrimitive;
     20import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     21import org.openstreetmap.josm.data.osm.Relation;
     22import org.openstreetmap.josm.data.osm.Way;
     23import org.openstreetmap.josm.gui.ExceptionDialogUtil;
     24import org.openstreetmap.josm.gui.PleaseWaitRunnable;
     25import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     26import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     27import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
     28import org.openstreetmap.josm.io.OsmServerObjectReader;
     29import org.openstreetmap.josm.io.OsmTransferException;
     30import org.xml.sax.SAXException;
     31
     32/**
     33 * The asynchronous task for updating a collection of objects using multi fetch.
     34 *
     35 */
     36public class DownloadPrimitivesTask extends PleaseWaitRunnable {
     37    @SuppressWarnings("unused")
     38    static private final Logger logger = Logger.getLogger(UpdatePrimitivesTask.class.getName());
     39
     40    private DataSet ds;
     41    private boolean canceled;
     42    private Exception lastException;
     43    private List<Long> nodeIds;
     44    private List<Long> wayIds;
     45    private List<Long> relIds;
     46
     47    private OsmDataLayer layer;
     48    private MultiFetchServerObjectReader multiObjectReader;
     49    private OsmServerObjectReader objectReader;
     50    private final boolean downloadReferrers;
     51
     52    /**
     53     * Creates the  task
     54     *
     55     * @param layer the layer in which primitives are updated. Must not be null.
     56     * @param toUpdate a collection of primitives to update from the server. Set to
     57     * the empty collection if null.
     58     * @throws IllegalArgumentException thrown if layer is null.
     59     */
     60    public DownloadPrimitivesTask(OsmDataLayer layer, List<Long>  nodeIds,
     61            List<Long>  wayIds,List<Long>  relIds, boolean downloadReferrers) throws IllegalArgumentException{
     62        super(tr("Download objects"), false /* don't ignore exception */);
     63        ensureParameterNotNull(layer, "layer");
     64        this.nodeIds = nodeIds; this.wayIds = wayIds;  this.relIds = relIds;
     65        this.layer = layer;
     66        this.downloadReferrers = downloadReferrers;
     67    }
     68
     69    @Override
     70    protected void cancel() {
     71        canceled = true;
     72        synchronized(this) {
     73            if (multiObjectReader != null) {
     74                multiObjectReader.cancel();
     75            }
     76            if (objectReader != null) {
     77                objectReader.cancel();
     78            }
     79        }
     80    }
     81
     82    @Override
     83    protected void finish() {
     84        if (canceled)
     85            return;
     86        if (lastException != null) {
     87            ExceptionDialogUtil.explainException(lastException);
     88            return;
     89        }
     90        Runnable r = new Runnable() {
     91            public void run() {
     92                layer.mergeFrom(ds);
     93                layer.onPostDownloadFromServer();
     94            }
     95        };
     96
     97        if (SwingUtilities.isEventDispatchThread()) {
     98            r.run();
     99        } else {
     100            try {
     101                SwingUtilities.invokeAndWait(r);
     102            } catch(InterruptedException e) {
     103                e.printStackTrace();
     104            } catch(InvocationTargetException e) {
     105                e.printStackTrace();
     106            }
     107        }
     108    }
     109
     110    protected void initMultiFetchReaderWithNodes(MultiFetchServerObjectReader reader) {
     111        getProgressMonitor().indeterminateSubTask(tr("Initializing nodes to download ..."));
     112        for (Long id : nodeIds) {
     113            Node n=(Node) layer.data.getPrimitiveById(id, OsmPrimitiveType.NODE);
     114            if (n == null) n=new Node(id);
     115            reader.append(n);
     116        }
     117    }
     118
     119    protected void initMultiFetchReaderWithWays(MultiFetchServerObjectReader reader) {
     120        getProgressMonitor().indeterminateSubTask(tr("Initializing ways to download ..."));
     121        for (Long id : wayIds) {
     122            Way w=(Way) layer.data.getPrimitiveById(id, OsmPrimitiveType.WAY);
     123            if (w == null) w=new Way(id);
     124            reader.append(w);
     125        }
     126    }
     127
     128    protected void initMultiFetchReaderWithRelations(MultiFetchServerObjectReader reader) {
     129        getProgressMonitor().indeterminateSubTask(tr("Initializing relations to download ..."));
     130        for (Long id : relIds) {
     131            Relation r=(Relation) layer.data.getPrimitiveById(id, OsmPrimitiveType.RELATION);
     132            if (r == null) r=new Relation(id);
     133            reader.append(r);
     134        }
     135    }
     136
     137    @Override
     138    protected void realRun() throws SAXException, IOException, OsmTransferException {
     139        this.ds = new DataSet();
     140        DataSet theirDataSet;
     141        try {
     142            synchronized(this) {
     143                if (canceled) return;
     144                multiObjectReader = new MultiFetchServerObjectReader();
     145            }
     146            initMultiFetchReaderWithNodes(multiObjectReader);
     147            initMultiFetchReaderWithWays(multiObjectReader);
     148            initMultiFetchReaderWithRelations(multiObjectReader);
     149            theirDataSet = multiObjectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
     150            synchronized(this) {
     151                multiObjectReader = null;
     152            }
     153            DataSetMerger merger = new DataSetMerger(ds, theirDataSet);
     154            merger.merge();
     155            // a way loaded with MultiFetch may have incomplete nodes because at least one of its
     156            // nodes isn't present in the local data set. We therefore fully load all
     157            // ways with incomplete nodes.
     158            //
     159            for (Way w : ds.getWays()) {
     160                if (canceled) return;
     161                if (w.hasIncompleteNodes()) {
     162                    synchronized(this) {
     163                        if (canceled) return;
     164                        objectReader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
     165                    }
     166                    theirDataSet = objectReader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
     167                    synchronized (this) {
     168                        objectReader = null;
     169                    }
     170                    merger = new DataSetMerger(ds, theirDataSet);
     171                    merger.merge();
     172                }
     173            }
     174        } catch(Exception e) {
     175            if (canceled)
     176                return;
     177            lastException = e;
     178        }
     179    }
     180}