Changeset 32626 in osm for applications


Ignore:
Timestamp:
2016-07-10T22:57:01+02:00 (8 years ago)
Author:
simon04
Message:

JOSM/wikipedia: query Wikidata description - #josm12039

Location:
applications/editors/josm/plugins/wikipedia
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/wikipedia/src/org/wikipedia/WikidataItemSearchDialog.java

    r32625 r32626  
    1010import java.util.Collections;
    1111import java.util.List;
     12import java.util.Locale;
    1213import java.util.concurrent.Executors;
    1314import java.util.concurrent.TimeUnit;
     
    103104                    final List<WikipediaApp.WikidataEntry> entries = query == null || query.isEmpty()
    104105                            ? Collections.<WikipediaApp.WikidataEntry>emptyList()
    105                             : WikipediaApp.getWikidataEntriesForQuery(WikipediaToggleDialog.wikipediaLang.get(), query);
     106                            : WikipediaApp.getWikidataEntriesForQuery(WikipediaToggleDialog.wikipediaLang.get(), query, Locale.getDefault());
    106107                    GuiHelper.runInEDT(new Runnable() {
    107108                        @Override
  • applications/editors/josm/plugins/wikipedia/src/org/wikipedia/WikipediaApp.java

    r32625 r32626  
    2727import javax.xml.xpath.XPathConstants;
    2828import javax.xml.xpath.XPathExpression;
     29import javax.xml.xpath.XPathExpressionException;
    2930import javax.xml.xpath.XPathFactory;
    3031
     
    8687                final Document doc = DOCUMENT_BUILDER.parse(in);
    8788                final NodeList nodes = (NodeList) xpathPlacemark.evaluate(doc, XPathConstants.NODESET);
    88                 final List<String> names = new ArrayList<>(nodes.getLength());
    8989                final List<WikipediaEntry> entries = new ArrayList<>(nodes.getLength());
    9090                for (int i = 0; i < nodes.getLength(); i++) {
    9191                    final Node node = nodes.item(i);
    9292                    final String name = xpathName.evaluate(node);
    93                     names.add(name);
    9493                    final LatLon latLon = new LatLon((
    9594                            (double) xpathLat.evaluate(node, XPathConstants.NUMBER)),
    9695                            (double) xpathLon.evaluate(node, XPathConstants.NUMBER));
    9796                    if ("wikidata".equals(wikipediaLang)) {
    98                         entries.add(new WikidataEntry(name, null, latLon));
     97                        entries.add(new WikidataEntry(name, null, latLon, null));
    9998                    } else {
    10099                        entries.add(new WikipediaEntry(wikipediaLang, name, name, latLon
     
    103102                }
    104103                if ("wikidata".equals(wikipediaLang)) {
    105                     final Map<String, String> labels = new HashMap<>();
    106                     for (final List<String> chunk : partitionList(names, 50)) {
    107                         labels.putAll(getLabelForWikidata(chunk, Locale.getDefault()));
    108                     }
    109104                    final List<WikipediaEntry> entriesWithLabel = new ArrayList<>(nodes.getLength());
    110                     for (WikipediaEntry entry : entries) {
    111                         entriesWithLabel.add(new WikidataEntry(entry.wikipediaArticle, labels.get(entry.wikipediaArticle), entry.coordinate));
     105                    for (final List<WikipediaEntry> chunk : partitionList(entries, 50)) {
     106                        entriesWithLabel.addAll(getLabelForWikidata(chunk, Locale.getDefault()));
    112107                    }
    113108                    return entriesWithLabel;
     
    121116    }
    122117
    123     static List<WikidataEntry> getWikidataEntriesForQuery(final String language, final String query) {
     118    static List<WikidataEntry> getWikidataEntriesForQuery(final String languageForQuery, final String query, final Locale localeForLabels) {
    124119        try {
    125120            final String url = "https://www.wikidata.org/w/api.php" +
    126121                    "?action=wbsearchentities" +
    127                     "&language=" + language +
     122                    "&language=" + languageForQuery +
    128123                    "&strictlanguage=false" +
    129124                    "&search=" + Utils.encodeUrl(query) +
     
    135130                final NodeList nodes = (NodeList) X_PATH.compile("//entity").evaluate(xml, XPathConstants.NODESET);
    136131                final XPathExpression xpathId = X_PATH.compile("@id");
    137                 final XPathExpression xpathLabel = X_PATH.compile("@label");
    138132                for (int i = 0; i < nodes.getLength(); i++) {
    139133                    final Node node = nodes.item(i);
    140134                    final String id = (String) xpathId.evaluate(node, XPathConstants.STRING);
    141                     final String label = (String) xpathLabel.evaluate(node, XPathConstants.STRING);
    142                     r.add(new WikidataEntry(id, label, null));
    143                 }
    144             }
    145             return r;
     135                    r.add(new WikidataEntry(id, null, null, null));
     136                }
     137            }
     138            return getLabelForWikidata(r, localeForLabels);
    146139        } catch (Exception ex) {
    147140            throw new RuntimeException(ex);
     
    277270
    278271    static String getLabelForWikidata(String wikidataId, Locale locale, String ... preferredLanguage) {
    279         return getLabelForWikidata(Collections.singleton(wikidataId), locale, preferredLanguage).get(wikidataId);
    280     }
    281 
    282     static Map<String, String> getLabelForWikidata(Collection<String> wikidataIds, Locale locale, String ... preferredLanguage) {
    283         try {
    284             for (final String wikidataId : wikidataIds) {
    285                 ensureValidWikidataId(wikidataId);
    286             }
     272        try {
     273            return getLabelForWikidata(Collections.singleton(new WikidataEntry(wikidataId, null, null, null)), locale, preferredLanguage).get(0).label;
     274        } catch (IndexOutOfBoundsException ignore) {
     275            return null;
     276        }
     277    }
     278
     279    static List<WikidataEntry> getLabelForWikidata(Collection<? extends WikipediaEntry> entries, Locale locale, String ... preferredLanguage) {
     280        final Collection<String> wikidataIds = Utils.transform(entries, new Function<WikipediaEntry, String>() {
     281            @Override
     282            public String apply(WikipediaEntry x) {
     283                return x.wikipediaArticle;
     284            }
     285        });
     286        try {
    287287            final String url = "https://www.wikidata.org/w/api.php" +
    288288                    "?action=wbgetentities" +
    289                     "&props=labels" +
     289                    "&props=labels|descriptions" +
    290290                    "&ids=" + Utils.join("|", wikidataIds) +
    291291                    "&format=xml";
     
    298298            languages.add("en");
    299299            languages.add(null);
    300             final Map<String, String> r = new HashMap<>();
     300            final List<WikidataEntry> r = new ArrayList<>(entries.size());
    301301            try (final InputStream in = HttpClient.create(new URL(url)).setReasonForRequest("Wikipedia").connect().getContent()) {
    302302                final Document xml = DOCUMENT_BUILDER.parse(in);
    303                 for (final String wikidataId : wikidataIds) {
    304                     final Node entity = (Node) X_PATH.compile("//entity[@id='" + wikidataId + "']").evaluate(xml, XPathConstants.NODE);
    305                     for (String language : languages) {
    306                         final String label = (String) X_PATH.compile(language != null
    307                                 ? "./labels/label[@language='" + language + "']/@value"
    308                                 : "./labels/label/@value"
    309                         ).evaluate(entity, XPathConstants.STRING);
    310                         if (label != null && !label.isEmpty()) {
    311                             r.put(wikidataId, label);
    312                             break;
    313                         }
    314                     }
     303                for (final WikipediaEntry entry : entries) {
     304                    final Node entity = (Node) X_PATH.compile("//entity[@id='" + entry.wikipediaArticle + "']").evaluate(xml, XPathConstants.NODE);
     305                    r.add(new WikidataEntry(
     306                            entry.wikipediaArticle,
     307                            getFirstField(languages, "label", entity),
     308                            entry.coordinate,
     309                            getFirstField(languages, "description", entity)
     310                    ));
    315311                }
    316312            }
     
    319315            throw new RuntimeException(ex);
    320316        }
     317    }
     318
     319    private static String getFirstField(Iterable<String> languages, String field, Node entity) throws XPathExpressionException {
     320        for (String language : languages) {
     321            final String label = (String) X_PATH.compile(language != null
     322                    ? ".//" + field + "[@language='" + language + "']/@value"
     323                    : ".//" + field + "/@value"
     324            ).evaluate(entity, XPathConstants.STRING);
     325            if (label != null && !label.isEmpty()) {
     326                return label;
     327            }
     328        }
     329        return null;
    321330    }
    322331
     
    486495    static class WikidataEntry extends WikipediaEntry {
    487496
    488         WikidataEntry(String id, String label, LatLon coordinate) {
     497        final String description;
     498
     499        WikidataEntry(String id, String label, LatLon coordinate, String description) {
    489500            super("wikidata", id, label, coordinate);
     501            this.description = description;
    490502            ensureValidWikidataId(id);
    491503        }
     
    498510        @Override
    499511        public String getLabelText() {
    500             return getLabelText(label, wikipediaArticle);
     512            final String descriptionInParen = description == null ? "" : (" (" + description + ")");
     513            return getLabelText(label, wikipediaArticle + descriptionInParen);
    501514        }
    502515
  • applications/editors/josm/plugins/wikipedia/test/unit/org/wikipedia/WikipediaAppTest.java

    r32625 r32626  
    151151    @Test
    152152    public void testForQuery() throws Exception {
    153         final List<WikipediaApp.WikidataEntry> entries = WikipediaApp.getWikidataEntriesForQuery("de", "Österreich");
    154         assertThat(entries.get(0).wikipediaArticle, is("Q40"));
    155         assertThat(entries.get(0).wikipediaLang, is("wikidata"));
    156         // assertThat(entries.get(0).label, is("Österreich"));
     153        final List<WikipediaApp.WikidataEntry> de = WikipediaApp.getWikidataEntriesForQuery("de", "Österreich", Locale.GERMAN);
     154        final List<WikipediaApp.WikidataEntry> en = WikipediaApp.getWikidataEntriesForQuery("de", "Österreich", Locale.ENGLISH);
     155        assertThat(de.get(0).wikipediaArticle, is("Q40"));
     156        assertThat(de.get(0).wikipediaLang, is("wikidata"));
     157        assertThat(de.get(0).label, is("Österreich"));
     158        assertThat(de.get(0).description, is("Staat in Mitteleuropa"));
     159        assertThat(en.get(0).label, is("Austria"));
     160        assertThat(en.get(0).description, is("country in Central Europe"));
    157161    }
    158162
     
    188192        // not found -> null
    189193        assertThat(WikipediaApp.getLabelForWikidata("Q" + Long.MAX_VALUE, Locale.ENGLISH), nullValue());
    190         final Map<String, String> twoLabels = WikipediaApp.getLabelForWikidata(Arrays.asList("Q84", "Q1741"), Locale.GERMAN);
    191         assertThat(twoLabels.get("Q84"), is("London"));
    192         assertThat(twoLabels.get("Q1741"), is("Wien"));
     194        final WikipediaApp.WikidataEntry q84 = new WikipediaApp.WikidataEntry("Q84", null, null, null);
     195        final WikipediaApp.WikidataEntry q1741 = new WikipediaApp.WikidataEntry("Q1741", null, null, null);
     196        final List<WikipediaApp.WikidataEntry> twoLabels = WikipediaApp.getLabelForWikidata(Arrays.asList(q84, q1741), Locale.GERMAN);
     197        assertThat(twoLabels.get(0).label, is("London"));
     198        assertThat(twoLabels.get(1).label, is("Wien"));
    193199    }
    194200
Note: See TracChangeset for help on using the changeset viewer.