jenkins-bot has submitted this change and it was merged.

Change subject: Simple DSL example
......................................................................


Simple DSL example

DSL is not finished but ready for testing/somewhat useful.  It works like:
./console.sh
g = TinkerGraph.open()
g.of(WikidataTraversal.class).ensureSchema().wd('Q1').properties()
g.of(WikidataTraversal.class).wd('Q23').wd('Q91').out('P509').unstub().properties('labelEn')
g.of(WikidataTraversal.class).all().instanceOf('Q5').namesList();

Change-Id: Ie79d93aeae67a060108603dd8e2394a1e7262cc6
---
M src/main/groovy/org/wikidata/gremlin/DomainSpecificLanguage.groovy
M src/main/groovy/org/wikidata/gremlin/GremlinPlugin.groovy
M src/main/groovy/org/wikidata/gremlin/Loader.groovy
M src/main/groovy/org/wikidata/gremlin/Schema.groovy
A src/main/java/org/wikidata/gremlin/DomainSpecificLanguageTraversal.java
A src/main/java/org/wikidata/gremlin/LoadingTraversal.java
A src/main/java/org/wikidata/gremlin/SelfAware.java
A src/main/java/org/wikidata/gremlin/WikidataTraversal.java
8 files changed, 198 insertions(+), 59 deletions(-)

Approvals:
  Smalyshev: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/src/main/groovy/org/wikidata/gremlin/DomainSpecificLanguage.groovy 
