Ticket #12303: 12303.patch

File 12303.patch, 8.6 KB (added by GerdP, 4 months ago)
  • src/org/openstreetmap/josm/actions/downloadtasks/DownloadReferrersTask.java

     
    77import java.io.IOException;
    88import java.text.MessageFormat;
    99import java.util.Collection;
     10import java.util.LinkedHashMap;
    1011import java.util.LinkedHashSet;
     12import java.util.Map;
     13import java.util.Map.Entry;
    1114import java.util.Set;
    1215import java.util.stream.Collectors;
    1316
     
    1417import javax.swing.JOptionPane;
    1518import javax.swing.SwingUtilities;
    1619
     20import org.openstreetmap.josm.data.Bounds;
    1721import org.openstreetmap.josm.data.osm.DataSet;
    1822import org.openstreetmap.josm.data.osm.DataSetMerger;
    1923import org.openstreetmap.josm.data.osm.Node;
     
    3034import org.openstreetmap.josm.io.OsmServerBackreferenceReader;
    3135import org.openstreetmap.josm.io.OsmServerReader;
    3236import org.openstreetmap.josm.io.OsmTransferException;
     37import org.openstreetmap.josm.io.OverpassDownloadReader;
    3338import org.openstreetmap.josm.tools.CheckParameterUtil;
    3439import org.openstreetmap.josm.tools.ExceptionUtil;
     40import org.openstreetmap.josm.tools.Logging;
    3541import org.xml.sax.SAXException;
    3642
    3743/**
     
    150156    @Override
    151157    protected void realRun() throws SAXException, IOException, OsmTransferException {
    152158        try {
    153             progressMonitor.setTicksCount(children.size());
    154             int i = 1;
    155             for (PrimitiveId p : children) {
    156                 if (canceled)
    157                     return;
    158                 String msg;
    159                 String id = Long.toString(p.getUniqueId());
    160                 switch(p.getType()) {
    161                 case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break;
    162                 case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break;
    163                 case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break;
    164                 default: throw new AssertionError();
     159            if (Boolean.TRUE.equals(OverpassDownloadReader.FOR_MULTI_FETCH.get())) {
     160                String request = genOverpassQuery();
     161                OverpassDownloadReader reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0),
     162                        OverpassDownloadReader.OVERPASS_SERVER.get(), request);
     163                DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
     164                new DataSetMerger(parents, ds).merge();
     165            } else {
     166                progressMonitor.setTicksCount(children.size());
     167                int i = 1;
     168                for (PrimitiveId p : children) {
     169                    if (canceled)
     170                        return;
     171                    String msg;
     172                    String id = Long.toString(p.getUniqueId());
     173                    switch(p.getType()) {
     174                    case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break;
     175                    case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break;
     176                    case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break;
     177                    default: throw new AssertionError();
     178                    }
     179                    progressMonitor.subTask(msg);
     180                    downloadParents(p.getUniqueId(), p.getType(), progressMonitor);
     181                    i++;
    165182                }
    166                 progressMonitor.subTask(msg);
    167                 downloadParents(p.getUniqueId(), p.getType(), progressMonitor);
    168                 i++;
    169             }
    170             Collection<Way> ways = parents.getWays();
     183                Collection<Way> ways = parents.getWays();
    171184
    172             if (!ways.isEmpty()) {
    173                 // Collect incomplete nodes of parent ways
    174                 Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete))
    175                         .collect(Collectors.toSet());
    176                 if (!nodes.isEmpty()) {
    177                     reader = MultiFetchServerObjectReader.create();
    178                     ((MultiFetchServerObjectReader) reader).append(nodes);
    179                     DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
    180                     synchronized (this) { // avoid race condition in cancel()
    181                         reader = null;
     185                if (!ways.isEmpty()) {
     186                    // Collect incomplete nodes of parent ways
     187                    Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete))
     188                            .collect(Collectors.toSet());
     189                    if (!nodes.isEmpty()) {
     190                        reader = MultiFetchServerObjectReader.create();
     191                        ((MultiFetchServerObjectReader) reader).append(nodes);
     192                        DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
     193                        synchronized (this) { // avoid race condition in cancel()
     194                            reader = null;
     195                        }
     196                        new DataSetMerger(parents, wayNodes).merge();
    182197                    }
    183                     new DataSetMerger(parents, wayNodes).merge();
    184198                }
    185199            }
    186200        } catch (OsmTransferException e) {
     
    189203            lastException = e;
    190204        }
    191205    }
     206
     207    private String genOverpassQuery() {
     208        Map<OsmPrimitiveType, Set<Long>> primitivesMap = new LinkedHashMap<>();
     209        primitivesMap.put(OsmPrimitiveType.NODE, new LinkedHashSet<>());
     210        primitivesMap.put(OsmPrimitiveType.WAY, new LinkedHashSet<>());
     211        primitivesMap.put(OsmPrimitiveType.RELATION, new LinkedHashSet<>());
     212        for (PrimitiveId p : children) {
     213            primitivesMap.get(p.getType()).add(p.getUniqueId());
     214        }
     215        boolean getWays = false;
     216        StringBuilder sb = new StringBuilder();
     217        StringBuilder sets = new StringBuilder();
     218        for (Entry<OsmPrimitiveType, Set<Long>> e : primitivesMap.entrySet()) {
     219            if (!e.getValue().isEmpty()) {
     220                String list = getPackageString(e.getKey(), e.getValue());
     221                switch (e.getKey()) {
     222                case NODE:
     223                    sb.append('(').append(list).append("->.n;.n;rel(bn);.n;way(bn);)->.pn;");
     224                    sets.append(".pn;");
     225                    getWays = true;
     226                    break;
     227                case CLOSEDWAY:
     228                case WAY:
     229                    sb.append(list).append(";rel(bw)->.pw;");
     230                    sets.append(".pw;");
     231                    break;
     232                case MULTIPOLYGON:
     233                case RELATION:
     234                    sb.append(list).append(";rel(br)->.pr;");
     235                    sets.append(".pr;");
     236                    break;
     237                }
     238            }
     239        }
     240        // retrieve all incomplete nodes for union of parents
     241        if (getWays)
     242            sb.append("((").append(sets).append(");node(w);node(r););");
     243        else
     244            sb.append("((").append(sets).append(");node(r););");
     245        sb.append("out meta;");
     246        String query = sb.toString();
     247        Logging.debug("{0} {1}", "Generated Overpass query:", query);
     248        return query;
     249
     250    }
     251
     252    private static String getPackageString(final OsmPrimitiveType type, Set<Long> idPackage) {
     253        return idPackage.stream().map(String::valueOf)
     254                .collect(Collectors.joining(",", type.getAPIName() + (idPackage.size() == 1 ? "(" : "(id:"), ")"));
     255    }
     256
    192257}
  • src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java

     
    434434                if (isCanceled())
    435435                    return null;
    436436                OverpassDownloadReader reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0), getBaseUrl(), request);
    437                 DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(n, false));
     437                DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
    438438                new DataSetMerger(outputDataSet, ds).merge();
    439439                checkMissing(outputDataSet, progressMonitor);
    440440            } else {