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

Reply via email to