source: osm/applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/datasets/AbstractDataSetHandler.java@ 28054

Last change on this file since 28054 was 28054, checked in by donvip, 13 years ago

opendata: various download improvements

File size: 19.1 KB
Line 
1// JOSM opendata plugin.
2// Copyright (C) 2011-2012 Don-vip
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16package org.openstreetmap.josm.plugins.opendata.core.datasets;
17
18import java.io.File;
19import java.net.MalformedURLException;
20import java.net.URL;
21import java.nio.charset.Charset;
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.List;
25import java.util.regex.Pattern;
26
27import org.geotools.referencing.CRS;
28import org.geotools.referencing.crs.AbstractDerivedCRS;
29import org.geotools.referencing.datum.DefaultEllipsoid;
30import org.geotools.referencing.operation.projection.LambertConformal;
31import org.geotools.referencing.operation.projection.LambertConformal1SP;
32import org.geotools.referencing.operation.projection.LambertConformal2SP;
33import org.geotools.referencing.operation.projection.MapProjection.AbstractProvider;
34import org.opengis.parameter.ParameterDescriptor;
35import org.opengis.parameter.ParameterValueGroup;
36import org.opengis.referencing.FactoryException;
37import org.opengis.referencing.crs.CoordinateReferenceSystem;
38import org.opengis.referencing.datum.GeodeticDatum;
39import org.opengis.referencing.operation.MathTransform;
40import org.openstreetmap.josm.Main;
41import org.openstreetmap.josm.data.Bounds;
42import org.openstreetmap.josm.data.coor.EastNorth;
43import org.openstreetmap.josm.data.coor.LatLon;
44import org.openstreetmap.josm.data.osm.DataSet;
45import org.openstreetmap.josm.data.osm.IPrimitive;
46import org.openstreetmap.josm.data.osm.OsmPrimitive;
47import org.openstreetmap.josm.data.projection.AbstractProjection;
48import org.openstreetmap.josm.data.projection.Ellipsoid;
49import org.openstreetmap.josm.data.projection.Projection;
50import org.openstreetmap.josm.data.projection.Projections;
51import org.openstreetmap.josm.data.projection.proj.LambertConformalConic;
52import org.openstreetmap.josm.data.projection.proj.LambertConformalConic.Parameters;
53import org.openstreetmap.josm.data.projection.proj.LambertConformalConic.Parameters1SP;
54import org.openstreetmap.josm.data.projection.proj.LambertConformalConic.Parameters2SP;
55import org.openstreetmap.josm.gui.preferences.SourceEditor.ExtendedSourceEntry;
56import org.openstreetmap.josm.io.AbstractReader;
57import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
58import org.openstreetmap.josm.plugins.opendata.core.util.NamesFrUtils;
59import org.openstreetmap.josm.tools.Pair;
60
61public abstract class AbstractDataSetHandler implements OdConstants {
62
63 public abstract boolean acceptsFilename(String filename);
64
65 public boolean acceptsFile(File file) {
66 return acceptsFilename(file.getName());
67 }
68
69 public abstract void updateDataSet(DataSet ds);
70
71 public void checkDataSetSource(DataSet ds) {
72 if (ds != null) {
73 for (OsmPrimitive p : ds.allPrimitives()) {
74 if (p.hasKeys() || p.getReferrers().isEmpty()) {
75 if (getSource() != null && p.get("source") == null) {
76 p.put("source", getSource());
77 }
78 if (sourceDate != null && p.get("source:date") == null) {
79 p.put("source:date", sourceDate);
80 }
81 }
82 }
83 }
84 }
85
86 public void checkNames(DataSet ds) {
87 if (ds != null) {
88 for (OsmPrimitive p : ds.allPrimitives()) {
89 if (p.get("name") != null) {
90 p.put("name", NamesFrUtils.checkDictionary(p.get("name")));
91 }
92 }
93 }
94 }
95
96 private String name;
97 private DataSetCategory category;
98 private String sourceDate;
99 private File associatedFile;
100 private URL dataURL;
101
102 public AbstractDataSetHandler() {
103 }
104
105 private final boolean acceptsFilename(String filename, String[] expected, String ... extensions ) {
106 if (filename != null) {
107 for (String name : expected) {
108 for (String ext : extensions) {
109 if (Pattern.compile(name+"\\."+ext, Pattern.CASE_INSENSITIVE).matcher(filename).matches()) {
110 //if (filename.equalsIgnoreCase(name+"."+ext)) {
111 return true;
112 }
113 }
114 }
115 }
116 return false;
117 }
118
119 protected final boolean acceptsCsvFilename(String filename, String ... expected) {
120 return acceptsFilename(filename, expected, CSV_EXT);
121 }
122
123 protected final boolean acceptsXlsFilename(String filename, String ... expected) {
124 return acceptsFilename(filename, expected, XLS_EXT);
125 }
126
127 protected final boolean acceptsOdsFilename(String filename, String ... expected) {
128 return acceptsFilename(filename, expected, ODS_EXT);
129 }
130
131 protected final boolean acceptsShpFilename(String filename, String ... expected) {
132 return acceptsFilename(filename, expected, SHP_EXT);
133 }
134
135 protected final boolean acceptsMifFilename(String filename, String ... expected) {
136 return acceptsFilename(filename, expected, MIF_EXT);
137 }
138
139 protected final boolean acceptsMifTabFilename(String filename, String ... expected) {
140 return acceptsFilename(filename, expected, MIF_EXT, TAB_EXT);
141 }
142
143 protected final boolean acceptsShpMifFilename(String filename, String ... expected) {
144 return acceptsFilename(filename, expected, SHP_EXT, MIF_EXT);
145 }
146
147 protected final boolean acceptsKmlFilename(String filename, String ... expected) {
148 return acceptsFilename(filename, expected, KML_EXT);
149 }
150
151 protected final boolean acceptsKmzFilename(String filename, String ... expected) {
152 return acceptsFilename(filename, expected, KMZ_EXT);
153 }
154
155 protected final boolean acceptsKmzTabFilename(String filename, String ... expected) {
156 return acceptsFilename(filename, expected, KMZ_EXT, TAB_EXT);
157 }
158
159 protected final boolean acceptsZipFilename(String filename, String ... expected) {
160 return acceptsFilename(filename, expected, ZIP_EXT);
161 }
162
163 protected final boolean acceptsCsvKmzFilename(String filename, String ... expected) {
164 return acceptsFilename(filename, expected, CSV_EXT, KMZ_EXT);
165 }
166
167 protected final boolean acceptsCsvKmzTabFilename(String filename, String ... expected) {
168 return acceptsFilename(filename, expected, CSV_EXT, KMZ_EXT, TAB_EXT);
169 }
170
171 protected final boolean acceptsCsvXlsFilename(String filename, String ... expected) {
172 return acceptsFilename(filename, expected, CSV_EXT, XLS_EXT);
173 }
174
175 public URL getWikiURL() {return null;}
176
177 public URL getLocalPortalURL() {return null;}
178
179 public URL getNationalPortalURL() {return null;}
180
181 public URL getLicenseURL() {return null;}
182
183 public URL getDataURL() {return dataURL;}
184
185 public final void setDataURL(String url) throws MalformedURLException {
186 this.dataURL = new URL(url);
187 }
188
189 public final void setDataURL(URL url) {
190 this.dataURL = url;
191 }
192
193 public List<Pair<String,URL>> getDataURLs() {return null;}
194
195 public AbstractReader getReaderForUrl(String url) {return null;}
196
197 public final DataSetCategory getCategory() {
198 return category;
199 }
200
201 public final void setCategory(DataSetCategory category) {
202 this.category = category;
203 }
204
205 public final Collection<String> getOsmXapiRequests(Bounds bounds) {
206 return getOsmXapiRequests(
207 LatLon.roundToOsmPrecisionStrict(bounds.getMin().lon())+","+
208 LatLon.roundToOsmPrecisionStrict(bounds.getMin().lat())+","+
209 LatLon.roundToOsmPrecisionStrict(bounds.getMax().lon())+","+
210 LatLon.roundToOsmPrecisionStrict(bounds.getMax().lat()));
211 }
212
213 protected Collection<String> getOsmXapiRequests(String bbox) {return null;}
214
215 public final String getOverpassApiRequest(Bounds bounds) {
216 return getOverpassApiRequest(
217 "w=\""+LatLon.roundToOsmPrecisionStrict(bounds.getMin().lon())+"\" "+
218 "s=\""+LatLon.roundToOsmPrecisionStrict(bounds.getMin().lat())+"\" "+
219 "e=\""+LatLon.roundToOsmPrecisionStrict(bounds.getMax().lon())+"\" "+
220 "n=\""+LatLon.roundToOsmPrecisionStrict(bounds.getMax().lat())+"\"");
221 }
222
223 public enum OaQueryType {
224 NODE ("node"),
225 WAY ("way"),
226 RELATION ("relation");
227 @Override
228 public String toString() { return this.value; }
229 private OaQueryType(final String value) { this.value = value; }
230 private final String value;
231 }
232
233 public enum OaRecurseType {
234 RELATION_RELATION ("relation-relation"),
235 RELATION_BACKWARDS ("relation-backwards"),
236 RELATION_WAY ("relation-way"),
237 RELATION_NODE ("relation-node"),
238 WAY_NODE ("way-node"),
239 WAY_RELATION ("way-relation"),
240 NODE_RELATION ("node-relation"),
241 NODE_WAY ("node-way");
242 @Override
243 public String toString() { return this.value; }
244 private OaRecurseType(final String value) { this.value = value; }
245 private final String value;
246 }
247
248 protected String getOverpassApiRequest(String bbox) {return null;}
249
250 protected final String oaUnion(String ... queries) {
251 String result = "<union>\n";
252 for (String query : queries) {
253 if (query != null) {
254 result += query + "\n";
255 }
256 }
257 result += "</union>";
258 return result;
259 }
260
261 protected final String oaQuery(String bbox, OaQueryType type, String ... conditions) {
262 String result = "<query type=\""+type+"\" >\n";
263 if (bbox != null) {
264 result += "<bbox-query "+bbox+"/>\n";
265 }
266 for (String condition : conditions) {
267 if (condition != null) {
268 result += condition + "\n";
269 }
270 }
271 result += "</query>";
272 return result;
273 }
274
275 protected final String oaRecurse(OaRecurseType type, String into) {
276 return "<recurse type=\""+type+"\" into=\""+into+"\"/>\n";
277 }
278
279 protected final String oaRecurse(OaRecurseType ... types) {
280 String result = "";
281 for (OaRecurseType type : types) {
282 result += "<recurse type=\""+type+"\"/>\n";
283 }
284 return result;
285 }
286
287 protected final String oaPrint() {
288 return "<print mode=\"meta\"/>";
289 }
290
291 protected final String oaHasKey(String key) {
292 return oaHasKey(key, null);
293 }
294
295 protected final String oaHasKey(String key, String value) {
296 return "<has-kv k=\""+key+"\" "+(value != null && !value.isEmpty() ? "v=\""+value+"\"" : "")+" />";
297 }
298
299 public boolean equals(IPrimitive p1, IPrimitive p2) {return false;}
300
301 public boolean isRelevant(IPrimitive p) {return false;}
302
303 public final Collection<IPrimitive> extractRelevantPrimitives(DataSet ds) {
304 ArrayList<IPrimitive> result = new ArrayList<IPrimitive>();
305 for (IPrimitive p : ds.allPrimitives()) {
306 if (isRelevant(p)) {
307 result.add(p);
308 }
309 }
310 return result;
311 }
312
313 public boolean isForbidden(IPrimitive p) {return false;}
314
315 public boolean hasForbiddenTags() {return false;}
316
317 public interface ValueReplacer {
318 public String replace(String value);
319 }
320
321 protected final void replace(IPrimitive p, String dataKey, String osmKey) {
322 addOrReplace(p, dataKey, osmKey, null, null, null, true);
323 }
324
325 protected final void replace(IPrimitive p, String dataKey, String osmKey, ValueReplacer replacer) {
326 addOrReplace(p, dataKey, osmKey, null, null, replacer, true);
327 }
328
329 protected final void replace(IPrimitive p, String dataKey, String osmKey, String[] dataValues, String[] osmValues) {
330 addOrReplace(p, dataKey, osmKey, dataValues, osmValues, null, true);
331 }
332
333 protected final void add(IPrimitive p, String dataKey, String osmKey, ValueReplacer replacer) {
334 addOrReplace(p, dataKey, osmKey, null, null, replacer, false);
335 }
336
337 protected final void add(IPrimitive p, String dataKey, String osmKey, String[] dataValues, String[] osmValues) {
338 addOrReplace(p, dataKey, osmKey, dataValues, osmValues, null, false);
339 }
340
341 private final void addOrReplace(IPrimitive p, String dataKey, String osmKey, String[] dataValues, String[] osmValues, ValueReplacer replacer, boolean replace) {
342 String value = p.get(dataKey);
343 if (value != null) {
344 int index = -1;
345 for (int i = 0; dataValues != null && index == -1 && i < dataValues.length; i++) {
346 if (Pattern.compile(dataValues[i], Pattern.CASE_INSENSITIVE).matcher(value).matches()) {
347 index = i;
348 }
349 /*if (value.equalsIgnoreCase(csvValues[i])) {
350 index = i;
351 }*/
352 }
353 if (index > -1 && osmValues != null) {
354 doAddReplace(p, dataKey, osmKey, osmValues[index], replace);
355 } else if (replacer != null) {
356 doAddReplace(p, dataKey, osmKey, replacer.replace(value), replace);
357 } else if (dataValues == null || osmValues == null) {
358 doAddReplace(p, dataKey, osmKey, value, replace);
359 }
360 }
361 }
362
363 private final void doAddReplace(IPrimitive p, String dataKey, String osmKey, String osmValue, boolean replace) {
364 if (replace) {
365 p.remove(dataKey);
366 }
367 p.put(osmKey, osmValue);
368 }
369
370 public String getSource() {
371 return null;
372 }
373
374 public final String getSourceDate() {
375 return sourceDate;
376 }
377
378 public final void setSourceDate(String sourceDate) {
379 this.sourceDate = sourceDate;
380 }
381
382 public final String getName() {
383 return name;
384 }
385
386 public final void setName(String name) {
387 this.name = name;
388 }
389
390 public String getLocalPortalIconName() {
391 return ICON_CORE_24;
392 }
393
394 public String getNationalPortalIconName() {
395 return ICON_CORE_24;
396 }
397
398 public String getDataLayerIconName() {
399 return ICON_CORE_16;
400 }
401
402 public boolean handlesSpreadSheetProjection() {
403 return false;
404 }
405
406 public List<Projection> getSpreadSheetProjections() {
407 return null;
408 }
409
410 public LatLon getSpreadSheetCoor(EastNorth en, String[] fields) {
411 return null;
412 }
413
414 public Charset getCsvCharset() {
415 return null;
416 }
417
418 public String getCsvSeparator() {
419 return null;
420 }
421
422 public int getSheetNumber() {
423 return -1;
424 }
425
426 public ExtendedSourceEntry getMapPaintStyle() {
427 return null;
428 }
429
430 public ExtendedSourceEntry getTaggingPreset() {
431 return null;
432 }
433
434 protected final ExtendedSourceEntry getMapPaintStyle(String displayName) {
435 return getMapPaintStyle(displayName, this.getClass().getSimpleName().replace("Handler", ""));
436 }
437
438 protected final ExtendedSourceEntry getMapPaintStyle(String displayName, String fileNameWithoutExtension) {
439 return new ExtendedSourceEntry(displayName, PROTO_RSRC+//"/"+
440 this.getClass().getPackage().getName().replace(".", "/")+"/"+
441 fileNameWithoutExtension+"."+MAPCSS_EXT);
442 }
443
444 public boolean preferMultipolygonToSimpleWay() {
445 return false;
446 }
447
448 public final void setAssociatedFile(File associatedFile) {
449 this.associatedFile = associatedFile;
450 }
451
452 public final File getAssociatedFile() {
453 return this.associatedFile;
454 }
455
456 private static final List<Pair<org.opengis.referencing.datum.Ellipsoid, Ellipsoid>>
457 ellipsoids = new ArrayList<Pair<org.opengis.referencing.datum.Ellipsoid, Ellipsoid>>();
458 static {
459 ellipsoids.add(new Pair<org.opengis.referencing.datum.Ellipsoid, Ellipsoid>(DefaultEllipsoid.GRS80, Ellipsoid.GRS80));
460 ellipsoids.add(new Pair<org.opengis.referencing.datum.Ellipsoid, Ellipsoid>(DefaultEllipsoid.WGS84, Ellipsoid.WGS84));
461 }
462
463 private static final Double get(ParameterValueGroup values, ParameterDescriptor desc) {
464 return (Double) values.parameter(desc.getName().getCode()).getValue();
465 }
466
467 private static final boolean equals(Double a, Double b) {
468 boolean res = Math.abs(a - b) <= Main.pref.getDouble(PREF_CRS_COMPARISON_TOLERANCE, DEFAULT_CRS_COMPARISON_TOLERANCE);
469 if (Main.pref.getBoolean(PREF_CRS_COMPARISON_DEBUG, false)) {
470 System.out.println("Comparing "+a+" and "+b+" -> "+res);
471 }
472 return res;
473 }
474
475 public MathTransform findMathTransform(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS, boolean lenient) throws FactoryException {
476 if (sourceCRS instanceof AbstractDerivedCRS && sourceCRS.getName().getCode().equalsIgnoreCase("Lambert_Conformal_Conic")) {
477 List<MathTransform> result = new ArrayList<MathTransform>();
478 AbstractDerivedCRS crs = (AbstractDerivedCRS) sourceCRS;
479 MathTransform transform = crs.getConversionFromBase().getMathTransform();
480 if (transform instanceof LambertConformal && crs.getDatum() instanceof GeodeticDatum) {
481 LambertConformal lambert = (LambertConformal) transform;
482 GeodeticDatum geo = (GeodeticDatum) crs.getDatum();
483 for (Projection p : Projections.getProjections()) {
484 if (p instanceof AbstractProjection) {
485 AbstractProjection ap = (AbstractProjection) p;
486 if (ap.getProj() instanceof LambertConformalConic) {
487 for (Pair<org.opengis.referencing.datum.Ellipsoid, Ellipsoid> pair : ellipsoids) {
488 if (pair.a.equals(geo.getEllipsoid()) && pair.b.equals(ap.getEllipsoid())) {
489 boolean ok = true;
490 ParameterValueGroup values = lambert.getParameterValues();
491 Parameters params = ((LambertConformalConic) ap.getProj()).getParameters();
492
493 ok = ok ? equals(get(values, AbstractProvider.LATITUDE_OF_ORIGIN), params.latitudeOrigin) : ok;
494 ok = ok ? equals(get(values, AbstractProvider.CENTRAL_MERIDIAN), ap.getCentralMeridian()) : ok;
495 ok = ok ? equals(get(values, AbstractProvider.SCALE_FACTOR), ap.getScaleFactor()) : ok;
496 ok = ok ? equals(get(values, AbstractProvider.FALSE_EASTING), ap.getFalseEasting()) : ok;
497 ok = ok ? equals(get(values, AbstractProvider.FALSE_NORTHING), ap.getFalseNorthing()) : ok;
498
499 if (lambert instanceof LambertConformal2SP && params instanceof Parameters2SP) {
500 Parameters2SP param = (Parameters2SP) params;
501 ok = ok ? equals(Math.min(get(values, AbstractProvider.STANDARD_PARALLEL_1),get(values, AbstractProvider.STANDARD_PARALLEL_2)),
502 Math.min(param.standardParallel1, param.standardParallel2)) : ok;
503 ok = ok ? equals(Math.max(get(values, AbstractProvider.STANDARD_PARALLEL_1), get(values, AbstractProvider.STANDARD_PARALLEL_2)),
504 Math.max(param.standardParallel1, param.standardParallel2)) : ok;
505
506 } else if (!(lambert instanceof LambertConformal1SP && params instanceof Parameters1SP)) {
507 ok = false;
508 }
509
510 if (ok) {
511 try {
512 result.add(CRS.findMathTransform(CRS.decode(p.toCode()), targetCRS, lenient));
513 } catch (FactoryException e) {
514 System.err.println(e.getMessage());
515 }
516 }
517 }
518 }
519 }
520 }
521 }
522 }
523 if (!result.isEmpty()) {
524 if (result.size() > 1) {
525 System.err.println("Found multiple projections !"); // TODO: something
526 }
527 return result.get(0);
528 }
529 }
530 return null;
531 }
532
533 public boolean checkShpNodeProximity() {
534 return false;
535 }
536
537 public boolean acceptsUrl(String url) {
538 if (getDataURL() != null && url.equals(getDataURL().toString())) {
539 return true;
540 }
541 if (getDataURLs() != null) {
542 for (Pair<String, URL> pair : getDataURLs()) {
543 if (pair.b != null && url.equals(pair.b.toString())) {
544 return true;
545 }
546 }
547 }
548 return false;
549 }
550
551 private boolean setSkipXsdValidationInZipReading = false;
552
553 public final void setSkipXsdValidationInZipReading(boolean skip) {
554 setSkipXsdValidationInZipReading = skip;
555 }
556
557 public boolean skipXsdValidationInZipReading() {
558 return setSkipXsdValidationInZipReading;
559 }
560}
Note: See TracBrowser for help on using the repository browser.