Ticket #12303: 12303.2.patch
| File 12303.2.patch, 14.7 KB (added by , 6 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/downloadtasks/DownloadReferrersTask.java
14 14 import javax.swing.JOptionPane; 15 15 import javax.swing.SwingUtilities; 16 16 17 import org.openstreetmap.josm.data.Bounds; 17 18 import org.openstreetmap.josm.data.osm.DataSet; 18 19 import org.openstreetmap.josm.data.osm.DataSetMerger; 19 20 import org.openstreetmap.josm.data.osm.Node; … … 26 27 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 27 28 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 28 29 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 30 import org.openstreetmap.josm.io.MultiFetchOverpassObjectReader; 29 31 import org.openstreetmap.josm.io.MultiFetchServerObjectReader; 30 32 import org.openstreetmap.josm.io.OsmServerBackreferenceReader; 31 33 import org.openstreetmap.josm.io.OsmServerReader; 32 34 import org.openstreetmap.josm.io.OsmTransferException; 35 import org.openstreetmap.josm.io.OverpassDownloadReader; 33 36 import org.openstreetmap.josm.tools.CheckParameterUtil; 34 37 import org.openstreetmap.josm.tools.ExceptionUtil; 35 38 import org.xml.sax.SAXException; … … 150 153 @Override 151 154 protected void realRun() throws SAXException, IOException, OsmTransferException { 152 155 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(); 156 if (Boolean.TRUE.equals(OverpassDownloadReader.FOR_MULTI_FETCH.get())) { 157 String request = MultiFetchOverpassObjectReader.genOverpassQuery(children, false, true, false); 158 reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0), 159 OverpassDownloadReader.OVERPASS_SERVER.get(), request); 160 DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 161 new DataSetMerger(parents, ds).merge(); 162 } else { 163 progressMonitor.setTicksCount(children.size()); 164 int i = 1; 165 for (PrimitiveId p : children) { 166 if (canceled) 167 return; 168 String msg; 169 String id = Long.toString(p.getUniqueId()); 170 switch(p.getType()) { 171 case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break; 172 case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break; 173 case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break; 174 default: throw new AssertionError(); 175 } 176 progressMonitor.subTask(msg); 177 downloadParents(p.getUniqueId(), p.getType(), progressMonitor); 178 i++; 165 179 } 166 progressMonitor.subTask(msg); 167 downloadParents(p.getUniqueId(), p.getType(), progressMonitor); 168 i++; 169 } 170 Collection<Way> ways = parents.getWays(); 180 Collection<Way> ways = parents.getWays(); 171 181 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; 182 if (!ways.isEmpty()) { 183 // Collect incomplete nodes of parent ways 184 Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete)) 185 .collect(Collectors.toSet()); 186 if (!nodes.isEmpty()) { 187 reader = MultiFetchServerObjectReader.create(); 188 ((MultiFetchServerObjectReader) reader).append(nodes); 189 DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 190 synchronized (this) { // avoid race condition in cancel() 191 reader = null; 192 } 193 new DataSetMerger(parents, wayNodes).merge(); 182 194 } 183 new DataSetMerger(parents, wayNodes).merge();184 195 } 185 196 } 186 197 } catch (OsmTransferException e) { … … 189 200 lastException = e; 190 201 } 191 202 } 203 192 204 } -
src/org/openstreetmap/josm/gui/io/DownloadPrimitivesWithReferrersTask.java
31 31 import org.openstreetmap.josm.gui.util.GuiHelper; 32 32 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 33 33 import org.openstreetmap.josm.gui.widgets.JosmTextArea; 34 import org.openstreetmap.josm.io.MultiFetchOverpassObjectReader; 34 35 import org.openstreetmap.josm.io.OsmTransferException; 35 36 import org.openstreetmap.josm.tools.GBC; 36 37 import org.xml.sax.SAXException; … … 101 102 102 103 @Override 103 104 protected void realRun() throws SAXException, IOException, OsmTransferException { 105 MultiFetchOverpassObjectReader.genOverpassQuery(ids, true, downloadReferrers, full); // TODO: remove 104 106 getProgressMonitor().setTicksCount(ids.size()+1); 105 107 // First, download primitives 106 108 mainTask = new DownloadPrimitivesTask(tmpLayer, ids, full, getProgressMonitor().createSubTaskMonitor(1, false)); -
src/org/openstreetmap/josm/io/MultiFetchOverpassObjectReader.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.io; 3 3 4 import java.util.Collection; 5 import java.util.Map; 4 6 import java.util.Map.Entry; 5 7 import java.util.Set; 8 import java.util.TreeMap; 9 import java.util.TreeSet; 6 10 import java.util.stream.Collectors; 7 11 8 12 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 13 import org.openstreetmap.josm.data.osm.PrimitiveId; 9 14 import org.openstreetmap.josm.tools.Logging; 10 15 11 16 /** … … 17 22 18 23 private static String getPackageString(final OsmPrimitiveType type, Set<Long> idPackage) { 19 24 return idPackage.stream().map(String::valueOf) 20 .collect(Collectors.joining(",", type.getAPIName() + (idPackage.size() == 1 ? "(" : "(id:"), ") ;"));25 .collect(Collectors.joining(",", type.getAPIName() + (idPackage.size() == 1 ? "(" : "(id:"), ")")); 21 26 } 22 27 23 28 /** … … 30 35 for (Entry<OsmPrimitiveType, Set<Long>> e : primitivesMap.entrySet()) { 31 36 if (!e.getValue().isEmpty()) { 32 37 countTypes++; 33 String list = getPackageString(e.getKey(), e.getValue()) ;38 String list = getPackageString(e.getKey(), e.getValue()) + ";"; 34 39 switch (e.getKey()) { 35 40 case MULTIPOLYGON: 36 41 case RELATION: … … 56 61 return query; 57 62 } 58 63 64 /** 65 * Generate single overpass query to retrieve multiple primitives. Can be used to download parents, 66 * children, the objects, or any combination of them. 67 * @param ids the collection of ids 68 * @param includeObjects if false, don't retrieve the primitives (e.g. only the referrers) 69 * @param recurseUp if true, referrers (parents) of the objects are downloaded and all nodes of these parents 70 * @param recurseDownRelations true: yes, recurse down to retrieve complete relations 71 * @return the overpass query 72 */ 73 public static String genOverpassQuery(Collection<PrimitiveId> ids, boolean includeObjects, boolean recurseUp, 74 boolean recurseDownRelations) { 75 Map<OsmPrimitiveType, Set<Long>> primitivesMap = new TreeMap<>(); 76 for (PrimitiveId p : ids) { 77 primitivesMap.computeIfAbsent(p.getType(), k -> new TreeSet<>()).add(p.getUniqueId()); 78 } 79 return genOverpassQuery(primitivesMap, includeObjects, recurseUp, recurseDownRelations); 80 } 81 82 /** 83 * Generate single overpass query to retrieve multiple primitives. Can be used to download parents, 84 * children, the objects, or any combination of them. 85 * @param primitivesMap map containing the primitives 86 * @param includeObjects if false, don't retrieve the primitives (e.g. only the referrers) 87 * @param recurseUp if true, referrers (parents) of the primitives are downloaded and all nodes of these parents 88 * @param recurseDownRelations true: yes, recurse down to retrieve complete relations 89 * @return the overpass query 90 */ 91 public static String genOverpassQuery(Map<OsmPrimitiveType, Set<Long>> primitivesMap, boolean includeObjects, 92 boolean recurseUp, boolean recurseDownRelations) { 93 boolean getWayNodes = false; 94 StringBuilder sb = new StringBuilder(); 95 StringBuilder setsToInclude = new StringBuilder("("); 96 for (Entry<OsmPrimitiveType, Set<Long>> e : primitivesMap.entrySet()) { 97 if (!e.getValue().isEmpty()) { 98 String list = getPackageString(e.getKey(), e.getValue()); 99 switch (e.getKey()) { 100 case NODE: 101 sb.append(list).append("->.n;"); 102 if (includeObjects) { 103 setsToInclude.append(".n;"); 104 } 105 if (recurseUp) { 106 sb.append(".n;way(bn)->.wn;.n;rel(bn)->.rn;"); 107 setsToInclude.append(".wn;.rn;"); 108 getWayNodes = true; 109 } 110 break; 111 case CLOSEDWAY: 112 case WAY: 113 sb.append(list).append("->.w;"); 114 if (includeObjects) { 115 setsToInclude.append(".w;"); 116 getWayNodes = true; 117 } 118 if (recurseUp) { 119 sb.append(".w;rel(bw)->.pw;"); 120 setsToInclude.append(".pw;"); 121 } 122 break; 123 case MULTIPOLYGON: 124 case RELATION: 125 sb.append(list).append("->.r;"); 126 if (includeObjects) { 127 setsToInclude.append(".r;"); 128 } 129 if (recurseUp) { 130 sb.append(".r;rel(br)->.pr;"); 131 setsToInclude.append(".pr;"); 132 } 133 if (recurseDownRelations) { 134 sb.append(".r;>>->.rm;"); 135 setsToInclude.append(".rm;"); 136 } 137 break; 138 } 139 } 140 } 141 setsToInclude.append(");"); 142 // retrieve all incomplete nodes for union of parents ? 143 if (getWayNodes) { 144 sb.append("(").append(setsToInclude).append("node(w););"); 145 } else { 146 sb.append(setsToInclude); 147 } 148 sb.append("out meta;"); 149 String query = sb.toString(); 150 Logging.debug("{0} {1}", "Possible Overpass query:", query); 151 return query; 152 } 153 59 154 @Override 60 155 protected String getBaseUrl() { 61 156 return OverpassDownloadReader.OVERPASS_SERVER.get(); -
src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java
12 12 import java.util.Collections; 13 13 import java.util.HashSet; 14 14 import java.util.Iterator; 15 import java.util.LinkedHashMap;16 15 import java.util.LinkedHashSet; 17 16 import java.util.List; 18 17 import java.util.Map; 19 18 import java.util.Map.Entry; 20 19 import java.util.Set; 20 import java.util.TreeMap; 21 21 import java.util.concurrent.Callable; 22 22 import java.util.concurrent.CompletionService; 23 23 import java.util.concurrent.ExecutionException; … … 89 89 relations = new LinkedHashSet<>(); 90 90 this.outputDataSet = new DataSet(); 91 91 this.missingPrimitives = new LinkedHashSet<>(); 92 primitivesMap = new LinkedHashMap<>();92 primitivesMap = new TreeMap<>(); 93 93 primitivesMap.put(OsmPrimitiveType.RELATION, relations); 94 94 primitivesMap.put(OsmPrimitiveType.WAY, ways); 95 95 primitivesMap.put(OsmPrimitiveType.NODE, nodes); … … 382 382 try { 383 383 if (this instanceof MultiFetchOverpassObjectReader) { 384 384 // calculate a single request for all the objects 385 String request = ((MultiFetchOverpassObjectReader) this).buildComplexRequestString();385 String request = MultiFetchOverpassObjectReader.genOverpassQuery(primitivesMap, true, false, recurseDownRelations); 386 386 if (isCanceled()) 387 387 return null; 388 388 OverpassDownloadReader reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0), getBaseUrl(), request); 389 DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor( n, false));389 DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 390 390 new DataSetMerger(outputDataSet, ds).merge(); 391 391 checkMissing(outputDataSet, progressMonitor); 392 392 } else {
