Manybubbles has uploaded a new change for review. https://gerrit.wikimedia.org/r/187657
Change subject: Add synthetic label and desc properties ...................................................................... Add synthetic label and desc properties These properties currently only work with .properties, .values, .propertiesMap, and .valuesMap. They default to resolving languages in the following order: en, de, nl, ru. If there is no value for label or description in any of those languages then the result is the wikibaseId. Examples: Use the defaults: g.wd('Q1').properties('label', 'desc') Default labels to German: g.wd('Q1').languages('de', 'en').properties('label') Change-Id: Ia019ce48d17cdd7133fddb1ae306e42e3628c5d4 --- M src/main/groovy/org/wikidata/gremlin/Loader.groovy A src/main/java/org/wikidata/gremlin/LanguageDependentHelper.java A src/main/java/org/wikidata/gremlin/LanguageDependentTraversal.java M src/main/java/org/wikidata/gremlin/LoadingTraversal.java M src/main/java/org/wikidata/gremlin/WikidataTraversal.java A src/main/java/org/wikidata/gremlin/impl/DelegatingElement.java A src/main/java/org/wikidata/gremlin/impl/DelegatingTraverser.java A src/test/java/org/wikidata/gremlin/AbstractBaseTest.groovy M src/test/java/org/wikidata/gremlin/ImportTest.groovy A src/test/java/org/wikidata/gremlin/LanguageDependentTraversalTest.groovy 10 files changed, 585 insertions(+), 31 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/wikidata/gremlin refs/changes/57/187657/1 diff --git a/src/main/groovy/org/wikidata/gremlin/Loader.groovy b/src/main/groovy/org/wikidata/gremlin/Loader.groovy index 9e1fe3e..31d99b0 100644 --- a/src/main/groovy/org/wikidata/gremlin/Loader.groovy +++ b/src/main/groovy/org/wikidata/gremlin/Loader.groovy @@ -40,8 +40,8 @@ */ @Slf4j class Loader { - public final String WIKIDATA_URL = "http://www.wikidata.org/wiki/Special:EntityData" - public final int MAX_EXPAND_FACTOR = 50 + public static final String WIKIDATA_URL = "http://www.wikidata.org/wiki/Special:EntityData" + public static final int MAX_EXPAND_FACTOR = 50 private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.dateTimeNoMillis() .withZone(DateTimeZone.UTC) @@ -56,8 +56,9 @@ private def specNodes = [:] private long claims = 0 - private String entitySource = WIKIDATA_URL private boolean hasMetadata = true + + String entitySource = WIKIDATA_URL Loader(Graph g, skip_props = true) { this.g = g @@ -155,10 +156,6 @@ // Not committing here to allow DataLoader to group updates } - void setEntitySource(String src) { - entitySource = src - } - void delete(id) { g.V().has('wikibaseId', id).sideEffect{log.info "Deleting ${id}"; it.get().remove()}.iterate() } @@ -169,11 +166,10 @@ * @return a map containing the entity data or null if it was not found */ private def fetchEntity(id) { - log.info "Fetching ${id} from source" // Disable caching. You might think that it'd be from a performance standpoint to allow caching // but it'll get you an out of date index. def url = "${entitySource}/${id}.json?nocache" - log.debug "URL: url" + log.info "Fetching ${url}" try { def text = new URL(url).getText('UTF-8') log.debug "Loaded id $id, got this: " + JsonOutput.prettyPrint(text) @@ -279,17 +275,18 @@ * @return */ private def getOrCreateVertex(id) { - if(batch) { + if (batch) { return batchGetVertex(id) } def v = g.V().has('wikibaseId', id) - if ( v ) { + if (v) { return v.next() } - if(id[0] == 'Q') { - g.addVertex(T.label, 'item', 'wikibaseId', id, 'stub', true) - } else if(id[0] == 'P') { + if (id[0] == 'Q') { + def r = g.addVertex(T.label, 'item', 'wikibaseId', id, 'stub', true) + r + } else if (id[0] == 'P') { g.addVertex(T.label, 'property', 'wikibaseId', id, 'stub', true) } else { g.addVertex('wikibaseId', id, 'stub', true) @@ -371,7 +368,7 @@ } def l = 'desc' + description.key.capitalize() try { - v.singleProperty(l, true) + v.singleProperty(l, description.value.value) } catch(java.lang.IllegalArgumentException e) { initProperty(l, Boolean.class) v.singleProperty(l, true) diff --git a/src/main/java/org/wikidata/gremlin/LanguageDependentHelper.java b/src/main/java/org/wikidata/gremlin/LanguageDependentHelper.java new file mode 100644 index 0000000..a2c8172 --- /dev/null +++ b/src/main/java/org/wikidata/gremlin/LanguageDependentHelper.java @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2014 Wikimedia Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wikidata.gremlin; + +import com.tinkerpop.gremlin.structure.Element; +import com.tinkerpop.gremlin.structure.Property; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +/** + * Helps hacking language dependent properties ('label' and 'desc') into vertices. + */ +public abstract class LanguageDependentHelper { + public static final String[] DEFAULT_FALLBACKS = new String[] {"En"}; + private LanguageDependentHelper() {} + + /** + * Format language codes in the way we like. + */ + public static void formatLanguages(String[] languages) { + for (int i = 0; i < languages.length; i++) { + languages[i] = languages[i].substring(0, 1).toUpperCase(Locale.ROOT) + + languages[i].substring(1).toLowerCase(Locale.ROOT); + } + } + + /** + * Build a propertyIterator for some keys - catching the language dependent ones. + */ + public static <V> Iterator<? extends Property<V>> sneakyPropertyIterator(Element element, + String[] langaugeFallbacks, String... propertyKeys) { + for (int i = 0; i < propertyKeys.length; i++) { + propertyKeys[i] = transformKey(propertyKeys[i], element, langaugeFallbacks); + } + return element.iterators().<V>propertyIterator(propertyKeys); + } + + /** + * Transform a property key if it is language dependent. + */ + public static String transformKey(String key, Element element, String[] langaugeFallbacks) { + if (!"label".equals(key) && !"desc".equals(key)) { + return key; + } + for (String language: langaugeFallbacks) { + String option = key + language; + if (element.property(option).isPresent()) { + return option; + } + } + return "wikibaseId"; + } +} diff --git a/src/main/java/org/wikidata/gremlin/LanguageDependentTraversal.java b/src/main/java/org/wikidata/gremlin/LanguageDependentTraversal.java new file mode 100644 index 0000000..da9e9e1 --- /dev/null +++ b/src/main/java/org/wikidata/gremlin/LanguageDependentTraversal.java @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2014 Wikimedia Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wikidata.gremlin; + +import com.tinkerpop.gremlin.process.graph.GraphTraversal; +import com.tinkerpop.gremlin.process.graph.step.map.PropertiesStep; +import com.tinkerpop.gremlin.process.graph.step.map.PropertyMapStep; +import com.tinkerpop.gremlin.process.graph.step.sideEffect.IdentityStep; +import com.tinkerpop.gremlin.process.Traverser; +import com.tinkerpop.gremlin.process.Traversal; +import com.tinkerpop.gremlin.structure.Element; +import com.tinkerpop.gremlin.structure.Property; +import com.tinkerpop.gremlin.structure.PropertyType; +import org.wikidata.gremlin.impl.DelegatingElement; +import org.wikidata.gremlin.impl.DelegatingTraverser; +import java.util.Iterator; +import java.util.Map; +import java.util.function.Function; + +/** + * Hacks language dependent properties ('label', 'desc') into vertices. Doesn't currently work with has or by. + */ +public interface LanguageDependentTraversal<S, E, Self> extends GraphTraversal<S, E>, SelfAware<Self> { + /** + * Set the languages to display. + */ + default Self languages(String... languages) { + LanguageDependentHelper.formatLanguages(languages); + sideEffects().set("languageFallbacks", languages); + return cast(addStep(new IdentityStep<>(this))); + } + + default <E2> GraphTraversal<S, ? extends Property<E2>> properties(final String... propertyKeys) { + return addStep(new LanguageDependentPropertiesStep<>(this, PropertyType.PROPERTY, propertyKeys)); + } + default <E2> GraphTraversal<S, E2> values(final String... propertyKeys) { + return addStep(new LanguageDependentPropertiesStep<>(this, PropertyType.VALUE, propertyKeys)); + } + default <E2> GraphTraversal<S, Map<String, E2>> propertyMap(final String... propertyKeys) { + return addStep(new LanguageDependentPropertyMapStep<>(this, PropertyType.PROPERTY, propertyKeys)); + } + default <E2> GraphTraversal<S, Map<String, E2>> valueMap(final String... propertyKeys) { + return addStep(new LanguageDependentPropertyMapStep<>(this, PropertyType.VALUE, propertyKeys)); + } + + + + static class LanguageDependentPropertiesStep<E> extends PropertiesStep<E> { + public LanguageDependentPropertiesStep(Traversal traversal, PropertyType propertyType, String... propertyKeys) { + super(traversal, propertyType, propertyKeys); + } + + @Override + public void setFunction(final Function<Traverser<Element>, Iterator<E>> f) { + super.setFunction(f.compose(LanguageDependentTraverser::new)); + } + } + + static class LanguageDependentPropertyMapStep<E> extends PropertyMapStep<E> { + public LanguageDependentPropertyMapStep(Traversal traversal, PropertyType propertyType, String... propertyKeys) { + super(traversal, propertyType, propertyKeys); + } + + @Override + public void setFunction(final Function<Traverser<Element>, Map<String, E>> f) { + super.setFunction(f.compose(LanguageDependentTraverser::new)); + } + } + + static class LanguageDependentTraverser extends DelegatingTraverser<Element> { + public LanguageDependentTraverser(Traverser<Element> next) { + super(next); + } + + @Override + public Element get() { + return new LanguageDependentElement(super.get(), + next().sideEffects().orElse("languageFallbacks", LanguageDependentHelper.DEFAULT_FALLBACKS)); + } + } + + static class LanguageDependentElement extends DelegatingElement { + private String[] languageFallbacks; + + public LanguageDependentElement(Element next, String[] languageFallbacks) { + super(next); + this.languageFallbacks = languageFallbacks; + } + + @Override + public <V> Property<V> property(String key) { + return next().<V>property(LanguageDependentHelper.transformKey(key, next(), languageFallbacks)); + } + + @Override + public <V> Iterator<? extends Property<V>> propertyIterator(final String... propertyKeys) { + return LanguageDependentHelper.sneakyPropertyIterator(next(), languageFallbacks, propertyKeys); + } + } +} diff --git a/src/main/java/org/wikidata/gremlin/LoadingTraversal.java b/src/main/java/org/wikidata/gremlin/LoadingTraversal.java index 2b81e2f..f4f0426 100644 --- a/src/main/java/org/wikidata/gremlin/LoadingTraversal.java +++ b/src/main/java/org/wikidata/gremlin/LoadingTraversal.java @@ -77,6 +77,16 @@ * Fetch the loader to use for this traversal. */ default Loader loader() { - return sideEffects().getOrCreate("loader", () -> new Loader(sideEffects().getGraph())); + return sideEffects().getOrCreate("loader", this::buildLoader); + } + + /** + * Build the loader. + */ + default Loader buildLoader() { + Loader loader = new Loader(sideEffects().getGraph()); + loader.setEntitySource( + sideEffects().getGraph().variables().<String>get("source").orElse(Loader.WIKIDATA_URL)); + return loader; } } diff --git a/src/main/java/org/wikidata/gremlin/WikidataTraversal.java b/src/main/java/org/wikidata/gremlin/WikidataTraversal.java index 7685624..a21f3f0 100644 --- a/src/main/java/org/wikidata/gremlin/WikidataTraversal.java +++ b/src/main/java/org/wikidata/gremlin/WikidataTraversal.java @@ -27,7 +27,8 @@ */ public interface WikidataTraversal<S, E> extends GraphTraversal<S, E>, LoadingTraversal<S, E, WikidataTraversal<S, E>>, - DomainSpecificLanguageTraversal<S, E, WikidataTraversal<S, E>> { + DomainSpecificLanguageTraversal<S, E, WikidataTraversal<S, E>>, + LanguageDependentTraversal<S, E, WikidataTraversal<S, E>> { @Override default WikidataTraversal<S, E> cast(Object self) { diff --git a/src/main/java/org/wikidata/gremlin/impl/DelegatingElement.java b/src/main/java/org/wikidata/gremlin/impl/DelegatingElement.java new file mode 100644 index 0000000..1c8275b --- /dev/null +++ b/src/main/java/org/wikidata/gremlin/impl/DelegatingElement.java @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2014 Wikimedia Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wikidata.gremlin.impl; + +import com.tinkerpop.gremlin.structure.Element; +import com.tinkerpop.gremlin.structure.Graph; +import com.tinkerpop.gremlin.structure.Property; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * Simple delegating Element. + */ +public class DelegatingElement implements Element, Element.Iterators { + private final Element next; + + public DelegatingElement(Element next) { + this.next = next; + } + + public Element next() { + return next; + } + + @Override + public Object id() { + return next.id(); + } + + @Override + public String label() { + return next.label(); + } + + @Override + public Graph graph() { + return next.graph(); + } + + @Override + public Set<String> keys() { + return next.keys(); + } + + @Override + public Set<String> hiddenKeys() { + return next.hiddenKeys(); + } + + @Override + public <V> Property<V> property(final String key) { + return next.property(key); + } + + @Override + public <V> Property<V> property(final String key, final V value) { + return next.property(key, value); + } + + @Override + public <V> V value(final String key) throws NoSuchElementException { + return next.value(key); + } + + @Override + public <V> V value(final String key, final V orElse) { + return next.value(key, orElse); + } + + @Override + public void remove() { + next.remove(); + } + + @Override + public Element.Iterators iterators() { + return this; + } + + @Override + public <V> Iterator<V> valueIterator(final String... propertyKeys) { + return next.iterators().valueIterator(propertyKeys); + } + + @Override + public <V> Iterator<? extends Property<V>> propertyIterator(final String... propertyKeys) { + return next.iterators().propertyIterator(propertyKeys); + } +} diff --git a/src/main/java/org/wikidata/gremlin/impl/DelegatingTraverser.java b/src/main/java/org/wikidata/gremlin/impl/DelegatingTraverser.java new file mode 100644 index 0000000..bae3c56 --- /dev/null +++ b/src/main/java/org/wikidata/gremlin/impl/DelegatingTraverser.java @@ -0,0 +1,157 @@ +/** + * Copyright (C) 2014 Wikimedia Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wikidata.gremlin.impl; + +import com.tinkerpop.gremlin.process.Path; +import com.tinkerpop.gremlin.process.Traversal; +import com.tinkerpop.gremlin.process.Traverser; +import com.tinkerpop.gremlin.structure.Graph; +import com.tinkerpop.gremlin.structure.Vertex; +import com.tinkerpop.gremlin.structure.util.detached.Attachable; + +/** + * Simple delegating Traverser. + */ +public class DelegatingTraverser<T> implements Traverser<T>, Traverser.Admin<T> { + private final Traverser<T> next; + + public DelegatingTraverser(Traverser<T> next) { + this.next = next; + } + + public Traverser<T> next() { + return next; + } + + @Override + public T get() { + return next.get(); + } + + @Override + public boolean hasSack() { + return next.hasSack(); + } + + @Override + public <S> S sack() { + return next.sack(); + } + + @Override + public <S> void sack(final S object) { + next.sack(object); + } + + @Override + public Path path() { + return next.path(); + } + + @Override + public boolean hasPath() { + return next.hasPath(); + } + + @Override + public short loops() { + return next.loops(); + } + + @Override + public long bulk() { + return next.bulk(); + } + + @Override + public Traversal.SideEffects sideEffects() { + return next.sideEffects(); + } + + @Override + public void merge(final Admin<?> other) { + next.asAdmin().merge(other); + } + + @Override + public <R> Admin<R> split(final String label, final R r) { + return next.asAdmin().split(label, r); + } + + @Override + public Admin<T> split() { + return next.asAdmin().split(); + } + + @Override + public void set(final T t) { + next.asAdmin().set(t); + } + + @Override + public void setPath(final Path path) { + asAdmin().setPath(path); + } + + @Override + public void incrLoops() { + asAdmin().incrLoops(); + } + + @Override + public void resetLoops() { + asAdmin().resetLoops(); + } + + @Override + public String getFuture() { + return asAdmin().getFuture(); + } + + @Override + public void setFuture(final String label) { + asAdmin().setFuture(label); + } + + @Override + public void setBulk(final long count) { + asAdmin().setBulk(count); + } + + @Override + public boolean isHalted() { + return asAdmin().isHalted(); + } + + @Override + public Admin<T> detach() { + return asAdmin().detach(); + } + + @Override + public Admin<T> attach(final Vertex hostVertex) { + return asAdmin().attach(hostVertex); + } + + @Override + public Admin<T> attach(final Graph graph) throws UnsupportedOperationException { + return asAdmin().attach(graph); + } + + @Override + public void setSideEffects(final Traversal.SideEffects sideEffects) { + asAdmin().setSideEffects(sideEffects); + } +} diff --git a/src/test/java/org/wikidata/gremlin/AbstractBaseTest.groovy b/src/test/java/org/wikidata/gremlin/AbstractBaseTest.groovy new file mode 100644 index 0000000..978050f --- /dev/null +++ b/src/test/java/org/wikidata/gremlin/AbstractBaseTest.groovy @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2014 Wikimedia Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wikidata.gremlin + +import com.tinkerpop.gremlin.structure.Graph +import com.tinkerpop.gremlin.structure.strategy.StrategyWrappedGraph +import com.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph +import org.testng.annotations.* + +/** + * Base class for tests TinkerGraph and enabling all the wikidata goodies. Has + * a "g" variable that is automatically initialized to a sane empty graph. + */ +abstract class AbstractBaseTest { + Graph g + + protected Graph getG() { + if (g) { + return g + } + g = TinkerGraph.open() + g.variables().set('source', getClass().getResource("/json").toString()) + new DomainSpecificLanguage().setup() + + // FIXME: we may want instead have a mock object here + Loader.metaClass.checkProperty = { true } + + // TODO this next line used to appear in the tests - add it somehow? +// loader = new Loader(g, false) + + g.wt().ensureSchema() + + g + } + + @AfterTest + public void clearGraph() { + g = null + } +} diff --git a/src/test/java/org/wikidata/gremlin/ImportTest.groovy b/src/test/java/org/wikidata/gremlin/ImportTest.groovy index 72f5f42..d0309ec 100644 --- a/src/test/java/org/wikidata/gremlin/ImportTest.groovy +++ b/src/test/java/org/wikidata/gremlin/ImportTest.groovy @@ -41,7 +41,7 @@ loader.metaClass.checkProperty = { true } // TODO: there may be a better way to do this sources = getClass().getClassLoader().getResource("json").toURI().toString(); - loader.setEntitySource(sources) + loader.entitySource = sources } private Vertex getV(id) { @@ -116,7 +116,7 @@ assert v.outE('P580').values('P580value_all').hasNext() == true assert v.outE('P580').values('P580value_all').next()['calendarmodel'] == 'http://www.wikidata.org/entity/Q1985727' // Descriptions - assert v.descEn == true + assert v.descEn == 'totality of planets, stars, galaxies, intergalactic space, and all matter and energy' assert v.descGrc == null } @@ -230,7 +230,7 @@ assert v.outE('P1036').count().next() == 2 v = null - loader.setEntitySource(sources+"/uadd") + loader.entitySource += "/uadd" loader.refreshWikidataItem('Q1') v = getV('Q1') @@ -250,7 +250,7 @@ assert v.outE('P1036').count().next() == 2 v = null - loader.setEntitySource(sources+"/urev") + loader.entitySource += "/urev" loader.refreshWikidataItem('Q1') v = getV('Q1') @@ -268,7 +268,7 @@ assert v.outE('P1036').count().next() == 2 v = null - loader.setEntitySource(sources+"/umod") + loader.entitySource += "/umod" loader.refreshWikidataItem('Q1') v = getV('Q1') @@ -288,7 +288,7 @@ assert v.outE('P1036').count().next() == 2 v = null - loader.setEntitySource(sources+"/urm") + loader.entitySource += "/urm" loader.refreshWikidataItem('Q1') v = getV('Q1') @@ -306,7 +306,7 @@ assert v.outE('P793').count().next() == 3 v = null - loader.setEntitySource(sources+"/uaddlink") + loader.entitySource += "/uaddlink" loader.refreshWikidataItem('Q1') v = getV('Q1') // Multiple link claim @@ -328,7 +328,7 @@ assert v.outE('P793').count().next() == 3 v = null - loader.setEntitySource(sources+"/uaddlink2") + loader.entitySource += "/uaddlink2" loader.refreshWikidataItem('Q1') v = getV('Q1') // Multiple link claim @@ -350,7 +350,7 @@ assert v.outE('P793').count().next() == 3 v = null - loader.setEntitySource(sources+"/uchglink") + loader.entitySource += "/uchglink" loader.refreshWikidataItem('Q1') v = getV('Q1') // Multiple link claim @@ -372,7 +372,7 @@ assert v.labelEn == 'Douglas Adams' assert v.labelFr == 'Douglas Adams' v = null - loader.setEntitySource(sources+"/ulabel") + loader.entitySource += "/ulabel" loader.refreshWikidataItem('Q42') v = getV('Q42') @@ -389,7 +389,7 @@ assert v.labelEn == 'Douglas Adams' assert v.labelNl == 'Douglas Adams' v = null - loader.setEntitySource(sources+"/urmlabel") + loader.entitySource += "/urmlabel" loader.refreshWikidataItem('Q42') v = getV('Q42') @@ -407,7 +407,7 @@ assert v.outE('P793').count().next() == 3 v = null - loader.setEntitySource(sources+"/udroplink") + loader.entitySource += "/udroplink" loader.refreshWikidataItem('Q1') v = getV('Q1') // Multiple link claim @@ -452,7 +452,7 @@ assert v.properties('Lnowiki').has('badge', 'Q17437798').hasNext() == true assert v.properties('Lnowiki').has('badge', 'Q17437796').hasNext() == false - loader.setEntitySource(sources+"/ubadges") + loader.entitySource += "/ubadges" loader.refreshWikidataItem('Q84') v = getV('Q84') @@ -476,7 +476,7 @@ void refreshDeletesEntitiesThatAreNotFound() { assert loader.refreshWikidataItem('Q1') != null assert g.V().has('wikibaseId', 'Q1').hasNext() - loader.setEntitySource(sources + "/doesNotExist") + loader.entitySource += "/doesNotExist" assert loader.refreshWikidataItem('Q1') == null assert !g.V().has('wikibaseId', 'Q1').hasNext() } diff --git a/src/test/java/org/wikidata/gremlin/LanguageDependentTraversalTest.groovy b/src/test/java/org/wikidata/gremlin/LanguageDependentTraversalTest.groovy new file mode 100644 index 0000000..158021c --- /dev/null +++ b/src/test/java/org/wikidata/gremlin/LanguageDependentTraversalTest.groovy @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2014 Wikimedia Foundation + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wikidata.gremlin + +import com.thinkaurelius.titan.core.attribute.Geoshape +import com.tinkerpop.gremlin.structure.Graph +import com.tinkerpop.gremlin.structure.Vertex +import static org.testng.AssertJUnit.* +import org.testng.annotations.* +import java.util.HashMap + +class LanguageDependentTraversalTest extends AbstractBaseTest { + @Test + void defaults() { + assertEquals('universe', g.wd('Q1').properties('label').value().next()) + assertEquals('totality of planets, stars, galaxies, intergalactic space, and all matter and energy', + g.wd('Q1').properties('desc').value().next()) + assertEquals('universe', g.wd('Q1').values('label').next()) + assertEquals(['label': 'universe'], g.wd('Q1').propertyMap('label').next() + .collectEntries{[it.key, it.value.value()]}) + assertEquals(['label': 'universe', 'wikibaseId': 'Q1'], g.wd('Q1').propertyMap('label', 'wikibaseId') + .next().collectEntries{[it.key, it.value.value()]}) + assertEquals(['label': 'universe'], g.wd('Q1').valueMap('label').next()) + assertEquals(new HashMap(), g.wd('Q1').valueMap('foo').next()) + assertEquals(['label': 'universe', 'desc': 'totality of planets, stars, galaxies, intergalactic space, and all matter and energy'], + g.wd('Q1').valueMap('label', 'desc').next()) + } + + @Test + void configurable() { + assertEquals('Olam', g.wd('Q1').languages('uz', 'en').properties('label').value().next()) + assertEquals('universo', g.wd('Q1').languages('es', 'uz', 'en').properties('label').value().next()) + assertEquals('universe', g.wd('Q1').languages('zzz', 'en').properties('label').value().next()) + assertEquals('totality of planets, stars, galaxies, intergalactic space, and all matter and energy', + g.wd('Q1').languages('zzz', 'en').properties('desc').value().next()) + assertEquals('Gesamtheit der Energie, des Raumes und der Materie', + g.wd('Q1').languages('de', 'es', 'uz', 'en').properties('desc').value().next()) + assertEquals('Q1', g.wd('Q1').languages('zzz').properties('label').value().next()) + assertEquals('Q1', g.wd('Q1').languages('zzz').properties('label').value().next()) + assertEquals('Q1', g.wd('Q1').languages().properties('label').value().next()) + assertEquals('Q1', g.wd('Q1').languages().properties('label').value().next()) + } +} -- To view, visit https://gerrit.wikimedia.org/r/187657 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia019ce48d17cdd7133fddb1ae306e42e3628c5d4 Gerrit-PatchSet: 1 Gerrit-Project: wikidata/gremlin Gerrit-Branch: master Gerrit-Owner: Manybubbles <never...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits