4
4
import java .io .BufferedReader ;
5
5
import java .io .IOException ;
6
6
import java .io .InputStream ;
7
+ import java .io .UncheckedIOException ;
7
8
import java .net .URL ;
8
9
import java .nio .charset .StandardCharsets ;
9
10
import java .util .AbstractList ;
29
30
30
31
import org .openstreetmap .josm .data .coor .LatLon ;
31
32
import org .openstreetmap .josm .data .osm .OsmPrimitive ;
33
+ import org .openstreetmap .josm .data .osm .Tagged ;
32
34
import org .openstreetmap .josm .gui .Notification ;
33
35
import org .openstreetmap .josm .tools .HttpClient ;
34
36
import org .openstreetmap .josm .tools .I18n ;
37
+ import org .openstreetmap .josm .tools .JosmRuntimeException ;
35
38
import org .openstreetmap .josm .tools .LanguageInfo ;
36
39
import org .openstreetmap .josm .tools .Logging ;
37
40
import org .openstreetmap .josm .tools .Pair ;
@@ -55,21 +58,28 @@ public final class WikipediaApp {
55
58
56
59
private static final String STRING_URI_PIPE = Utils .encodeUrl ("|" );
57
60
61
+ private static final String WIKIDATA = "wikidata" ;
62
+ private static final String WIKIPEDIA = "wikipedia" ;
63
+
64
+ private final String [] wikipediaKeys ;
58
65
private final String wikipediaLang ;
59
66
private final SitematrixResult .Sitematrix .Site site ;
60
67
61
68
private WikipediaApp (final String wikipediaLang ) throws IOException {
62
69
this .wikipediaLang = wikipediaLang ;
70
+ this .wikipediaKeys = new String [] {WIKIDATA , WIKIPEDIA , WIKIPEDIA + ':' + wikipediaLang };
63
71
64
72
final SitematrixResult .Sitematrix sitematrix = ApiQueryClient .query (WikidataActionApiQuery .sitematrix ());
65
- final SitematrixResult .Sitematrix .Language language = sitematrix .getLanguages ().stream (). filter ( it -> wikipediaLang . equalsIgnoreCase ( it . getCode ())). findFirst (). orElse ( null );
66
- final SitematrixResult . Sitematrix . Site site ;
73
+ final SitematrixResult .Sitematrix .Language language = sitematrix .getLanguages ().stream ()
74
+ . filter ( it -> wikipediaLang . equalsIgnoreCase ( it . getCode ())). findFirst (). orElse ( null ) ;
67
75
if (language != null ) {
68
- site = language .getSites ().stream ().filter (it -> "wiki" .equals (it .getCode ())).findFirst ().orElseThrow (() -> new IllegalArgumentException ("No Wikipedia for language " + language .getName () + " (" + language .getCode () + ") found!" ));
76
+ this .site = language .getSites ().stream ().filter (it -> "wiki" .equals (it .getCode ())).findFirst ()
77
+ .orElseThrow (() -> new IllegalArgumentException ("No Wikipedia for language " + language .getName ()
78
+ + " (" + language .getCode () + ") found!" ));
69
79
} else {
70
- site = sitematrix .getSpecialSites ().stream ().filter (it -> wikipediaLang .equals (it .getCode ())).findFirst ().orElseThrow (() -> new IllegalArgumentException ("No wiki site for code '" + wikipediaLang + "' found!" ));
80
+ this .site = sitematrix .getSpecialSites ().stream ().filter (it -> wikipediaLang .equals (it .getCode ())).findFirst ()
81
+ .orElseThrow (() -> new IllegalArgumentException ("No wiki site for code '" + wikipediaLang + "' found!" ));
71
82
}
72
- this .site = site ;
73
83
}
74
84
75
85
public static WikipediaApp forLanguage (final String wikipediaLang ) {
@@ -108,20 +118,19 @@ private static HttpClient.Response connect(String url) throws IOException {
108
118
public List <WikipediaEntry > getEntriesFromCoordinates (LatLon min , LatLon max ) {
109
119
try {
110
120
// construct url
111
- final String url = new StringBuilder (getSiteUrl ()).append ("/w/api.php" )
112
- .append ("?action=query" )
113
- .append ("&list=geosearch" )
114
- .append ("&format=xml" )
115
- .append ("&gslimit=500" )
116
- .append ("&gsbbox=" )
117
- .append (max .lat ()).append (STRING_URI_PIPE ).append (min .lon ())
118
- .append (STRING_URI_PIPE ).append (min .lat ()).append (STRING_URI_PIPE ).append (max .lon ())
119
- .toString ();
121
+ final String url = getSiteUrl () + "/w/api.php" +
122
+ "?action=query" +
123
+ "&list=geosearch" +
124
+ "&format=xml" +
125
+ "&gslimit=500" +
126
+ "&gsbbox=" +
127
+ max .lat () + STRING_URI_PIPE + min .lon () +
128
+ STRING_URI_PIPE + min .lat () + STRING_URI_PIPE + max .lon ();
120
129
// parse XML document
121
130
try (InputStream in = connect (url ).getContent ()) {
122
131
final Document doc = newDocumentBuilder ().parse (in );
123
132
final String errorInfo = X_PATH .evaluateString ("//error/@info" , doc );
124
- if (errorInfo != null && errorInfo .length () >= 1 ) {
133
+ if (errorInfo != null && ! errorInfo .isEmpty () ) {
125
134
// I18n: {0} is the error message returned by the API
126
135
new Notification (I18n .tr ("Downloading entries with geo coordinates failed: {0}" , errorInfo ))
127
136
.setIcon (WikipediaPlugin .NOTIFICATION_ICON )
@@ -133,24 +142,25 @@ public List<WikipediaEntry> getEntriesFromCoordinates(LatLon min, LatLon max) {
133
142
final LatLon latLon = new LatLon (
134
143
X_PATH .evaluateDouble ("@lat" , node ),
135
144
X_PATH .evaluateDouble ("@lon" , node ));
136
- if ("wikidata" .equals (wikipediaLang )) {
145
+ if (WIKIDATA .equals (wikipediaLang )) {
137
146
return new WikidataEntry (name , null , latLon , null );
138
147
} else {
139
148
return new WikipediaEntry (wikipediaLang , name , latLon );
140
149
}
141
150
}).collect (Collectors .toList ());
142
- if ("wikidata" .equals (wikipediaLang )) {
151
+ if (WIKIDATA .equals (wikipediaLang )) {
143
152
return new ArrayList <>(getLabelForWikidata (entries , Locale .getDefault ()));
144
153
} else {
145
154
return entries ;
146
155
}
147
156
}
148
157
} catch (Exception ex ) {
149
- throw new RuntimeException (ex );
158
+ throw new JosmRuntimeException (ex );
150
159
}
151
160
}
152
161
153
- public static List <WikidataEntry > getWikidataEntriesForQuery (final String languageForQuery , final String query , final Locale localeForLabels ) {
162
+ public static List <WikidataEntry > getWikidataEntriesForQuery (final String languageForQuery , final String query ,
163
+ final Locale localeForLabels ) {
154
164
try {
155
165
final String url = "https://www.wikidata.org/w/api.php" +
156
166
"?action=wbsearchentities" +
@@ -167,7 +177,7 @@ public static List<WikidataEntry> getWikidataEntriesForQuery(final String langua
167
177
return getLabelForWikidata (r , localeForLabels );
168
178
}
169
179
} catch (Exception ex ) {
170
- throw new RuntimeException (ex );
180
+ throw new JosmRuntimeException (ex );
171
181
}
172
182
}
173
183
@@ -184,12 +194,12 @@ public List<WikipediaEntry> getEntriesFromCategory(String category, int depth) {
184
194
.collect (Collectors .toList ());
185
195
}
186
196
} catch (IOException ex ) {
187
- throw new RuntimeException (ex );
197
+ throw new UncheckedIOException (ex );
188
198
}
189
199
}
190
200
191
201
public static List <WikipediaEntry > getEntriesFromClipboard (final String wikipediaLang , String clipboardStringContent ) {
192
- if ("wikidata" .equals (wikipediaLang )) {
202
+ if (WIKIDATA .equals (wikipediaLang )) {
193
203
List <WikidataEntry > entries = new ArrayList <>();
194
204
Matcher matcher = RegexUtil .Q_ID_PATTERN .matcher (clipboardStringContent );
195
205
while (matcher .find ()) {
@@ -231,7 +241,7 @@ public void updateWIWOSMStatus(List<WikipediaEntry> entries) {
231
241
});
232
242
}
233
243
} catch (Exception ex ) {
234
- throw new RuntimeException (ex );
244
+ throw new JosmRuntimeException (ex );
235
245
}
236
246
}
237
247
for (WikipediaEntry i : entries ) {
@@ -240,15 +250,33 @@ public void updateWIWOSMStatus(List<WikipediaEntry> entries) {
240
250
}
241
251
242
252
public boolean hasWikipediaTag (final OsmPrimitive p ) {
243
- return p .hasKey ("wikidata" , "wikipedia" , "wikipedia:" + wikipediaLang );
253
+ return p .hasKey (wikipediaKeys );
254
+ }
255
+
256
+ /**
257
+ * Check to see if a tagged object has had its wikipedia tag change
258
+ * @param primitive The tagged object to check
259
+ * @param originalKeys The original keys
260
+ * @return {@code true} if the tagged object has had a change in wikipedia keys
261
+ */
262
+ public boolean tagChangeWikipedia (Tagged primitive , Map <String , String > originalKeys ) {
263
+ for (String key : wikipediaKeys ) {
264
+ // If the key has been added or removed, it has been changed.
265
+ if (primitive .hasKey (key ) != originalKeys .containsKey (key ) ||
266
+ // If the original key doesn't equal the new key, then it has been changed
267
+ (primitive .hasKey (key ) && originalKeys .containsKey (key ) && !originalKeys .get (key ).equals (primitive .get (key )))) {
268
+ return true ;
269
+ }
270
+ }
271
+ return false ;
244
272
}
245
273
246
274
public Stream <String > getWikipediaArticles (final OsmPrimitive p ) {
247
- if ("wikidata" .equals (wikipediaLang )) {
248
- return Stream .of (p .get ("wikidata" )).filter (Objects ::nonNull );
275
+ if (WIKIDATA .equals (wikipediaLang )) {
276
+ return Stream .of (p .get (WIKIDATA )).filter (Objects ::nonNull );
249
277
}
250
278
return Stream
251
- .of ("wikipedia" , "wikipedia:" + wikipediaLang )
279
+ .of (WIKIPEDIA , WIKIPEDIA + ':' + wikipediaLang )
252
280
.map (key -> WikipediaEntry .parseTag (key , p .get (key )))
253
281
.filter (Objects ::nonNull )
254
282
.filter (wp -> wikipediaLang .equals (wp .lang ))
@@ -263,9 +291,7 @@ public Stream<String> getWikipediaArticles(final OsmPrimitive p) {
263
291
public Map <String , String > getWikidataForArticles (Collection <String > articles ) {
264
292
final Map <String , String > result = new HashMap <>();
265
293
// maximum of 50 titles
266
- ListUtil .processInBatches (new ArrayList <>(articles ), 50 , batch -> {
267
- result .putAll (resolveWikidataItems (batch ));
268
- });
294
+ ListUtil .processInBatches (new ArrayList <>(articles ), 50 , batch -> result .putAll (resolveWikidataItems (batch )));
269
295
return result ;
270
296
}
271
297
@@ -321,10 +347,10 @@ private Map<String, String> getWikidataForArticles0(Collection<String> articles)
321
347
return ApiQueryClient .query (WikidataActionApiQuery .wbgetentities (site , articles ))
322
348
.getEntities ().values ()
323
349
.stream ()
324
- .filter (it -> RegexUtil .isValidQId (it .getId ()) && it .getSitelinks ().size () >= 1 )
350
+ .filter (it -> RegexUtil .isValidQId (it .getId ()) && ! it .getSitelinks ().isEmpty () )
325
351
.collect (Collectors .toMap (it -> it .getSitelinks ().iterator ().next ().getTitle (), WbgetentitiesResult .Entity ::getId ));
326
352
} catch (IOException ex ) {
327
- throw new RuntimeException (ex );
353
+ throw new UncheckedIOException (ex );
328
354
}
329
355
}
330
356
@@ -336,9 +362,10 @@ private Map<String, String> getWikidataForArticles0(Collection<String> articles)
336
362
*/
337
363
Map <String , String > resolveRedirectsForArticles (Collection <String > articles ) {
338
364
try {
339
- return articles .stream ().collect (Collectors .toMap (it -> it , ApiQueryClient .query (WikipediaActionApiQuery .query (site , articles )).getQuery ()::resolveRedirect ));
365
+ return articles .stream ().collect (Collectors .toMap (it -> it ,
366
+ ApiQueryClient .query (WikipediaActionApiQuery .query (site , articles )).getQuery ()::resolveRedirect ));
340
367
} catch (Exception ex ) {
341
- throw new RuntimeException (ex );
368
+ throw new JosmRuntimeException (ex );
342
369
}
343
370
}
344
371
@@ -359,21 +386,24 @@ public List<String> getCategoriesForPrefix(final String prefix) {
359
386
.collect (Collectors .toList ())
360
387
).orElse (new ArrayList <>());
361
388
} catch (IOException ex ) {
362
- throw new RuntimeException (ex );
389
+ throw new UncheckedIOException (ex );
363
390
}
364
391
}
365
392
366
393
public static String getLabelForWikidata (String wikidataId , Locale locale , String ... preferredLanguage ) {
367
394
try {
368
395
final List <WikidataEntry > entry = Collections .singletonList (new WikidataEntry (wikidataId ));
369
396
return getLabelForWikidata (entry , locale , preferredLanguage ).get (0 ).label ;
370
- } catch (IndexOutOfBoundsException ignore ) {
397
+ } catch (IndexOutOfBoundsException indexOutOfBoundsException ) {
398
+ Logging .trace (indexOutOfBoundsException );
371
399
return null ;
372
400
}
373
401
}
374
402
375
- static List <WikidataEntry > getLabelForWikidata (final List <? extends WikipediaEntry > entries , final Locale locale , final String ... preferredLanguage ) {
376
- final List <WikidataEntry > wdEntries = entries .stream ().map (it -> it instanceof WikidataEntry ? (WikidataEntry ) it : null ).filter (Objects ::nonNull ).collect (Collectors .toList ());
403
+ static List <WikidataEntry > getLabelForWikidata (final List <? extends WikipediaEntry > entries , final Locale locale ,
404
+ final String ... preferredLanguage ) {
405
+ final List <WikidataEntry > wdEntries = entries .stream ()
406
+ .map (it -> it instanceof WikidataEntry ? (WikidataEntry ) it : null ).filter (Objects ::nonNull ).collect (Collectors .toList ());
377
407
if (wdEntries .size () != entries .size ()) {
378
408
throw new IllegalArgumentException ("The entries given to method `getLabelForWikidata` must all be of type WikidataEntry!" );
379
409
}
@@ -389,7 +419,9 @@ static List<WikidataEntry> getLabelForWikidata(final List<? extends WikipediaEnt
389
419
final List <WikidataEntry > result = new ArrayList <>(wdEntries .size ());
390
420
ListUtil .processInBatches (wdEntries , 50 , batch -> {
391
421
try {
392
- final Map <String , Optional <WbgetentitiesResult .Entity >> entities = ApiQueryClient .query (WikidataActionApiQuery .wbgetentitiesLabels (batch .stream ().map (it -> it .article ).collect (Collectors .toList ())));
422
+ final Map <String , Optional <WbgetentitiesResult .Entity >> entities =
423
+ ApiQueryClient .query (WikidataActionApiQuery .wbgetentitiesLabels (batch .stream ().map (it -> it .article )
424
+ .collect (Collectors .toList ())));
393
425
if (entities != null ) {
394
426
for (final WikidataEntry batchEntry : batch ) {
395
427
Optional .ofNullable (entities .get (batchEntry .article )).flatMap (it -> it ).ifPresent (entity -> {
@@ -403,7 +435,7 @@ static List<WikidataEntry> getLabelForWikidata(final List<? extends WikipediaEnt
403
435
}
404
436
}
405
437
} catch (Exception ex ) {
406
- throw new RuntimeException (ex );
438
+ throw new JosmRuntimeException (ex );
407
439
}
408
440
});
409
441
return result ;
@@ -435,7 +467,7 @@ public Collection<WikipediaEntry> getInterwikiArticles(String article) {
435
467
}).collect (Collectors .toList ());
436
468
}
437
469
} catch (Exception ex ) {
438
- throw new RuntimeException (ex );
470
+ throw new JosmRuntimeException (ex );
439
471
}
440
472
}
441
473
@@ -456,7 +488,7 @@ public LatLon getCoordinateForArticle(String article) {
456
488
}
457
489
}
458
490
} catch (Exception ex ) {
459
- throw new RuntimeException (ex );
491
+ throw new JosmRuntimeException (ex );
460
492
}
461
493
}
462
494
@@ -482,7 +514,7 @@ private static DocumentBuilder newDocumentBuilder() {
482
514
} catch (ParserConfigurationException e ) {
483
515
Logging .warn ("Cannot create DocumentBuilder" );
484
516
Logging .warn (e );
485
- throw new RuntimeException (e );
517
+ throw new JosmRuntimeException (e );
486
518
}
487
519
}
488
520
}
0 commit comments