...
 
Commits (3)
......@@ -38,7 +38,7 @@ import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.wikipedia.api.ApiQueryClient;
import org.wikipedia.api.wikidata_action.WikidataActionApiQuery;
import org.wikipedia.api.wikidata_action.json.CheckEntityExistsResult;
import org.wikipedia.api.wikidata_action.json.WbgetentitiesResult;
import org.wikipedia.data.WikidataEntry;
import org.wikipedia.data.WikipediaEntry;
import org.wikipedia.tools.ListUtil;
......@@ -295,7 +295,7 @@ public final class WikipediaApp {
.getEntities().values()
.stream()
.filter(it -> RegexUtil.isValidQId(it.getId()) && it.getSitelinks().size() >= 1)
.collect(Collectors.toMap(it -> it.getSitelinks().iterator().next().getTitle(), CheckEntityExistsResult.Entity::getId));
.collect(Collectors.toMap(it -> it.getSitelinks().iterator().next().getTitle(), WbgetentitiesResult.Entity::getId));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
......
package org.wikipedia.api;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.function.Function;
import org.openstreetmap.josm.tools.HttpClient;
import org.openstreetmap.josm.tools.Utils;
import org.wikipedia.WikipediaPlugin;
public abstract class ApiQuery<T> {
private final SerializationSchema<T> schema;
private final URL url;
private final long cacheExpiryTime;
private final IOExceptionFunction<InputStream, T> deserializeFunc;
protected ApiQuery(final URL url, final SerializationSchema<T> schema, final long cacheExpiryTime) {
this.schema = schema;
protected <S> ApiQuery(final URL url, final SerializationSchema<S> schema, final long cacheExpiryTime, final Function<S, T> resultConverter) {
this.url = url;
this.deserializeFunc = stream -> resultConverter.apply(schema.getMapper().readValue(stream, schema.getSchemaClass()));
if (cacheExpiryTime >= 1) {
this.cacheExpiryTime = cacheExpiryTime;
} else {
......@@ -20,6 +23,14 @@ public abstract class ApiQuery<T> {
}
}
protected ApiQuery(final URL url, final SerializationSchema<T> schema, final long cacheExpiryTime) {
this(url, schema, cacheExpiryTime, it -> it);
}
protected ApiQuery(final URL url, final SerializationSchema<T> schema) {
this(url, schema, -1);
}
/**
* @return the number of milliseconds for which the API response should be retrieved
* from the cache without trying to get it directly from the API
......@@ -41,11 +52,8 @@ public abstract class ApiQuery<T> {
public abstract HttpClient getHttpClient();
/**
* @return the schema that is used to get from the JSON encoded response to its Java representation
*/
public final SerializationSchema<T> getSchema() {
return schema;
public final T deserialize(final InputStream stream) throws IOException {
return deserializeFunc.apply(stream);
}
/**
......@@ -67,4 +75,8 @@ public abstract class ApiQuery<T> {
return result + Utils.encodeUrl(" " + String.join(" ", keywords));
}
@FunctionalInterface
private interface IOExceptionFunction<T, R> {
R apply(T t) throws IOException;
}
}
......@@ -45,10 +45,7 @@ public final class ApiQueryClient {
final String remoteResponse = new String(IOUtils.toByteArray(getInputStreamForQuery(query)), StandardCharsets.UTF_8);
Caches.API_RESPONSES.put(query.getCacheKey(), remoteResponse);
Logging.info("Successfully updated API cache for " + query.getCacheKey());
return query.getSchema().getMapper().readValue(
new ByteArrayInputStream(remoteResponse.getBytes(StandardCharsets.UTF_8)),
query.getSchema().getSchemaClass()
);
return query.deserialize(new ByteArrayInputStream(remoteResponse.getBytes(StandardCharsets.UTF_8)));
} catch (IOException e) {
if (cachedValue == null) {
throw wrapReadDecodeJsonExceptions(e, query.getApiName());
......@@ -64,7 +61,7 @@ public final class ApiQueryClient {
}
try {
return query.getSchema().getMapper().readValue(stream, query.getSchema().getSchemaClass());
return query.deserialize(stream);
} catch (IOException e) {
throw wrapReadDecodeJsonExceptions(e, query.getApiName());
}
......
......@@ -19,7 +19,7 @@ public class WdqApiQuery<T> extends ApiQuery<T> {
private final String queryString;
public WdqApiQuery(final URL url, final String queryString, final SerializationSchema<T> schema) {
super(url, schema, -1);
super(url, schema);
this.queryString = Objects.requireNonNull(queryString);
}
......
......@@ -3,13 +3,16 @@ package org.wikipedia.api.wikidata_action;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.openstreetmap.josm.tools.HttpClient;
import org.openstreetmap.josm.tools.Utils;
import org.wikipedia.api.ApiQuery;
import org.wikipedia.api.ApiUrl;
import org.wikipedia.api.SerializationSchema;
import org.wikipedia.api.wikidata_action.json.CheckEntityExistsResult;
import org.wikipedia.api.wikidata_action.json.SitematrixResult;
import org.wikipedia.api.wikidata_action.json.WbgetentitiesResult;
import org.wikipedia.tools.RegexUtil;
public final class WikidataActionApiQuery<T> extends ApiQuery<T> {
......@@ -17,19 +20,24 @@ public final class WikidataActionApiQuery<T> extends ApiQuery<T> {
private static final String FORMAT_PARAMS = "format=json&utf8=1&formatversion=1";
private static final String[] TICKET_KEYWORDS = {"wikidata", "ActionAPI"};
private final String query;
private final String queryString;
private WikidataActionApiQuery(final String query, final SerializationSchema<T> schema, final long cacheExpiryTime) {
super(defaultUrl, schema, cacheExpiryTime);
this.query = query;
this.queryString = query;
}
private WikidataActionApiQuery(final String query, final SerializationSchema<T> schema) {
this(query, schema, -1);
}
public String getQuery() {
return query;
private <S> WikidataActionApiQuery(final String queryString, final SerializationSchema<S> schema, final Function<S, T> converter) {
super(defaultUrl, schema, -1, converter);
this.queryString = queryString;
}
public String getQueryString() {
return queryString;
}
public static WikidataActionApiQuery<SitematrixResult> sitematrix() {
......@@ -40,7 +48,7 @@ public final class WikidataActionApiQuery<T> extends ApiQuery<T> {
);
}
public static WikidataActionApiQuery<CheckEntityExistsResult> wbgetentities(final Collection<String> qIds) {
public static WikidataActionApiQuery<WbgetentitiesResult> wbgetentities(final Collection<String> qIds) {
if (qIds.size() < 1) {
throw new IllegalArgumentException("You must supply at least one Q-ID to construct a checkEntityExists URL.");
}
......@@ -49,11 +57,11 @@ public final class WikidataActionApiQuery<T> extends ApiQuery<T> {
}
return new WikidataActionApiQuery<>(
FORMAT_PARAMS + "&action=wbgetentities&sites=&props=&ids=" + Utils.encodeUrl(String.join("|", qIds)),
CheckEntityExistsResult.SCHEMA
WbgetentitiesResult.SCHEMA
);
}
public static WikidataActionApiQuery<CheckEntityExistsResult> wbgetentities(final String siteId, final Collection<String> titles) {
public static WikidataActionApiQuery<WbgetentitiesResult> wbgetentities(final String siteId, final Collection<String> titles) {
if (siteId == null || titles == null || titles.size() <= 0) {
throw new IllegalArgumentException("The site ID and titles must be present!");
}
......@@ -64,13 +72,24 @@ public final class WikidataActionApiQuery<T> extends ApiQuery<T> {
FORMAT_PARAMS + "&action=wbgetentities&props=sitelinks&sites=" + siteId + // defines the language of the titles
"&sitefilter=" + siteId + // defines for which languages sitelinks should be returned
"&titles=" + Utils.encodeUrl(String.join("|", titles)),
CheckEntityExistsResult.SCHEMA
WbgetentitiesResult.SCHEMA
);
}
public static WikidataActionApiQuery<Map<String, String>> wbgetentitiesLabels(final String qId) {
if (!RegexUtil.isValidQId(qId)) {
throw new IllegalArgumentException("Invalid Q-ID: " + qId);
}
return new WikidataActionApiQuery<>(
FORMAT_PARAMS + "&action=wbgetentities&props=labels&ids=" + qId,
WbgetentitiesResult.SCHEMA,
result -> result.getEntities().values().stream().findFirst().map(WbgetentitiesResult.Entity::getLabels).orElse(new HashMap<>())
);
}
@Override
public String getCacheKey() {
return getUrl().toString() + '?' + getQuery();
return getUrl().toString() + '?' + getQueryString();
}
@Override
......@@ -84,7 +103,7 @@ public final class WikidataActionApiQuery<T> extends ApiQuery<T> {
.setAccept("application/json")
.setHeader("Content-Type", "text/plain; charset=utf-8")
.setHeader("User-Agent", getUserAgent(TICKET_KEYWORDS))
.setReasonForRequest(getQuery().replace('&', ' '))
.setRequestBody(getQuery().getBytes(StandardCharsets.UTF_8));
.setReasonForRequest(getQueryString().replace('&', ' '))
.setRequestBody(getQueryString().getBytes(StandardCharsets.UTF_8));
}
}
......@@ -16,18 +16,19 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.wikipedia.api.SerializationSchema;
public final class CheckEntityExistsResult {
public static final SerializationSchema<CheckEntityExistsResult> SCHEMA = new SerializationSchema<>(
CheckEntityExistsResult.class,
public final class WbgetentitiesResult {
public static final SerializationSchema<WbgetentitiesResult> SCHEMA = new SerializationSchema<>(
WbgetentitiesResult.class,
it -> {
it.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
it.registerModule(new SimpleModule().addDeserializer(
CheckEntityExistsResult.AbstractEntity.class,
new CheckEntityExistsResult.AbstractEntity.Deserializer(it)
WbgetentitiesResult.AbstractEntity.class,
new WbgetentitiesResult.AbstractEntity.Deserializer(it)
));
}
);
......@@ -37,7 +38,7 @@ public final class CheckEntityExistsResult {
private final List<MissingEntity> missingEntities = new ArrayList<>();
@JsonCreator
public CheckEntityExistsResult(@JsonProperty("success") final int success, @JsonProperty("entities") final Map<String, AbstractEntity> entities) {
public WbgetentitiesResult(@JsonProperty("success") final int success, @JsonProperty("entities") final Map<String, AbstractEntity> entities) {
this.success = success;
for (final Map.Entry<String, AbstractEntity> entry : entities.entrySet()) {
entry.getValue().addTo(entry.getKey(), this);
......@@ -72,12 +73,12 @@ public final class CheckEntityExistsResult {
*/
public interface AbstractEntity {
/**
* Adds this entity to the entity lists/maps of {@link CheckEntityExistsResult}, depending on the implementing
* Adds this entity to the entity lists/maps of {@link WbgetentitiesResult}, depending on the implementing
* class it can vary to which list or map the entity is added.
* @param key the key to which the entity is associated in the JSON
* @param result the object to which the entity should be added
*/
void addTo(final String key, CheckEntityExistsResult result);
void addTo(final String key, WbgetentitiesResult result);
class Deserializer extends StdDeserializer<AbstractEntity> {
private final ObjectMapper mapper;
......@@ -127,7 +128,7 @@ public final class CheckEntityExistsResult {
}
@Override
public void addTo(final String key, final CheckEntityExistsResult result) {
public void addTo(final String key, final WbgetentitiesResult result) {
result.missingEntities.add(this);
}
}
......@@ -136,18 +137,23 @@ public final class CheckEntityExistsResult {
private final String id;
private final String type;
private final Map<String, Sitelink> sitelinks = new HashMap<>();
private final Map<String, String> labels = new HashMap<>();
@JsonCreator
public Entity(
@JsonProperty("id") final String id,
@JsonProperty("type") final String type,
@JsonProperty("sitelinks") final Map<String, Sitelink> sitelinks
@JsonProperty("sitelinks") final Map<String, Sitelink> sitelinks,
@JsonProperty("labels") final Map<String, Label> labels
) {
this.id = id;
this.type = type;
if (sitelinks != null) {
this.sitelinks.putAll(sitelinks);
}
if (labels != null) {
labels.values().forEach(label -> this.labels.put(label.getLanguage(), label.getValue()));
}
}
public String getId() {
......@@ -158,15 +164,38 @@ public final class CheckEntityExistsResult {
return type;
}
public Map<String, String> getLabels() {
return Collections.unmodifiableMap(labels);
}
public Collection<Sitelink> getSitelinks() {
return Collections.unmodifiableCollection(sitelinks.values());
}
@Override
public void addTo(final String key, final CheckEntityExistsResult result) {
public void addTo(final String key, final WbgetentitiesResult result) {
result.entities.put(key, this);
}
public static final class Label {
private final String language;
private final String value;
@JsonCreator
public Label(@JsonProperty("language") final String language, @JsonProperty("value") final String value) {
this.language = language;
this.value = value;
}
public String getLanguage() {
return language;
}
public String getValue() {
return value;
}
}
public static final class Sitelink {
private final String site;
private final String title;
......
......@@ -20,7 +20,7 @@ public class WikipediaActionApiQuery<T> extends ApiQuery<T> {
private final String queryString;
private WikipediaActionApiQuery(final IWikipediaSite site, final String queryString, SerializationSchema<T> schema) {
super(ApiUrl.url(site.getSite().getUrl(), "/w/api.php"), schema, -1);
super(ApiUrl.url(site.getSite().getUrl(), "/w/api.php"), schema);
this.queryString = Objects.requireNonNull(queryString);
}
......
......@@ -15,7 +15,7 @@ import org.openstreetmap.josm.tools.I18n;
import org.wikipedia.WikipediaPlugin;
import org.wikipedia.api.ApiQueryClient;
import org.wikipedia.api.wikidata_action.WikidataActionApiQuery;
import org.wikipedia.api.wikidata_action.json.CheckEntityExistsResult;
import org.wikipedia.api.wikidata_action.json.WbgetentitiesResult;
import org.wikipedia.tools.ListUtil;
import org.wikipedia.tools.RegexUtil;
......@@ -43,7 +43,7 @@ public class WikidataItemExists extends BatchProcessedTagTest<WikidataItemExists
protected void check(List<TestCompanion> allPrimitives) {
ListUtil.processInBatches(allPrimitives, BATCH_SIZE, primitiveBatch -> {
try {
final CheckEntityExistsResult entityQueryResult = ApiQueryClient.query(
final WbgetentitiesResult entityQueryResult = ApiQueryClient.query(
WikidataActionApiQuery.wbgetentities(primitiveBatch.stream().map(tc -> tc.wikidataId).collect(Collectors.toList()))
);
if (entityQueryResult.getSuccess() != 1) {
......@@ -69,12 +69,12 @@ public class WikidataItemExists extends BatchProcessedTagTest<WikidataItemExists
}
/**
* Checks an {@link OsmPrimitive} against a given {@link CheckEntityExistsResult}.
* Checks an {@link OsmPrimitive} against a given {@link WbgetentitiesResult}.
* @param tc the test companion for the {@link OsmPrimitive}
* @param entityQueryResult the result from the Wikidata Action API
*/
private void check(final TestCompanion tc, final CheckEntityExistsResult entityQueryResult) {
final CheckEntityExistsResult.Entity entity = entityQueryResult.getEntities().get(tc.wikidataId);
private void check(final TestCompanion tc, final WbgetentitiesResult entityQueryResult) {
final WbgetentitiesResult.Entity entity = entityQueryResult.getEntities().get(tc.wikidataId);
if (entityQueryResult.getMissingEntities().stream().anyMatch(it -> tc.wikidataId.equals(it.getId()))) {
errors.add(
AllValidationTests.WIKIDATA_ITEM_DOES_NOT_EXIST.getBuilder(this)
......
......@@ -17,7 +17,7 @@ import org.openstreetmap.josm.tools.Pair;
import org.wikipedia.WikipediaPlugin;
import org.wikipedia.api.ApiQueryClient;
import org.wikipedia.api.wikidata_action.WikidataActionApiQuery;
import org.wikipedia.api.wikidata_action.json.CheckEntityExistsResult;
import org.wikipedia.api.wikidata_action.json.WbgetentitiesResult;
import org.wikipedia.tools.ListUtil;
import org.wikipedia.tools.RegexUtil;
......@@ -66,7 +66,7 @@ public class WikipediaAgainstWikidata extends BatchProcessedTagTest<WikipediaAga
private void checkBatch(final String language, final List<TestCompanion> primitiveBatch) {
try {
final Map<String, CheckEntityExistsResult.Entity.Sitelink> sitelinks = ApiQueryClient
final Map<String, WbgetentitiesResult.Entity.Sitelink> sitelinks = ApiQueryClient
.query(WikidataActionApiQuery.wbgetentities(
language + "wiki",
primitiveBatch.stream().map(it -> it.title).collect(Collectors.toList())
......
{"entities":{"Q42":{"type":"item","id":"Q42","labels":{"fr":{"language":"fr","value":"Douglas Adams"},"ru":{"language":"ru","value":"\u0414\u0443\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"pl":{"language":"pl","value":"Douglas Adams"},"it":{"language":"it","value":"Douglas Adams"},"en-gb":{"language":"en-gb","value":"Douglas Adams"},"nb":{"language":"nb","value":"Douglas Adams"},"es":{"language":"es","value":"Douglas Adams"},"en-ca":{"language":"en-ca","value":"Douglas Adams"},"hr":{"language":"hr","value":"Douglas Adams"},"pt":{"language":"pt","value":"Douglas Adams"},"ko":{"language":"ko","value":"\ub354\uae00\ub7ec\uc2a4 \uc560\ub364\uc2a4"},"nl":{"language":"nl","value":"Douglas Adams"},"el":{"language":"el","value":"\u039d\u03c4\u03ac\u03b3\u03ba\u03bb\u03b1\u03c2 \u0386\u03bd\u03c4\u03b1\u03bc\u03c2"},"ar":{"language":"ar","value":"\u062f\u0648\u063a\u0644\u0627\u0633 \u0622\u062f\u0645\u0632"},"arz":{"language":"arz","value":"\u062f\u0648\u062c\u0644\u0627\u0633 \u0627\u062f\u0627\u0645\u0632"},"bar":{"language":"bar","value":"Douglas Adams"},"be":{"language":"be","value":"\u0414\u0443\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"bg":{"language":"bg","value":"\u0414\u044a\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"bs":{"language":"bs","value":"Douglas Adams"},"ca":{"language":"ca","value":"Douglas Adams"},"cs":{"language":"cs","value":"Douglas Adams"},"cy":{"language":"cy","value":"Douglas Adams"},"da":{"language":"da","value":"Douglas Adams"},"eo":{"language":"eo","value":"Douglas Adams"},"et":{"language":"et","value":"Douglas Adams"},"fa":{"language":"fa","value":"\u062f\u0627\u06af\u0644\u0627\u0633 \u0622\u062f\u0627\u0645\u0632"},"fi":{"language":"fi","value":"Douglas Adams"},"ga":{"language":"ga","value":"Douglas Adams"},"gl":{"language":"gl","value":"Douglas Adams"},"he":{"language":"he","value":"\u05d3\u05d0\u05d2\u05dc\u05e1 \u05d0\u05d3\u05de\u05e1"},"hu":{"language":"hu","value":"Douglas Adams"},"id":{"language":"id","value":"Douglas Adams"},"io":{"language":"io","value":"Douglas Adams"},"is":{"language":"is","value":"Douglas Adams"},"ja":{"language":"ja","value":"\u30c0\u30b0\u30e9\u30b9\u30fb\u30a2\u30c0\u30e0\u30ba"},"jv":{"language":"jv","value":"Douglas Adams"},"ka":{"language":"ka","value":"\u10d3\u10d0\u10d2\u10da\u10d0\u10e1 \u10d0\u10d3\u10d0\u10db\u10e1\u10d8"},"la":{"language":"la","value":"Duglassius Adams"},"lv":{"language":"lv","value":"Duglass Adamss"},"mk":{"language":"mk","value":"\u0414\u0430\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"mr":{"language":"mr","value":"\u0921\u0917\u094d\u0932\u0938 \u0905\u0945\u0921\u092e\u094d\u0938"},"nn":{"language":"nn","value":"Douglas Adams"},"ro":{"language":"ro","value":"Douglas Adams"},"sco":{"language":"sco","value":"Douglas Adams"},"sh":{"language":"sh","value":"Douglas Adams"},"sk":{"language":"sk","value":"Douglas Adams"},"sl":{"language":"sl","value":"Douglas Adams"},"sq":{"language":"sq","value":"Douglas Adams"},"sr":{"language":"sr","value":"\u0414\u0430\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"sv":{"language":"sv","value":"Douglas Adams"},"ta":{"language":"ta","value":"\u0b9f\u0b95\u0bcd\u0bb3\u0bb8\u0bcd \u0b86\u0b9f\u0bae\u0bcd\u0bb8\u0bcd"},"tr":{"language":"tr","value":"Douglas Adams"},"uk":{"language":"uk","value":"\u0414\u0443\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"vi":{"language":"vi","value":"Douglas Adams"},"zh":{"language":"zh","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9a\u5f53\u65af"},"zh-cn":{"language":"zh-cn","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9a\u5f53\u65af"},"zh-hans":{"language":"zh-hans","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9a\u5f53\u65af"},"zh-hant":{"language":"zh-hant","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9e\u7576\u65af"},"de-ch":{"language":"de-ch","value":"Douglas Adams"},"pt-br":{"language":"pt-br","value":"Douglas Adams"},"zh-sg":{"language":"zh-sg","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9a\u5f53\u65af"},"zh-my":{"language":"zh-my","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9a\u5f53\u65af"},"zh-hk":{"language":"zh-hk","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9e\u7576\u65af"},"zh-tw":{"language":"zh-tw","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9e\u7576\u65af"},"zh-mo":{"language":"zh-mo","value":"\u9053\u683c\u62c9\u65af\u00b7\u4e9e\u7576\u65af"},"war":{"language":"war","value":"Douglas Adams"},"be-tarask":{"language":"be-tarask","value":"\u0414\u0443\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0437"},"vep":{"language":"vep","value":"Adams Duglas"},"ur":{"language":"ur","value":"\u0688\u06af\u0644\u0633 \u0627\u06cc\u0688\u0645"},"oc":{"language":"oc","value":"Douglas Adams"},"af":{"language":"af","value":"Douglas Adams"},"an":{"language":"an","value":"Douglas Adams"},"br":{"language":"br","value":"Douglas Adams"},"eu":{"language":"eu","value":"Douglas Adams"},"lb":{"language":"lb","value":"Douglas Adams"},"lmo":{"language":"lmo","value":"Douglas Adams"},"lt":{"language":"lt","value":"Douglas Adams"},"nds":{"language":"nds","value":"Douglas Adams"},"nds-nl":{"language":"nds-nl","value":"Douglas Adams"},"pms":{"language":"pms","value":"Douglas Adams"},"vec":{"language":"vec","value":"Douglas Adams"},"wa":{"language":"wa","value":"Douglas Adams"},"sr-ec":{"language":"sr-ec","value":"\u0414\u0430\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"},"sr-el":{"language":"sr-el","value":"Daglas Adams"},"de":{"language":"de","value":"Douglas Adams"},"ckb":{"language":"ckb","value":"\u062f\u06d5\u06af\u0644\u0627\u0633 \u0626\u0627\u062f\u0645\u0632"},"fo":{"language":"fo","value":"Douglas Adams"},"kl":{"language":"kl","value":"Douglas Adams"},"gsw":{"language":"gsw","value":"Douglas Adams"},"te":{"language":"te","value":"\u0c21\u0c17\u0c4d\u0c32\u0c38\u0c4d \u0c06\u0c21\u0c2e\u0c4d\u0c38\u0c4d"},"si":{"language":"si","value":"\u0da9\u0d9c\u0dca\u0dbd\u0dc3\u0dca \u0d87\u0da9\u0db8\u0dca\u0dc3\u0dca"},"bn":{"language":"bn","value":"\u09a1\u0997\u09b2\u09be\u09b8 \u0985\u09cd\u09af\u09be\u09a1\u09be\u09ae\u09b8"},"hi":{"language":"hi","value":"\u0921\u0917\u094d\u0932\u0938 \u0905\u200d\u0921\u092e\u094d\u0938"},"rwr":{"language":"rwr","value":"\u0921\u0917\u094d\u0932\u0938 \u0905\u200d\u0921\u092e\u094d\u0938"},"mg":{"language":"mg","value":"Douglas Adams"},"ml":{"language":"ml","value":"\u0d21\u0d17\u0d4d\u0d32\u0d38\u0d4d \u0d06\u0d21\u0d02\u0d38\u0d4d"},"gu":{"language":"gu","value":"\u0aa1\u0a97\u0acd\u0ab2\u0abe\u0ab8 \u0a8f\u0aa1\u0aae\u0acd\u0ab8"},"hy":{"language":"hy","value":"\u0534\u0578\u0582\u0563\u056c\u0561\u057d \u0531\u0564\u0561\u0574\u057d"},"ast":{"language":"ast","value":"Douglas Adams"},"co":{"language":"co","value":"Douglas Adams"},"de-at":{"language":"de-at","value":"Douglas Adams"},"frp":{"language":"frp","value":"Douglas Adams"},"fur":{"language":"fur","value":"Douglas Adams"},"gd":{"language":"gd","value":"Douglas Adams"},"ia":{"language":"ia","value":"Douglas Adams"},"ie":{"language":"ie","value":"Douglas Adams"},"kg":{"language":"kg","value":"Douglas Adams"},"li":{"language":"li","value":"Douglas Adams"},"lij":{"language":"lij","value":"Douglas Adams"},"min":{"language":"min","value":"Douglas Adams"},"ms":{"language":"ms","value":"Douglas Adams"},"nap":{"language":"nap","value":"Douglas Adams"},"nrm":{"language":"nrm","value":"Douglas Adams"},"pcd":{"language":"pcd","value":"Douglas Adams"},"rm":{"language":"rm","value":"Douglas Adams"},"sc":{"language":"sc","value":"Douglas Adams"},"scn":{"language":"scn","value":"Douglas Adams"},"sw":{"language":"sw","value":"Douglas Adams"},"vls":{"language":"vls","value":"Douglas Adams"},"vo":{"language":"vo","value":"Douglas Adams"},"wo":{"language":"wo","value":"Douglas Adams"},"zu":{"language":"zu","value":"Douglas Adams"},"az":{"language":"az","value":"Duqlas Noel Adams"},"ak":{"language":"ak","value":"Doglas Adams"},"or":{"language":"or","value":"\u0b21\u0b17\u0b4d\u200c\u0b32\u0b3e\u0b38\u0b4d\u200c \u0b06\u0b26\u0b3e\u0b2e\u0b4d\u200c\u0b38"},"kn":{"language":"kn","value":"\u0ca1\u0c97\u0ccd\u0cb2\u0cb8\u0ccd \u0c86\u0ca1\u0cae\u0ccd\u0cb8\u0ccd"},"ne":{"language":"ne","value":"\u0921\u0917\u0932\u0938 \u090f\u0921\u092e\u094d\u0938"},"mrj":{"language":"mrj","value":"\u0410\u0434\u0430\u043c\u0441"},"th":{"language":"th","value":"\u0e14\u0e31\u0e4a\u0e01\u0e25\u0e32\u0e2a \u0e2d\u0e14\u0e31\u0e21\u0e2a\u0e4c"},"pa":{"language":"pa","value":"\u0a21\u0a17\u0a32\u0a38 \u0a10\u0a21\u0a2e\u0a1c\u0a3c"},"tcy":{"language":"tcy","value":"\u0ca1\u0cbe\u0c97\u0ccd\u0cb2\u0cb8\u0ccd \u0c86\u0ca1\u0cae\u0ccd\u0cb8\u0ccd"},"tl":{"language":"tl","value":"Douglas Adams"},"ext":{"language":"ext","value":"Douglas Adams"},"azb":{"language":"azb","value":"\u062f\u0627\u0642\u0644\u0627\u0633 \u0622\u062f\u0627\u0645\u0632"},"en":{"language":"en","value":"Douglas Adams"},"lfn":{"language":"lfn","value":"Douglas Adams"},"nan":{"language":"nan","value":"Douglas Adams"},"ky":{"language":"ky","value":"\u0414\u0443\u0433\u043b\u0430\u0441 \u0410\u0434\u0430\u043c\u0441"}}}},"success":1}
\ No newline at end of file
......@@ -28,7 +28,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.openstreetmap.josm.testutils.JOSMTestRules;
import org.wikipedia.api.ApiQueryClient;
import org.wikipedia.api.wikidata_action.json.CheckEntityExistsResult;
import org.wikipedia.api.wikidata_action.json.WbgetentitiesResult;
import org.wikipedia.testutils.ResourceFileLoader;
public class WikidataActionApiQueryTest {
......@@ -74,11 +74,11 @@ public class WikidataActionApiQueryTest {
public void testWbgetentitiesQuery() {
assertEquals(
"format=json&utf8=1&formatversion=1&action=wbgetentities&sites=&props=&ids=Q1",
WikidataActionApiQuery.wbgetentities(Collections.singletonList("Q1")).getQuery()
WikidataActionApiQuery.wbgetentities(Collections.singletonList("Q1")).getQueryString()
);
assertEquals(
"format=json&utf8=1&formatversion=1&action=wbgetentities&sites=&props=&ids=Q1%7CQ13%7CQ24%7CQ20150617%7CQ42%7CQ12345",
WikidataActionApiQuery.wbgetentities(Arrays.asList("Q1", "Q13", "Q24", "Q20150617", "Q42", "Q12345")).getQuery()
WikidataActionApiQuery.wbgetentities(Arrays.asList("Q1", "Q13", "Q24", "Q20150617", "Q42", "Q12345")).getQueryString()
);
}
......@@ -95,16 +95,16 @@ public class WikidataActionApiQueryTest {
)
);
final CheckEntityExistsResult result = ApiQueryClient.query(WikidataActionApiQuery.wbgetentities("dewiki", Collections.singletonList("Berlin")));
final WbgetentitiesResult result = ApiQueryClient.query(WikidataActionApiQuery.wbgetentities("dewiki", Collections.singletonList("Berlin")));
assertEquals(1, result.getSuccess());
assertEquals(0, result.getMissingEntities().size());
assertEquals(1, result.getEntities().size());
final Map.Entry<String, CheckEntityExistsResult.Entity> entityEntry = result.getEntities().entrySet().iterator().next();
final Map.Entry<String, WbgetentitiesResult.Entity> entityEntry = result.getEntities().entrySet().iterator().next();
assertEquals("Q64", entityEntry.getKey());
assertEquals("item", entityEntry.getValue().getType());
assertEquals("Q64", entityEntry.getValue().getId());
final Collection<CheckEntityExistsResult.Entity.Sitelink> sitelinks = entityEntry.getValue().getSitelinks();
final Collection<WbgetentitiesResult.Entity.Sitelink> sitelinks = entityEntry.getValue().getSitelinks();
assertEquals(1, sitelinks.size());
assertEquals("dewiki", sitelinks.iterator().next().getSite());
assertEquals("Berlin", sitelinks.iterator().next().getTitle());
......@@ -124,7 +124,7 @@ public class WikidataActionApiQueryTest {
)
);
final CheckEntityExistsResult result = ApiQueryClient.query(WikidataActionApiQuery.wbgetentities("enwiki", Arrays.asList("United States", "missing-article", "Great Britain", "Another missing article")));
final WbgetentitiesResult result = ApiQueryClient.query(WikidataActionApiQuery.wbgetentities("enwiki", Arrays.asList("United States", "missing-article", "Great Britain", "Another missing article")));
assertEquals(2, result.getEntities().size());
assertEquals(2, result.getMissingEntities().size());
......@@ -141,16 +141,39 @@ public class WikidataActionApiQueryTest {
assertEquals("enwiki", result.getEntities().get("Q23666").getSitelinks().iterator().next().getSite());
assertEquals("Great Britain", result.getEntities().get("Q23666").getSitelinks().iterator().next().getTitle());
final CheckEntityExistsResult.MissingEntity missing1 = result.getMissingEntities().stream().filter(it -> "missing-article".equals(it.getTitle())).findFirst().orElse(null);
final WbgetentitiesResult.MissingEntity missing1 = result.getMissingEntities().stream().filter(it -> "missing-article".equals(it.getTitle())).findFirst().orElse(null);
assertNull(missing1.getId());
assertEquals("enwiki", missing1.getSite());
final CheckEntityExistsResult.MissingEntity missing2 = result.getMissingEntities().stream().filter(it -> "Another missing article".equals(it.getTitle())).findFirst().orElse(null);
final WbgetentitiesResult.MissingEntity missing2 = result.getMissingEntities().stream().filter(it -> "Another missing article".equals(it.getTitle())).findFirst().orElse(null);
assertNull(missing2.getId());
assertEquals("enwiki", missing2.getSite());
verify(postRequestedFor(urlEqualTo("/")).withRequestBody(new EqualToPattern("format=json&utf8=1&formatversion=1&action=wbgetentities&props=sitelinks&sites=enwiki&sitefilter=enwiki&titles=United+States%7Cmissing-article%7CGreat+Britain%7CAnother+missing+article")));
}
@Test
public void testWikidataItemLabelQuery() throws IOException, URISyntaxException {
stubFor(post("/")
.withHeader("Accept", equalTo("application/json"))
.willReturn(
aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(ResourceFileLoader.getResourceBytes(WikidataActionApiQueryTest.class, "response/wbgetentities/labels_Q42.json"))
)
);
final Map<String, String> result = ApiQueryClient.query(WikidataActionApiQuery.wbgetentitiesLabels("Q42"));
assertEquals(138, result.size());
assertEquals("Douglas Adams", result.get("en"));
assertEquals("Дуглас Адамс", result.get("ru"));
assertEquals("더글러스 애덤스", result.get("ko"));
assertEquals("ಡಾಗ್ಲಸ್ ಆಡಮ್ಸ್", result.get("tcy"));
verify(postRequestedFor(urlEqualTo("/")).withRequestBody(new EqualToPattern("format=json&utf8=1&formatversion=1&action=wbgetentities&props=labels&ids=Q42")));
}
/**
* Sets {@link WikidataActionApiQuery#defaultUrl} to the supplied URL
* @param url the new URL
......