b/src/main/groovy/org/wikidata/gremlin/DomainSpecificLanguage.groovy
index 95274b8..869b7a4 100644
--- a/src/main/groovy/org/wikidata/gremlin/DomainSpecificLanguage.groovy
+++ b/src/main/groovy/org/wikidata/gremlin/DomainSpecificLanguage.groovy
@@ -12,42 +12,38 @@
 @Slf4j
 class DomainSpecificLanguage {
   void setup() {
-       // Some syntax sugar for setting properties
-       Vertex.metaClass.getProperty = { this.property(it).value(); }
-       Vertex.metaClass.setProperty = { name, value -> 
this.singleProperty(name, value); }
-       
-       return // for now
     log.info "Setting up domain specific language"
-    Pipe.metaClass.randomMark = {
-        RandomStringUtils.random(10, true, true)
+
+    // Some syntax sugar for setting properties
+    Vertex.metaClass {
+      getProperty = { delegate.property(it).value(); }
+      setProperty = { name, value -> delegate.singleProperty(name, value); }
     }
+
     // TODO the loader_ name seems silly
     Graph.metaClass.loader_ = null
-    Gremlin.addStep('loader')
+    //Gremlin.addStep('loader')
     Graph.metaClass.loader = { ->
       if (delegate.loader_ == null) {
         delegate.loader_ = new Loader(delegate)
       }
       return delegate.loader_
     }
-    Gremlin.addStep('wd')
-    Graph.metaClass.wd = { id ->
-      delegate.loader().byId(id)
-      return delegate.V('wikibaseId', id)
+    Graph.metaClass.commitIfSupported = { ->
+      if (delegate.features().graph().supportsTransactions()) {
+        delegate.tx().commit()
+      }
+    }
+    //Gremlin.addStep('wd')
+    //Graph.metaClass.wd = { id ->
+    //  delegate.loader().byId(id)
+    //  return delegate.of(WikidataTraversal.class).V('wikibaseId', id)
+    //}
+    return // for now
+    Pipe.metaClass.randomMark = {
+        RandomStringUtils.random(10, true, true)
     }
     // This exists in Tinkerpop 3 but not 2.
-    Vertex.metaClass.graph = { ->
-      // This probably only works in titan
-      return delegate.tx().getGraph()
-    }
-    Gremlin.addStep('refresh')
-    Pipe.metaClass.refresh = {
-      delegate.sideEffect{it.graph().loader().byVertex(it)}
-    }
-    Gremlin.addStep('reload')
-    Pipe.metaClass.reload = {
-      delegate.sideEffect{it.graph().loader().byVertex(it, true)}
-    }
     Gremlin.addStep('isA')
     Pipe.metaClass.isA = { id ->
       delegate.has('P31link', CONTAINS, id).hasNext()
@@ -73,18 +69,6 @@
     Gremlin.addStep('claimVertices')
     Pipe.metaClass.claimVertices = { prop ->
       delegate.out(prop)
-    }
-    // Produces list of entities that are instances of this class
-    // E.g. g.listOf('Q5') are humans
-    Gremlin.addStep('listOf')
-    Pipe.metaClass.listOf = {
-        delegate.V('P31link', it)
-    }
-    // Produces list of instances of the pipeline
-    // E.g. g.wd('Q5').instances() are humans
-    Gremlin.addStep('instances')
-    Pipe.metaClass.instances = {
-        delegate.in('P31')
     }
     // if the list has elements ranked "preferred", take them, otherwise take 
all
     // this produces list of claims
diff --git a/src/main/groovy/org/wikidata/gremlin/GremlinPlugin.groovy 
b/src/main/groovy/org/wikidata/gremlin/GremlinPlugin.groovy
index e69fc1d..37fb1b4 100644
--- a/src/main/groovy/org/wikidata/gremlin/GremlinPlugin.groovy
+++ b/src/main/groovy/org/wikidata/gremlin/GremlinPlugin.groovy
@@ -4,6 +4,7 @@
 import com.tinkerpop.gremlin.groovy.plugin.IllegalEnvironmentException
 import com.tinkerpop.gremlin.groovy.plugin.PluginAcceptor
 import com.tinkerpop.gremlin.groovy.plugin.PluginInitializationException
+import com.tinkerpop.gremlin.structure.Graph
 
 /**
  * Sets up Wikidata plugin.
@@ -11,11 +12,12 @@
 class GremlinPlugin extends AbstractGremlinPlugin {
   @Override
   public String getName() {
-    return "wikidata";
+    return "wikidata"
   }
 
   @Override
   public void afterPluginTo(PluginAcceptor pluginAcceptor) throws 
IllegalEnvironmentException, PluginInitializationException {
-    pluginAcceptor.addImports(["import org.wikidata.gremlin.*"] as Set);
+    pluginAcceptor.addImports(["import org.wikidata.gremlin.*"] as Set)
+    new DomainSpecificLanguage().setup();
   }
 }
diff --git a/src/main/groovy/org/wikidata/gremlin/Loader.groovy 
b/src/main/groovy/org/wikidata/gremlin/Loader.groovy
index 04323e0..04a7a44 100644
--- a/src/main/groovy/org/wikidata/gremlin/Loader.groovy
+++ b/src/main/groovy/org/wikidata/gremlin/Loader.groovy
@@ -27,7 +27,7 @@
  */
 @Slf4j
 class Loader {
-  final Graph g
+  private final Graph g
   private boolean batch = false
 //  private TitanBatchGraph bgraph = null
   /**
@@ -40,14 +40,14 @@
 
   Loader(Graph g, skip_props = true) {
     this.g = g
-       this.skip_props = skip_props
+    this.skip_props = skip_props
   }
 
   /**
    * Set if this loader is a batch loader
    */
   public void setBatch(boolean val = true) {
-         batch = val
+    batch = val
          throw new RuntimeException("Not supported yet for Titan 0.9")
 //       if(batch) {
 //               bgraph = new TitanBatchGraph(g, VertexIDType.STRING, 100000)
@@ -62,37 +62,29 @@
   /**
    * Load a wikidata item by id if it isn't in the database.
    */
-  void byId(id) {
+  def byId(id) {
     def v = g.V().has('wikibaseId', id)
-    if (!v.hasNext() || v.next().stub) {
-      refreshWikidataItem(id)
+    def found = null
+    if (!v.hasNext() || (found = v.next()).stub) {
+      return refreshWikidataItem(id)
     }
-  }
-
-  /**
-   * Loads a vertex from wikibase if it is a stub.
-   */
-  void byVertex(v, refresh = false) {
-    if (v.stub || refresh) {
-      refreshWikidataItem(v.wikibaseId)
-    }
+    return found
   }
 
   /**
    * Refresh a wikidata item by id.
    */
-  private void refreshWikidataItem(id) {
+  def refreshWikidataItem(id) {
     def item = fetchEntity(id)
-       loadFromItem(item)
-       // We do commit here since it's one-off update
-       g.tx().commit()
+    return loadFromItem(item)
+    g.commitIfSupported()
   }
 
   /**
    * Load into the DB from hashmap stricture
    * @param item
    */
-  public void loadFromItem(item) {
+  public loadFromItem(item) {
          def id = item['id']
          def isProperty = (id[0] == 'P')
          if(isProperty && skip_props) {
@@ -129,6 +121,7 @@
          if(isProperty) {
                        g.tx().commit()
                }
+               return g.v(v.id);
 // Not committing here to allow DataLoader to group updates
   }
 
diff --git a/src/main/groovy/org/wikidata/gremlin/Schema.groovy 
b/src/main/groovy/org/wikidata/gremlin/Schema.groovy
index ddc67db..8ee9ad6 100644
--- a/src/main/groovy/org/wikidata/gremlin/Schema.groovy
+++ b/src/main/groovy/org/wikidata/gremlin/Schema.groovy
@@ -162,6 +162,7 @@
          // wikibaseId is needed for Batch loading
       g.addVertex(T.label, 'special', 'specialValueNode', 'novalue', 'stub', 
false, 'wikibaseId', 'novalue')
     }
-    g.tx().commit()
+
+    g.commitIfSupported()
   }
 }
diff --git 
a/src/main/java/org/wikidata/gremlin/DomainSpecificLanguageTraversal.java 
b/src/main/java/org/wikidata/gremlin/DomainSpecificLanguageTraversal.java
new file mode 100644
index 0000000..dd863ad
--- /dev/null
+++ b/src/main/java/org/wikidata/gremlin/DomainSpecificLanguageTraversal.java
@@ -0,0 +1,49 @@
+package org.wikidata.gremlin;
+
+import com.tinkerpop.gremlin.process.graph.GraphTraversal;
+import com.tinkerpop.gremlin.process.graph.step.sideEffect.IdentityStep;
+import com.tinkerpop.gremlin.process.graph.step.sideEffect.StartStep;
+import com.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Implementations of methods to load items from wikidata and ensure the schema
+ * is good.
+ */
+public interface DomainSpecificLanguageTraversal<S, E, Self> extends 
GraphTraversal<S, E>, SelfAware<Self> {
+  /**
+   * Seed the graph traversal with all things.
+   */
+  default Self all() {
+    return cast(addStep(new StartStep<>(this, sideEffects().getGraph().V())));
+  }
+
+  /**
+   * Return all items that are an 'instanceof' the current item.
+   */
+  default Self instances() {
+    return cast(in("P31"));
+  }
+
+  /**
+   * Filter the current list to those things that are an 'instanceOf' the 
provided id.
+   */
+  default Self instanceOf(String id) {
+    return cast(has("P31link", id));
+  }
+
+  /**
+   * Produce list of id-name pairs for human inspection.
+   */
+  default Self namesList() {
+    return cast(map(t -> {
+      Map<String, String> map = new LinkedHashMap<>();
+      Vertex v = (Vertex) t.get();
+      map.put("id", v.property("wikibaseId").value().toString());
+      map.put("name", v.property("labelEn").orElse("unknown").toString());
+      return map;
+    }));
+  }
+}
diff --git a/src/main/java/org/wikidata/gremlin/LoadingTraversal.java 
b/src/main/java/org/wikidata/gremlin/LoadingTraversal.java
new file mode 100644
index 0000000..f29d76b
--- /dev/null
+++ b/src/main/java/org/wikidata/gremlin/LoadingTraversal.java
@@ -0,0 +1,59 @@
+package org.wikidata.gremlin;
+
+import com.tinkerpop.gremlin.process.graph.GraphTraversal;
+import com.tinkerpop.gremlin.process.graph.step.sideEffect.IdentityStep;
+import com.tinkerpop.gremlin.process.graph.step.sideEffect.StartStep;
+import com.tinkerpop.gremlin.structure.Vertex;
+
+/**
+ * Implementations of methods to load items from wikidata and ensure the schema
+ * is good.
+ */
+public interface LoadingTraversal<S, E, Self> extends GraphTraversal<S, E>, 
SelfAware<Self> {
+  /**
+   * Ensure schema is setup.
+   */
+  default Self ensureSchema() {
+    Schema schema = new Schema(sideEffects().getGraph());
+    schema.setupSchema();
+    schema.setupConstantData();
+    return cast(addStep(new IdentityStep<>(this)));
+  }
+
+  /**
+   * Load id from wikidata (if it isn't already loaded) and start the 
traversal there.
+   */
+  default Self wd(String id) {
+    return cast(addStep(new StartStep<>(this, loader().byId(id))));
+  }
+
+  /**
+   * Forcibly refresh a vertex from wikidata.
+   */
+  default Self refresh() {
+    return cast(sideEffect((t) -> {
+      Vertex v = (Vertex) t.get();
+      System.err.println(v);
+      loader().refreshWikidataItem(v.property("wikibaseId").value());
+    }));
+  }
+
+  /**
+   * Refresh a vertex from wikidata if it is a stub.
+   */
+  default Self unstub() {
+    return cast(sideEffect((t) -> {
+      Vertex v = (Vertex) t.get();
+      if ((Boolean)v.property("stub").value()) {
+        loader().refreshWikidataItem(v.property("wikibaseId").value());
+      }
+    }));
+  }
+
+  /**
+   * Fetch the loader to use for this traversal.
+   */
+  default Loader loader() {
+    return sideEffects().getOrCreate("loader", () -> new 
Loader(sideEffects().getGraph()));
+  }
+}
diff --git a/src/main/java/org/wikidata/gremlin/SelfAware.java 
b/src/main/java/org/wikidata/gremlin/SelfAware.java
new file mode 100644
index 0000000..fad5284
--- /dev/null
+++ b/src/main/java/org/wikidata/gremlin/SelfAware.java
@@ -0,0 +1,13 @@
+package org.wikidata.gremlin;
+
+import com.tinkerpop.gremlin.process.graph.GraphTraversal;
+import com.tinkerpop.gremlin.process.graph.step.sideEffect.IdentityStep;
+import com.tinkerpop.gremlin.process.graph.step.sideEffect.StartStep;
+import com.tinkerpop.gremlin.structure.Vertex;
+
+/**
+ * Objects of this type can cast things to their ultimate type.
+ */
+public interface SelfAware<Self> {
+  Self cast(Object o);
+}
diff --git a/src/main/java/org/wikidata/gremlin/WikidataTraversal.java 
b/src/main/java/org/wikidata/gremlin/WikidataTraversal.java
new file mode 100644
index 0000000..1f79dcf
--- /dev/null
+++ b/src/main/java/org/wikidata/gremlin/WikidataTraversal.java
@@ -0,0 +1,38 @@
+package org.wikidata.gremlin;
+
+import com.tinkerpop.gremlin.process.TraversalStrategies;
+import com.tinkerpop.gremlin.process.graph.GraphTraversal;
+import com.tinkerpop.gremlin.process.graph.strategy.TraverserSourceStrategy;
+import com.tinkerpop.gremlin.process.util.DefaultTraversal;
+import com.tinkerpop.gremlin.process.util.DefaultTraversalStrategies;
+import com.tinkerpop.gremlin.structure.Graph;
+
+/**
+ * Traversal interface defining new steps for wikidata.  Note that this must 
be written in Java
+ * because Groovy doesn't yet support default method implementations on 
interface methods.
+ */
+public interface WikidataTraversal<S, E> extends GraphTraversal<S, E>,
+    LoadingTraversal<S, E, WikidataTraversal<S, E>>,
+    DomainSpecificLanguageTraversal<S, E, WikidataTraversal<S, E>> {
+
+  @Override
+  default WikidataTraversal<S, E> cast(Object self) {
+    return (WikidataTraversal) self;
+  }
+
+  static <S> WikidataTraversal<S, S> of(Graph graph) {
+    return new DefaultWikidataTraversal(graph);
+  }
+
+  class DefaultWikidataTraversal extends DefaultTraversal implements 
WikidataTraversal {
+    static {
+      DefaultTraversalStrategies traversalStrategies = new 
DefaultTraversalStrategies();
+      traversalStrategies.addStrategy(TraverserSourceStrategy.instance());
+      
TraversalStrategies.GlobalCache.registerStrategies(DefaultWikidataTraversal.class,
 traversalStrategies);
+    }
+
+    public DefaultWikidataTraversal(Graph graph) {
+      super(graph);
+    }
+  }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/183307
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ie79d93aeae67a060108603dd8e2394a1e7262cc6
Gerrit-PatchSet: 5
Gerrit-Project: wikidata/gremlin
Gerrit-Branch: master
Gerrit-Owner: Manybubbles <[email protected]>
Gerrit-Reviewer: Smalyshev <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to