| | 113 | @Override |
| | 114 | public void realRun() throws IOException, SAXException, OsmTransferException { |
| | 115 | super.realRun(); |
| | 116 | final Map<OsmPrimitive, Instant> toLoadNext = new HashMap<>(); |
| | 117 | final Map<OsmPrimitive, Instant> toLoad = getToLoad(dataSet); |
| | 118 | while (!toLoad.isEmpty()) { |
| | 119 | loadLastVersions(toLoad, toLoadNext); |
| | 120 | toLoad.putAll(toLoadNext); |
| | 121 | toLoadNext.clear(); |
| | 122 | } |
| | 123 | } |
| | 124 | |
| | 125 | /** |
| | 126 | * This gets the last versions of references primitives. This may enough for many of the primitives. |
| | 127 | * @param toLoad The primitives to load |
| | 128 | * @param toLoadNext The primitives to load next (filled by this method) |
| | 129 | */ |
| | 130 | private void loadLastVersions(Map<OsmPrimitive, Instant> toLoad, Map<OsmPrimitive, Instant> toLoadNext) throws OsmTransferException { |
| | 131 | final Map<OsmPrimitiveType, Map<OsmPrimitive, Instant>> typeMap = toLoad.entrySet().stream() |
| | 132 | .collect(Collectors.groupingBy(entry -> entry.getKey().getType(), Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); |
| | 133 | final Map<PrimitiveId, OsmPrimitive> idMap = toLoad.keySet().stream() |
| | 134 | .collect(Collectors.toMap(OsmPrimitive::getPrimitiveId, Function.identity())); |
| | 135 | for (OsmPrimitiveType type : Arrays.asList(OsmPrimitiveType.NODE, OsmPrimitiveType.WAY, OsmPrimitiveType.RELATION)) { |
| | 136 | if (!typeMap.containsKey(type)) { |
| | 137 | continue; |
| | 138 | } |
| | 139 | final MultiFetchServerObjectReader reader = MultiFetchServerObjectReader.create(); |
| | 140 | typeMap.get(type).forEach((primitive, instant) -> reader.append(primitive)); |
| | 141 | final DataSet ds = reader.parseOsm(this.progressMonitor.createSubTaskMonitor(1, false)); |
| | 142 | switch (type) { |
| | 143 | case NODE: |
| | 144 | for (Node node : ds.getNodes()) { |
| | 145 | Node original = (Node) idMap.get(node.getPrimitiveId()); |
| | 146 | if (original != null && toLoad.get(original).isAfter(node.getInstant())) { |
| | 147 | original.load(node.save()); |
| | 148 | } |
| | 149 | toLoad.remove(original); |
| | 150 | } |
| | 151 | break; |
| | 152 | case WAY: |
| | 153 | for (Way way : ds.getWays()) { |
| | 154 | Way original = (Way) idMap.get(way.getPrimitiveId()); |
| | 155 | if (original != null && toLoad.get(original).isAfter(way.getInstant())) { |
| | 156 | Instant date = toLoad.get(original); |
| | 157 | original.load(way.save()); |
| | 158 | for (Long nodeId : way.getNodeIds()) { |
| | 159 | if (way.getDataSet().getPrimitiveById(nodeId, OsmPrimitiveType.NODE) == null) { |
| | 160 | Node n = new Node(nodeId); |
| | 161 | way.getDataSet().addPrimitive(n); |
| | 162 | toLoadNext.put(n, date); |
| | 163 | } |
| | 164 | } |
| | 165 | } |
| | 166 | toLoad.remove(original); |
| | 167 | } |
| | 168 | break; |
| | 169 | case RELATION: |
| | 170 | for (Relation relation : ds.getRelations()) { |
| | 171 | Relation original = (Relation) idMap.get(relation.getPrimitiveId()); |
| | 172 | if (original != null && toLoad.get(original).isAfter(relation.getInstant())) { |
| | 173 | original.load(relation.save()); |
| | 174 | } |
| | 175 | toLoad.remove(relation); |
| | 176 | } |
| | 177 | break; |
| | 178 | default: |
| | 179 | throw new IllegalStateException("Only Node, Ways, and Relations should be returned by the API"); |
| | 180 | } |
| | 181 | } |
| | 182 | } |
| | 183 | |
| 114 | | Map<OsmPrimitive, Instant> toLoad = new HashMap<>(); |
| 115 | | for (OsmPrimitive p : downloadedData.allNonDeletedPrimitives()) { |
| 116 | | if (p.isIncomplete()) { |
| 117 | | Instant timestamp = p.getReferrers().stream() |
| 118 | | .filter(ref -> !ref.isTimestampEmpty()) |
| 119 | | .findFirst() |
| 120 | | .map(AbstractPrimitive::getInstant) |
| 121 | | .orElse(null); |
| 122 | | toLoad.put(p, timestamp); |
| 123 | | } |
| 124 | | } |
| 125 | | if (isCanceled()) return; |
| 126 | | // Let's load all required history |
| 127 | | MainApplication.worker.submit(new HistoryLoaderAndListener(toLoad)); |
| 128 | | } catch (RejectedExecutionException e) { |
| 129 | | rememberException(e); |
| 130 | | setFailed(true); |
| | 192 | Map<OsmPrimitive, Instant> toLoad = getToLoad(downloadedData); |
| | 193 | if (isCanceled()) return; |
| | 194 | // Let's load all required history |
| | 195 | MainApplication.worker.submit(new HistoryLoaderAndListener(toLoad)); |
| | 196 | } catch (RejectedExecutionException e) { |
| | 197 | rememberException(e); |
| | 198 | setFailed(true); |
| | 199 | } |
| | 200 | } |
| | 201 | } |
| | 202 | |
| | 203 | /** |
| | 204 | * Get the primitives to load more information |
| | 205 | * @param ds The dataset to look for incomplete primitives from |
| | 206 | * @return The objects that still need to be loaded |
| | 207 | */ |
| | 208 | private static Map<OsmPrimitive, Instant> getToLoad(DataSet ds) { |
| | 209 | Map<OsmPrimitive, Instant> toLoad = new HashMap<>(); |
| | 210 | for (OsmPrimitive p : ds.allNonDeletedPrimitives()) { |
| | 211 | if (p.isIncomplete()) { |
| | 212 | Instant timestamp = p.getReferrers().stream() |
| | 213 | .filter(ref -> !ref.isTimestampEmpty()) |
| | 214 | .findFirst() |
| | 215 | .map(AbstractPrimitive::getInstant) |
| | 216 | .orElse(null); |
| | 217 | toLoad.put(p, timestamp); |