Ticket #12303: 12303.6.patch
File 12303.6.patch, 31.9 KB (added by , 4 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; … … 154 157 @Override 155 158 protected void realRun() throws SAXException, IOException, OsmTransferException { 156 159 try { 157 progressMonitor.setTicksCount(children.size()); 158 int i = 1; 159 for (PrimitiveId p : children) { 160 if (canceled) 161 return; 162 String msg; 163 String id = Long.toString(p.getUniqueId()); 164 switch(p.getType()) { 165 case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break; 166 case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break; 167 case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break; 168 default: throw new AssertionError(); 160 if (Boolean.TRUE.equals(OverpassDownloadReader.FOR_MULTI_FETCH.get())) { 161 String request = MultiFetchOverpassObjectReader.genOverpassQuery(children, false, true, false); 162 reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0), 163 OverpassDownloadReader.OVERPASS_SERVER.get(), request); 164 DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 165 new DataSetMerger(parents, ds).merge(); 166 } else { 167 progressMonitor.setTicksCount(children.size()); 168 int i = 1; 169 for (PrimitiveId p : children) { 170 if (canceled) 171 return; 172 String msg; 173 String id = Long.toString(p.getUniqueId()); 174 switch(p.getType()) { 175 case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break; 176 case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break; 177 case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break; 178 default: throw new AssertionError(); 179 } 180 progressMonitor.subTask(msg); 181 downloadParents(p.getUniqueId(), p.getType(), progressMonitor); 182 i++; 169 183 } 170 progressMonitor.subTask(msg); 171 downloadParents(p.getUniqueId(), p.getType(), progressMonitor); 172 i++; 173 } 174 Collection<Way> ways = parents.getWays(); 184 Collection<Way> ways = parents.getWays(); 175 185 176 if (!ways.isEmpty()) { 177 // Collect incomplete nodes of parent ways 178 Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete)) 179 .collect(Collectors.toSet()); 180 if (!nodes.isEmpty()) { 181 reader = MultiFetchServerObjectReader.create(); 182 ((MultiFetchServerObjectReader) reader).append(nodes); 183 DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 184 synchronized (this) { // avoid race condition in cancel() 185 reader = null; 186 if (!ways.isEmpty()) { 187 // Collect incomplete nodes of parent ways 188 Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete)) 189 .collect(Collectors.toSet()); 190 if (!nodes.isEmpty()) { 191 reader = MultiFetchServerObjectReader.create(); 192 ((MultiFetchServerObjectReader) reader).append(nodes); 193 DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 194 synchronized (this) { // avoid race condition in cancel() 195 reader = null; 196 } 197 new DataSetMerger(parents, wayNodes).merge(); 186 198 } 187 new DataSetMerger(parents, wayNodes).merge();188 199 } 189 200 } 190 201 } catch (OsmTransferException e) { … … 193 204 lastException = e; 194 205 } 195 206 } 207 196 208 } -
src/org/openstreetmap/josm/gui/io/DownloadFromOverpassTask.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.io; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.io.IOException; 7 8 import org.openstreetmap.josm.data.Bounds; 9 import org.openstreetmap.josm.data.osm.DataSet; 10 import org.openstreetmap.josm.data.osm.DataSetMerger; 11 import org.openstreetmap.josm.gui.ExceptionDialogUtil; 12 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 13 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 14 import org.openstreetmap.josm.io.OsmTransferException; 15 import org.openstreetmap.josm.io.OverpassDownloadReader; 16 import org.xml.sax.SAXException; 17 18 /** 19 * Download OSM data from Overpass API 20 * 21 */ 22 public class DownloadFromOverpassTask extends PleaseWaitRunnable { 23 private boolean canceled; 24 private final String request; 25 private final DataSet ds; 26 private Exception lastException; 27 28 /** 29 * Constructor 30 * @param request the overpass query 31 * @param ds the {@code DataSet} instance that should contain the downloaded data 32 * @param monitor ProgressMonitor to use or null to create a new one. 33 */ 34 public DownloadFromOverpassTask(String request, DataSet ds, ProgressMonitor monitor) { 35 super(tr("Download objects via Overpass API"), monitor, false); 36 this.request = request; 37 this.ds = ds; 38 } 39 40 @Override 41 protected void cancel() { 42 canceled = true; 43 } 44 45 @Override 46 protected void realRun() throws SAXException, IOException, OsmTransferException { 47 try { 48 OverpassDownloadReader reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0), 49 OverpassDownloadReader.OVERPASS_SERVER.get(), request); 50 DataSet tmpDs = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 51 if (!canceled) { 52 new DataSetMerger(ds, tmpDs).merge(); 53 } 54 } catch (OsmTransferException e) { 55 if (canceled) 56 return; 57 lastException = e; 58 } 59 60 } 61 62 @Override 63 protected void finish() { 64 if (canceled) 65 return; 66 if (lastException != null) { 67 ExceptionDialogUtil.explainException(lastException); 68 } 69 } 70 } -
src/org/openstreetmap/josm/gui/io/DownloadPrimitivesWithReferrersTask.java
9 9 import java.io.IOException; 10 10 import java.text.MessageFormat; 11 11 import java.util.ArrayList; 12 import java.util.Collections; 12 13 import java.util.HashSet; 14 import java.util.LinkedHashSet; 13 15 import java.util.List; 14 16 import java.util.Set; 15 17 import java.util.stream.Collectors; … … 31 33 import org.openstreetmap.josm.gui.util.GuiHelper; 32 34 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 33 35 import org.openstreetmap.josm.gui.widgets.JosmTextArea; 36 import org.openstreetmap.josm.io.MultiFetchOverpassObjectReader; 34 37 import org.openstreetmap.josm.io.OsmTransferException; 38 import org.openstreetmap.josm.io.OverpassDownloadReader; 35 39 import org.openstreetmap.josm.tools.GBC; 36 40 import org.xml.sax.SAXException; 37 41 … … 50 54 51 55 /** Temporary layer where downloaded primitives are put */ 52 56 private final OsmDataLayer tmpLayer; 53 /** Reference to the task that download requested primitives */54 private DownloadPrimitivesTask mainTask;55 57 /** Flag indicated that user ask for cancel this task */ 56 58 private boolean canceled; 57 59 /** Reference to the task currently running */ 58 60 private PleaseWaitRunnable currentTask; 59 61 62 /** set of missing ids, with overpass API these are also deleted objects */ 63 private Set<PrimitiveId> missingPrimitives; 64 60 65 /** 61 66 * Constructor 62 67 * … … 101 106 102 107 @Override 103 108 protected void realRun() throws SAXException, IOException, OsmTransferException { 109 if (Boolean.TRUE.equals(OverpassDownloadReader.FOR_MULTI_FETCH.get())) { 110 useOverpassApi(); 111 } else { 112 useOSMApi(); 113 } 114 } 115 116 private void useOverpassApi() { 117 String request = MultiFetchOverpassObjectReader.genOverpassQuery(ids, true, downloadReferrers, full); 118 currentTask = new DownloadFromOverpassTask(request, tmpLayer.data, getProgressMonitor().createSubTaskMonitor(1, false)); 119 currentTask.run(); 120 missingPrimitives = ids.stream() 121 .filter(id -> tmpLayer.data.getPrimitiveById(id) == null) 122 .collect(Collectors.toSet()); 123 } 124 125 private void useOSMApi() { 104 126 getProgressMonitor().setTicksCount(ids.size()+1); 105 127 // First, download primitives 106 mainTask = new DownloadPrimitivesTask(tmpLayer, ids, full, getProgressMonitor().createSubTaskMonitor(1, false)); 128 DownloadPrimitivesTask mainTask = new DownloadPrimitivesTask(tmpLayer, ids, full, 129 getProgressMonitor().createSubTaskMonitor(1, false)); 107 130 synchronized (this) { 108 131 currentTask = mainTask; 109 132 if (canceled) { … … 112 135 } 113 136 } 114 137 currentTask.run(); 138 139 missingPrimitives = mainTask.getMissingPrimitives(); 140 115 141 // Then, download referrers for each primitive 116 142 if (downloadReferrers && tmpLayer.data != null) { 117 143 // see #18895: don't try to download parents for invisible objects … … 143 169 else 144 170 layer.mergeFrom(tmpLayer); 145 171 172 // Collect known deleted primitives 173 final Set<PrimitiveId> del = new HashSet<>(); 174 DataSet ds = MainApplication.getLayerManager().getEditDataSet(); 175 for (PrimitiveId id : ids) { 176 OsmPrimitive osm = ds.getPrimitiveById(id); 177 if (osm != null && osm.isDeleted()) { 178 del.add(id); 179 } 180 } 181 final Set<PrimitiveId> errs; 182 if (missingPrimitives != null) { 183 errs = missingPrimitives.stream().filter(id -> !del.contains(id)).collect(Collectors.toCollection(LinkedHashSet::new)); 184 } else { 185 errs = Collections.emptySet(); 186 } 187 146 188 // Warm about missing primitives 147 final Set<PrimitiveId> errs = mainTask.getMissingPrimitives(); 148 if (errs != null && !errs.isEmpty()) 189 if (!errs.isEmpty()) { 190 final String assumedApiRC; 191 if (Boolean.TRUE.equals(OverpassDownloadReader.FOR_MULTI_FETCH.get())) { 192 assumedApiRC = tr("The server does not know an object with the requested id, it was either deleted or doesn't exist."); 193 194 } else { 195 assumedApiRC = tr("The server replied with response code 404.<br>" 196 + "This usually means, the server does not know an object with the requested id."); 197 } 149 198 GuiHelper.runInEDTAndWait(() -> reportProblemDialog(errs, 150 199 trn("Object could not be downloaded", "Some objects could not be downloaded", errs.size()), 151 200 trn("One object could not be downloaded.<br>", … … 152 201 "{0} objects could not be downloaded.<br>", 153 202 errs.size(), 154 203 errs.size()) 155 + tr("The server replied with response code 404.<br>" 156 + "This usually means, the server does not know an object with the requested id."), 204 + assumedApiRC, 157 205 tr("missing objects:"), 158 206 JOptionPane.ERROR_MESSAGE 159 207 ).showDialog()); 208 } 160 209 161 210 // Warm about deleted primitives 162 final Set<PrimitiveId> del = new HashSet<>();163 DataSet ds = MainApplication.getLayerManager().getEditDataSet();164 for (PrimitiveId id : ids) {165 OsmPrimitive osm = ds.getPrimitiveById(id);166 if (osm != null && osm.isDeleted()) {167 del.add(id);168 }169 }170 211 if (!del.isEmpty()) 171 212 GuiHelper.runInEDTAndWait(() -> reportProblemDialog(del, 172 213 trn("Object deleted", "Objects deleted", del.size()), … … 190 231 return null; 191 232 } 192 233 List<PrimitiveId> downloaded = new ArrayList<>(ids); 193 downloaded.removeAll(m ainTask.getMissingPrimitives());234 downloaded.removeAll(missingPrimitives); 194 235 return downloaded; 195 236 } 196 237 -
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.Map.Entry; 4 import java.util.Arrays; 5 import java.util.Collection; 6 import java.util.LinkedHashMap; 7 import java.util.List; 8 import java.util.Map; 5 9 import java.util.Set; 10 import java.util.TreeSet; 6 11 import java.util.stream.Collectors; 7 12 8 13 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 14 import org.openstreetmap.josm.data.osm.PrimitiveId; 9 15 import org.openstreetmap.josm.tools.Logging; 10 16 11 17 /** … … 14 20 * @since 9241 15 21 */ 16 22 public class MultiFetchOverpassObjectReader extends MultiFetchServerObjectReader { 23 private static final List<OsmPrimitiveType> wantedOrder = Arrays.asList(OsmPrimitiveType.RELATION, 24 OsmPrimitiveType.WAY, OsmPrimitiveType.NODE); 17 25 18 26 private static String getPackageString(final OsmPrimitiveType type, Set<Long> idPackage) { 19 27 return idPackage.stream().map(String::valueOf) 20 .collect(Collectors.joining(",", type.getAPIName() + (idPackage.size() == 1 ? "(" : "(id:"), ") ;"));28 .collect(Collectors.joining(",", type.getAPIName() + (idPackage.size() == 1 ? "(" : "(id:"), ")")); 21 29 } 22 30 23 31 /** 24 * Create a single query for all elements 25 * @return the request string 32 * Generate single overpass query to retrieve multiple primitives. Can be used to download parents, 33 * children, the objects, or any combination of them. 34 * @param ids the collection of ids 35 * @param includeObjects if false, don't retrieve the primitives (e.g. only the referrers) 36 * @param recurseUp if true, referrers (parents) of the objects are downloaded and all nodes of parent ways 37 * @param recurseDownRelations true: yes, recurse down to retrieve complete relations 38 * @return the overpass query 39 * @since xxx 26 40 */ 27 protected String buildComplexRequestString() { 28 StringBuilder sb = new StringBuilder(); 29 int countTypes = 0; 30 for (Entry<OsmPrimitiveType, Set<Long>> e : primitivesMap.entrySet()) { 31 if (!e.getValue().isEmpty()) { 32 countTypes++; 33 String list = getPackageString(e.getKey(), e.getValue()); 34 switch (e.getKey()) { 35 case MULTIPOLYGON: 36 case RELATION: 41 public static String genOverpassQuery(Collection<? extends PrimitiveId> ids, boolean includeObjects, boolean recurseUp, 42 boolean recurseDownRelations) { 43 Map<OsmPrimitiveType, Set<Long>> primitivesMap = new LinkedHashMap<>(); 44 Arrays.asList(OsmPrimitiveType.RELATION, OsmPrimitiveType.WAY, OsmPrimitiveType.NODE) 45 .forEach(type -> primitivesMap.put(type, new TreeSet<>())); 46 for (PrimitiveId p : ids) { 47 primitivesMap.get(p.getType()).add(p.getUniqueId()); 48 } 49 return genOverpassQuery(primitivesMap, includeObjects, recurseUp, recurseDownRelations); 50 } 51 52 /** 53 * Generate single overpass query to retrieve multiple primitives. Can be used to download parents, 54 * children, the objects, or any combination of them. 55 * @param primitivesMap map containing the primitives 56 * @param includeObjects if false, don't retrieve the primitives (e.g. only the referrers) 57 * @param recurseUp if true, referrers (parents) of the objects are downloaded and all nodes of parent ways 58 * @param recurseDownRelations true: yes, recurse down to retrieve complete relations 59 * @return the overpass query 60 */ 61 protected static String genOverpassQuery(Map<OsmPrimitiveType, Set<Long>> primitivesMap, boolean includeObjects, 62 boolean recurseUp, boolean recurseDownRelations) { 63 if (!(includeObjects || recurseUp || recurseDownRelations)) 64 throw new IllegalArgumentException("At least one options must be true"); 65 StringBuilder sb = new StringBuilder(128); 66 StringBuilder setsToInclude = new StringBuilder(); 67 StringBuilder up = new StringBuilder(); 68 String down = null; 69 for (OsmPrimitiveType type : wantedOrder) { 70 Set<Long> set = primitivesMap.get(type); 71 if (!set.isEmpty()) { 72 sb.append(getPackageString(type, set)); 73 if (type == OsmPrimitiveType.NODE) { 74 sb.append("->.n;"); 75 if (includeObjects) { 76 setsToInclude.append(".n;"); 77 } 78 if (recurseUp) { 79 up.append(".n;way(bn)->.wn;.n;rel(bn)->.rn;"); 80 setsToInclude.append(".wn;node(w);.rn;"); 81 } 82 } else if (type == OsmPrimitiveType.WAY) { 83 sb.append("->.w;"); 84 if (includeObjects) { 85 setsToInclude.append(".w;>;"); 86 } 87 if (recurseUp) { 88 up.append(".w;rel(bw)->.pw;"); 89 setsToInclude.append(".pw;"); 90 } 91 } else { 92 sb.append("->.r;"); 93 if (includeObjects) { 94 setsToInclude.append(".r;"); 95 } 96 if (recurseUp) { 97 up.append(".r;rel(br)->.pr;"); 98 setsToInclude.append(".pr;"); 99 } 37 100 if (recurseDownRelations) { 38 sb.append('(').append(list); 39 sb.setLength(sb.length()-1); // remove semicolon 40 //recurse down only one level, see #18835 41 sb.append("->.r;.r;rel(r);.r;way(r);>;.r;node(r););"); 42 } else { 43 sb.append(list); 101 // get complete ways and nodes of the relation and next level of sub relations 102 down = ".r;rel(r)->.rm;"; 103 setsToInclude.append(".r;>;.rm;"); 44 104 } 45 break;46 case CLOSEDWAY:47 case WAY:48 sb.append('(').append(list).append(">;);");49 break;50 case NODE:51 sb.append(list);52 105 } 53 106 } 54 107 } 108 if (up.length() > 0) { 109 sb.append(up); 110 } 111 if (down != null) { 112 sb.append(down); 113 } 114 sb.append('(').append(setsToInclude).append(");"); 115 116 sb.append("out meta;"); 55 117 String query = sb.toString(); 56 if (countTypes > 1) {57 query = "(" + query + ");";58 }59 query += "out meta;";60 118 Logging.debug("{0} {1}", "Generated Overpass query:", query); 61 119 return query; 62 120 } -
src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java
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 { -
test/unit/org/openstreetmap/josm/io/MultiFetchOverpassObjectReaderTest.java
4 4 import static org.junit.Assert.assertEquals; 5 5 6 6 import java.util.Arrays; 7 import java.util.List; 7 8 8 9 import org.junit.Rule; 9 10 import org.junit.Test; 10 11 import org.openstreetmap.josm.data.osm.Node; 12 import org.openstreetmap.josm.data.osm.OsmPrimitive; 11 13 import org.openstreetmap.josm.data.osm.Relation; 12 14 import org.openstreetmap.josm.data.osm.Way; 13 15 import org.openstreetmap.josm.testutils.JOSMTestRules; … … 27 29 public JOSMTestRules test = new JOSMTestRules().preferences(); 28 30 29 31 /** 30 * Test {@link MultiFetchOverpassObjectReader#buildRequestString} 31 */ 32 @Test 33 public void testBuildRequestWaysString() { 34 MultiFetchOverpassObjectReader reader = new MultiFetchOverpassObjectReader(); 35 reader.append(Arrays.asList(new Way(123), new Way(126), new Way(130))); 36 String requestString = reader.buildComplexRequestString(); 37 assertEquals("(way(id:123,126,130);>;);out meta;", requestString); 38 } 39 32 * Test {@link MultiFetchOverpassObjectReader#buildRequestString} 33 */ 34 @Test 35 public void testBuildRequestNodesString() { 36 List<OsmPrimitive> objects = Arrays.asList(new Node(123), new Node(126), new Node(130)); 37 String requestString; 38 // nodes without parents 39 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, false); 40 assertEquals("node(id:123,126,130)->.n;(.n;);out meta;", requestString); 41 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, true); 42 assertEquals("node(id:123,126,130)->.n;(.n;);out meta;", requestString); 43 44 // nodes with parents 45 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, false); 46 assertEquals("node(id:123,126,130)->.n;.n;way(bn)->.wn;.n;rel(bn)->.rn;(.n;.wn;node(w);.rn;);out meta;", 47 requestString); 48 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, true); 49 assertEquals("node(id:123,126,130)->.n;.n;way(bn)->.wn;.n;rel(bn)->.rn;(.n;.wn;node(w);.rn;);out meta;", 50 requestString); 51 52 // simulate download referrers 53 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, false, true, false); 54 assertEquals("node(id:123,126,130)->.n;.n;way(bn)->.wn;.n;rel(bn)->.rn;(.wn;node(w);.rn;);out meta;", 55 requestString); 56 57 } 58 59 /** 60 * Test {@link MultiFetchOverpassObjectReader#buildRequestString} 61 */ 62 @Test 63 public void testBuildRequestWaysString() { 64 List<OsmPrimitive> objects = Arrays.asList(new Way(123), new Way(126), new Way(130)); 65 String requestString; 66 // ways without parents (always with nodes) 67 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, false); 68 assertEquals("way(id:123,126,130)->.w;(.w;>;);out meta;", requestString); 69 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, true); 70 assertEquals("way(id:123,126,130)->.w;(.w;>;);out meta;", requestString); 71 72 // ways with parents (always with nodes) 73 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, false); 74 assertEquals("way(id:123,126,130)->.w;.w;rel(bw)->.pw;(.w;>;.pw;);out meta;", requestString); 75 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, true); 76 assertEquals("way(id:123,126,130)->.w;.w;rel(bw)->.pw;(.w;>;.pw;);out meta;", requestString); 77 78 // simulate download referrers 79 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, false, true, false); 80 assertEquals("way(id:123,126,130)->.w;.w;rel(bw)->.pw;(.pw;);out meta;", requestString); 81 82 } 83 40 84 /** 41 85 * Test {@link MultiFetchOverpassObjectReader#buildRequestString} 42 86 */ 43 87 @Test 44 public void testBuildRequestRelationsString() { 45 MultiFetchOverpassObjectReader reader = new MultiFetchOverpassObjectReader(); 46 reader.append(Arrays.asList(new Relation(123), new Relation(126), new Relation(130))); 47 reader.setRecurseDownRelations(true); 48 String requestString = reader.buildComplexRequestString(); 49 assertEquals("(relation(id:123,126,130)->.r;.r;rel(r);.r;way(r);>;.r;node(r););out meta;", requestString); 50 reader.setRecurseDownRelations(false); 51 requestString = reader.buildComplexRequestString(); 52 assertEquals("relation(id:123,126,130);out meta;", requestString); 88 public void testBuildRequestRelationsString() { 89 List<OsmPrimitive> objects = Arrays.asList(new Relation(123), new Relation(126), new Relation(130)); 90 String requestString; 91 // objects without parents or children 92 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, false); 93 assertEquals("relation(id:123,126,130)->.r;(.r;);out meta;", requestString); 94 // objects without parents, with children 95 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, true); 96 assertEquals("relation(id:123,126,130)->.r;.r;rel(r)->.rm;(.r;.r;>;.rm;);out meta;", requestString); 97 // objects with parents, without children 98 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, false); 99 assertEquals("relation(id:123,126,130)->.r;.r;rel(br)->.pr;(.r;.pr;);out meta;", requestString); 100 // objects with parents and with children 101 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, true); 102 assertEquals("relation(id:123,126,130)->.r;.r;rel(br)->.pr;.r;rel(r)->.rm;(.r;.pr;.r;>;.rm;);out meta;", 103 requestString); 104 // simulate download referrers 105 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, false, true, false); 106 assertEquals("relation(id:123,126,130)->.r;.r;rel(br)->.pr;(.pr;);out meta;", requestString); 107 53 108 } 54 109 55 /** 56 * Test {@link MultiFetchOverpassObjectReader#buildRequestString} 57 */ 58 @Test 59 public void testBuildComplexString() { 60 MultiFetchOverpassObjectReader reader = new MultiFetchOverpassObjectReader(); 61 reader.setRecurseDownRelations(true); 62 reader.append(Arrays.asList(new Relation(123), new Relation(126), new Relation(130), new Way(88), new Way(99), 63 new Node(1))); 64 String requestString = reader.buildComplexRequestString(); 110 /** 111 * Test {@link MultiFetchOverpassObjectReader#buildRequestString} 112 */ 113 @Test 114 public void testBuildComplexString() { 115 List<OsmPrimitive> objects = Arrays.asList(new Relation(123), new Relation(126), new Relation(130), new Way(88), new Way(99), 116 new Node(1)); 117 // all request strings should start with the same list of objects 118 final String ids = "relation(id:123,126,130)->.r;way(id:88,99)->.w;node(1)->.n;"; 119 String requestString; 120 121 // objects without parents (ways always with nodes) 122 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, false); 123 assertEquals(ids + "(.r;.w;>;.n;);out meta;", requestString); 124 // objects without parents (ways always with nodes), recurse down one level for sub relations 125 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, false, true); 126 assertEquals(ids + ".r;rel(r)->.rm;(.r;.r;>;.rm;.w;>;.n;);out meta;", requestString); 127 128 // objects with parents 129 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, false); 65 130 assertEquals( 66 "((relation(id:123,126,130)->.r;.r;rel(r);.r;way(r);>;.r;node(r););(way(id:88,99);>;);node(1););out meta;",131 ids + ".r;rel(br)->.pr;.w;rel(bw)->.pw;.n;way(bn)->.wn;.n;rel(bn)->.rn;(.r;.pr;.w;>;.pw;.n;.wn;node(w);.rn;);out meta;", 67 132 requestString); 68 reader.setRecurseDownRelations(false); 69 requestString = reader.buildComplexRequestString(); 70 assertEquals("(relation(id:123,126,130);(way(id:88,99);>;);node(1););out meta;", requestString); 71 } 72 133 134 // objects with parents, recurse down one level for sub relations 135 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, true, true, true); 136 assertEquals(ids + ".r;rel(br)->.pr;.w;rel(bw)->.pw;.n;way(bn)->.wn;.n;rel(bn)->.rn;.r;rel(r)->.rm;" 137 + "(.r;.pr;.r;>;.rm;.w;>;.pw;.n;.wn;node(w);.rn;);out meta;", requestString); 138 // simulate download referrers 139 requestString = MultiFetchOverpassObjectReader.genOverpassQuery(objects, false, true, false); 140 assertEquals( 141 ids + ".r;rel(br)->.pr;.w;rel(bw)->.pw;.n;way(bn)->.wn;.n;rel(bn)->.rn;(.pr;.pw;.wn;node(w);.rn;);out meta;", 142 requestString); 143 } 73 144 }