Javascript GLV
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/4e768a81 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/4e768a81 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/4e768a81 Branch: refs/heads/TINKERPOP-1489 Commit: 4e768a81f9109cca737151efbd1212086fd58749 Parents: 4eb80bd Author: Jorge Bay Gondra <jorgebaygon...@gmail.com> Authored: Wed Oct 5 16:14:46 2016 +0200 Committer: Jorge Bay Gondra <jorgebaygon...@gmail.com> Committed: Wed Jan 17 16:16:17 2018 +0100 ---------------------------------------------------------------------- gremlin-javascript/pom.xml | 132 ++ .../GraphTraversalSourceGenerator.groovy | 247 +++ .../javascript/TraversalSourceGenerator.groovy | 398 ++++ .../javascript/GenerateGremlinJavascript.java | 32 + .../gremlin/javascript/jsr223/SymbolHelper.java | 59 + .../driver/remote-connection.js | 107 + .../main/javascript/gremlin-javascript/index.js | 85 + .../process/graph-traversal.js | 2025 ++++++++++++++++++ .../gremlin-javascript/process/traversal.js | 395 ++++ .../gremlin-javascript/structure/graph.js | 146 ++ .../structure/io/graph-serializer.js | 406 ++++ .../javascript/gremlin-javascript/helper.js | 84 + .../gremlin-javascript/test-exports.js | 78 + .../gremlin-javascript/test-graphson.js | 108 + .../gremlin-javascript/test-traversal.js | 54 + pom.xml | 1 + 16 files changed, 4357 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/pom.xml ---------------------------------------------------------------------- diff --git a/gremlin-javascript/pom.xml b/gremlin-javascript/pom.xml new file mode 100644 index 0000000..387e628 --- /dev/null +++ b/gremlin-javascript/pom.xml @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>tinkerpop</artifactId> + <version>3.2.3-SNAPSHOT</version> + </parent> + <artifactId>gremlin-javascript</artifactId> + <name>Apache TinkerPop :: Gremlin Javascript</name> + <dependencies> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy</artifactId> + <version>${groovy.version}</version> + <classifier>indy</classifier> + </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>tinkergraph-gremlin</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-server</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + <properties> + <!-- provides a way to convert maven.test.skip value to skipTests for use in skipping python tests --> + <maven.test.skip>false</maven.test.skip> + <skipTests>${maven.test.skip}</skipTests> + <gremlin.server.dir>${project.parent.basedir}/gremlin-server</gremlin.server.dir> + </properties> + <build> + <directory>${basedir}/target</directory> + <finalName>${project.artifactId}-${project.version}</finalName> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.2.1</version> + <executions> + <execution> + <id>generate-javascript</id> + <phase>generate-test-resources</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.apache.tinkerpop.gremlin.javascript.GenerateGremlinJavascript</mainClass> + <arguments> + <argument>${basedir}/src/main/javascript/gremlin-javascript/process/traversal.js</argument> + <argument>${basedir}/src/main/javascript/gremlin-javascript/process/graph-traversal.js</argument> + </arguments> + </configuration> + </execution> + <execution> + <id>js-tests</id> + <phase>test</phase> + <goals> + <goal>exec</goal> + </goals> + <configuration> + <executable>jjs</executable> + <arguments> + <argument>${basedir}/src/test/javascript/gremlin-javascript/test-exports.js</argument> + <argument>${basedir}/src/test/javascript/gremlin-javascript/test-graphson.js</argument> + <argument>${basedir}/src/test/javascript/gremlin-javascript/test-traversal.js</argument> + </arguments> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.gmavenplus</groupId> + <artifactId>gmavenplus-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-clean-plugin</artifactId> + <version>3.0.0</version> + <executions> + <execution> + <goals> + <goal>clean</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/GraphTraversalSourceGenerator.groovy ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/GraphTraversalSourceGenerator.groovy b/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/GraphTraversalSourceGenerator.groovy new file mode 100644 index 0000000..81c38dc --- /dev/null +++ b/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/GraphTraversalSourceGenerator.groovy @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tinkerpop.gremlin.javascript + +import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__ +import org.apache.tinkerpop.gremlin.javascript.jsr223.SymbolHelper + +import java.lang.reflect.Modifier + +/** + * @author Jorge Bay Gondra + */ +class GraphTraversalSourceGenerator { + + public static void create(final String graphTraversalSourceFile) { + + final StringBuilder moduleOutput = new StringBuilder() + + moduleOutput.append("""/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + """) + +////////////////////////// +// GraphTraversalSource // +////////////////////////// + moduleOutput.append(""" +/** + * @author Jorge Bay Gondra + */ +(function defineGraphTraversalModule() { + "use strict"; + + var t = loadModule.call(this, './traversal.js'); + var remote = loadModule.call(this, '../driver/remote-connection.js'); + var Bytecode = t.Bytecode; + var inherits = t.inherits; + var parseArgs = t.parseArgs; + + /** + * + * @param {Graph} graph + * @param {TraversalStrategies} traversalStrategies + * @param {Bytecode} [bytecode] + * @constructor + */ + function GraphTraversalSource(graph, traversalStrategies, bytecode) { + this._graph = graph; + this._traversalStrategies = traversalStrategies; + this._bytecode = bytecode || new Bytecode(); + } + + /** + * @param remoteConnection + * @returns {GraphTraversal} + */ + GraphTraversalSource.prototype.withRemote = function (remoteConnection) { + var traversalStrategy = new t.TraversalStrategies(this._traversalStrategies); + traversalStrategy.addStrategy(new remote.RemoteStrategy(remoteConnection)); + return new GraphTraversal(this._graph, traversalStrategy, new Bytecode(this._bytecode)); + }; + + /** + * Returns the string representation of the GraphTraversalSource. + * @returns {string} + */ + GraphTraversalSource.prototype.toString = function () { + return 'graphtraversalsource[' + this._graph.toString() + ']'; + }; +""") + GraphTraversalSource.getMethods(). // SOURCE STEPS + findAll { GraphTraversalSource.class.equals(it.returnType) }. + findAll { + !it.name.equals("clone") && + !it.name.equals(TraversalSource.Symbols.withBindings) && + !it.name.equals(TraversalSource.Symbols.withRemote) + }. + collect { SymbolHelper.toJs(it.name) }. + unique(). + sort { a, b -> a <=> b }. + forEach { method -> + moduleOutput.append( + """ + /** + * ${method} GraphTraversalSource method. + * @param {...Object} args + * @returns {GraphTraversalSource} + */ + GraphTraversalSource.prototype.${method} = function (args) { + var b = new Bytecode(this._bytecode).addSource('${SymbolHelper.toJava(method)}', parseArgs.apply(null, arguments)); + return new GraphTraversalSource(this._graph, new t.TraversalStrategies(this._traversalStrategies), b); + }; +""") + } + GraphTraversalSource.getMethods(). // SPAWN STEPS + findAll { GraphTraversal.class.equals(it.returnType) }. + collect { SymbolHelper.toJs(it.name) }. + unique(). + sort { a, b -> a <=> b }. + forEach { method -> + moduleOutput.append( + """ + /** + * ${method} GraphTraversalSource step method. + * @param {...Object} args + * @returns {GraphTraversal} + */ + GraphTraversalSource.prototype.${method} = function (args) { + var b = new Bytecode(this._bytecode).addStep('${SymbolHelper.toJava(method)}', parseArgs.apply(null, arguments)); + return new GraphTraversal(this._graph, new t.TraversalStrategies(this._traversalStrategies), b); + }; +""") + } +//////////////////// +// GraphTraversal // +//////////////////// + moduleOutput.append( + """ + /** + * Represents a graph traversal. + * @constructor + */ + function GraphTraversal(graph, traversalStrategies, bytecode) { + t.Traversal.call(this, graph, traversalStrategies, bytecode); + } + + inherits(GraphTraversal, t.Traversal); +""") + GraphTraversal.getMethods(). + findAll { GraphTraversal.class.equals(it.returnType) }. + findAll { !it.name.equals("clone") && !it.name.equals("iterate") }. + collect { SymbolHelper.toJs(it.name) }. + unique(). + sort { a, b -> a <=> b }. + forEach { method -> + moduleOutput.append( + """ + /** + * @param {...Object} args + * @returns {GraphTraversal} + */ + GraphTraversal.prototype.${method} = function (args) { + this._bytecode.addStep('${SymbolHelper.toJava(method)}', parseArgs.apply(null, arguments)); + return this; + }; +""") + }; + +//////////////////////// +// AnonymousTraversal // +//////////////////////// + moduleOutput.append(""" + /** + * Contains the static method definitions + * @type {Object} + */ + var statics = {}; +"""); + __.class.getMethods(). + findAll { GraphTraversal.class.equals(it.returnType) }. + findAll { Modifier.isStatic(it.getModifiers()) }. + collect { SymbolHelper.toJs(it.name) }. + unique(). + sort { a, b -> a <=> b }. + forEach { method -> + moduleOutput.append( + """ + /** + * ${method}() static method + * @param {...Object} args + * @returns {GraphTraversal} + */ + statics.${method} = function (args) { + var g = new GraphTraversal(null, null, new Bytecode()); + return g.${method}.apply(g, arguments); + }; +""") + }; + + moduleOutput.append(""" + function loadModule(moduleName) { + if (typeof require !== 'undefined') { + return require(moduleName); + } + if (typeof load !== 'undefined') { + var path = new java.io.File(__DIR__ + moduleName).getCanonicalPath(); + this.__dependencies = this.__dependencies || {}; + return this.__dependencies[path] = (this.__dependencies[path] || load(path)); + } + throw new Error('No module loader was found'); + } + + var toExport = { + GraphTraversal: GraphTraversal, + GraphTraversalSource: GraphTraversalSource, + statics: statics + }; + if (typeof module !== 'undefined') { + // CommonJS + module.exports = toExport; + return; + } + // Nashorn and rest + return toExport; +}).call(this);""") + + // save to file + final File file = new File(graphTraversalSourceFile); + file.delete() + moduleOutput.eachLine { file.append(it + "\n") } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/TraversalSourceGenerator.groovy ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/TraversalSourceGenerator.groovy b/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/TraversalSourceGenerator.groovy new file mode 100644 index 0000000..efcb826 --- /dev/null +++ b/gremlin-javascript/src/main/groovy/org/apache/tinkerpop/gremlin/javascript/TraversalSourceGenerator.groovy @@ -0,0 +1,398 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tinkerpop.gremlin.javascript + +import org.apache.tinkerpop.gremlin.process.traversal.P +import org.apache.tinkerpop.gremlin.util.CoreImports +import org.apache.tinkerpop.gremlin.javascript.jsr223.SymbolHelper + +import java.lang.reflect.Modifier + +/** + * @author Jorge Bay Gondra + */ +class TraversalSourceGenerator { + + public static void create(final String traversalSourceFile) { + + final StringBuilder moduleOutput = new StringBuilder() + + moduleOutput.append("""/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +""") + moduleOutput.append(""" +/** + * @author Jorge Bay Gondra + */ +(function defineTraversalModule() { + "use strict"; + + function Traversal(graph, traversalStrategies, bytecode) { + this._graph = graph; + this._traversalStrategies = traversalStrategies; + this._bytecode = bytecode; + this.traversers = null; + this.sideEffects = null; + } + + /** @returns {Bytecode} */ + Traversal.prototype.getBytecode = function () { + return this._bytecode; + }; + + /** @param {Function} callback */ + Traversal.prototype.list = function (callback) { + var self = this; + this._traversalStrategies.applyStrategies(this, function (err) { + if (err) { + return callback(err); + } + callback(err, self.traversers); + }); + }; + + /** @param {Function} callback */ + Traversal.prototype.one = function (callback) { + this.list(function (err, result) { + callback(err, result ? result[0] : null); + }); + }; + + /** + * Returns the Bytecode JSON representation of the traversal + * @returns {String} + */ + Traversal.prototype.toString = function () { + return this._bytecode.toString(); + }; + """); + + moduleOutput.append(""" + /** + * Represents an operation. + * @constructor + */ + function P(operator, value, other) { + this.operator = operator; + this.value = value; + this.other = other; + } + + /** + * Returns the string representation of the instance. + * @returns {string} + */ + P.prototype.toString = function () { + if (this.other === undefined) { + return this.operator + '(' + this.value + ')'; + } + return this.operator + '(' + this.value + ', ' + this.other + ')'; + }; + + function createP(operator, args) { + args.unshift(null, operator); + return new (Function.prototype.bind.apply(P, args)); + } +""") + P.class.getMethods(). + findAll { Modifier.isStatic(it.getModifiers()) }. + findAll { P.class.isAssignableFrom(it.returnType) }. + collect { SymbolHelper.toJs(it.name) }. + unique(). + sort { a, b -> a <=> b }. + each { method -> + moduleOutput.append( + """ + /** @param {...Object} args */ + P.${method} = function (args) { + return createP('${SymbolHelper.toJava(method)}', parseArgs.apply(null, arguments)); + }; +""") + }; + moduleOutput.append(""" + P.prototype.and = function (arg) { + return new P('and', this, arg); + }; + + P.prototype.or = function (arg) { + return new P('or', this, arg); + }; +""") + + moduleOutput.append(""" + function Traverser(object, bulk) { + this.object = object; + this.bulk = bulk == undefined ? 1 : bulk; + } + + function TraversalSideEffects() { + + } + + /** + * Creates a new instance of TraversalStrategies. + * @param {TraversalStrategies} [traversalStrategies] + * @constructor + */ + function TraversalStrategies(traversalStrategies) { + /** @type {Array<TraversalStrategy>} */ + this.strategies = traversalStrategies ? traversalStrategies.strategies : []; + } + + /** @param {TraversalStrategy} strategy */ + TraversalStrategies.prototype.addStrategy = function (strategy) { + this.strategies.push(strategy); + }; + + /** @param {Traversal} traversal */ + TraversalStrategies.prototype.applyStrategies = function (traversal) { + this.strategies.forEach(function eachStrategy(s) { + s.apply(traversal); + }); + }; + + /** + * @abstract + * @constructor + */ + function TraversalStrategy() { + + } + + /** + * @abstract + * @param {Traversal} traversal + */ + TraversalStrategy.prototype.apply = function (traversal) { + + }; + + /** + * Creates a new instance of Bytecode + * @param {Bytecode} [toClone] + * @constructor + */ + function Bytecode(toClone) { + this._bindings = {}; + if (!toClone) { + this.sourceInstructions = []; + this.stepInstructions = []; + } + else { + this.sourceInstructions = toClone.sourceInstructions.slice(0); + this.stepInstructions = toClone.sourceInstructions.slice(0); + } + } + + /** + * Adds a new source instructions + * @param {String} name + * @param {Array} values + * @returns {Bytecode} + */ + Bytecode.prototype.addSource = function (name, values) { + if (name === undefined) { + throw new Error('Name is not defined'); + } + var instruction = new Array(values.length + 1); + instruction[0] = name; + for (var i = 0; i < values.length; ++i) { + instruction[i + 1] = this._convertToArgument(values[i]); + } + this.sourceInstructions.push(this._generateInstruction(name, values)); + return this; + }; + + /** + * Adds a new step instructions + * @param {String} name + * @param {Array} values + * @returns {Bytecode} + */ + Bytecode.prototype.addStep = function (name, values) { + if (name === undefined) { + throw new Error('Name is not defined'); + } + this.stepInstructions.push(this._generateInstruction(name, values)); + return this; + }; + + Bytecode.prototype._generateInstruction = function (name, values) { + var instruction = new Array(values.length + 1); + instruction[0] = name; + for (var i = 0; i < values.length; ++i) { + instruction[i + 1] = this._convertToArgument(values[i]); + } + return instruction; + }; + + /** + * Returns the JSON representation of the source and step instructions + * @returns {String} + */ + Bytecode.prototype.toString = function () { + return ( + (this.sourceInstructions.length > 0 ? JSON.stringify(this.sourceInstructions) : '') + + (this.stepInstructions.length > 0 ? JSON.stringify(this.stepInstructions) : '') + ); + }; + + Bytecode.prototype._convertToArgument = function (value) { + return value; + }; + + function toEnum(typeName, keys) { + var result = {}; + keys.split(' ').forEach(function (k) { + if (k === k.toUpperCase()) { + k = k.toLowerCase(); + } + result[k] = new EnumValue(typeName, k); + }); + return result; + } + + function EnumValue(typeName, elementName) { + this.typeName = typeName; + this.elementName = elementName; + } + + /** + * @type {{barrier, cardinality, column, direction, operator, order, pop, scope, t}} + */ + var enums = {};\n""") + + for (final Class<? extends Enum> enumClass : CoreImports.getClassImports() + .findAll { Enum.class.isAssignableFrom(it) } + .sort { a, b -> a.getSimpleName() <=> b.getSimpleName() } + .collect()) { + moduleOutput.append(" enums.${SymbolHelper.decapitalize(enumClass.getSimpleName())} = " + + "toEnum('${SymbolHelper.toJs(enumClass.getSimpleName())}', '"); + enumClass.getEnumConstants() + .sort { a, b -> a.name() <=> b.name() } + .each { value -> moduleOutput.append("${SymbolHelper.toJs(value.name())} "); } + moduleOutput.deleteCharAt(moduleOutput.length() - 1).append("');\n") + } + + moduleOutput.append(""" + // Utility functions + /** @returns {Array} */ + function parseArgs() { + return (arguments.length === 1 ? [ arguments[0] ] : Array.apply(null, arguments)); + } + + /** + * @param {Array} arr + * @param {Function} fn + * @param {Function} [callback] + */ + function eachSeries(arr, fn, callback) { + if (!Array.isArray(arr)) { + throw new TypeError('First parameter is not an Array'); + } + callback = callback || noop; + var length = arr.length; + if (length === 0) { + return callback(); + } + var sync; + var index = 1; + fn(arr[0], next); + if (sync === undefined) { + sync = false; + } + + function next(err) { + if (err) { + return callback(err); + } + if (index >= length) { + return callback(); + } + if (sync === undefined) { + sync = true; + } + if (sync) { + return process.nextTick(function () { + fn(arr[index++], next); + }); + } + fn(arr[index++], next); + } + } + + function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + } + + var toExport = { + Bytecode: Bytecode, + EnumValue: EnumValue, + inherits: inherits, + P: P, + parseArgs: parseArgs, + Traversal: Traversal, + TraversalSideEffects: TraversalSideEffects, + TraversalStrategies: TraversalStrategies, + TraversalStrategy: TraversalStrategy, + Traverser: Traverser + }; + Object.keys(enums).forEach(function (k) { + toExport[k] = enums[k]; + }); + if (typeof module !== 'undefined') { + // CommonJS + module.exports = toExport; + return; + } + // Nashorn and rest + return toExport; +}).call(this);""") + + // save to a file + final File file = new File(traversalSourceFile); + file.delete() + moduleOutput.eachLine { file.append(it + "\n") } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/GenerateGremlinJavascript.java ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/GenerateGremlinJavascript.java b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/GenerateGremlinJavascript.java new file mode 100644 index 0000000..1656db4 --- /dev/null +++ b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/GenerateGremlinJavascript.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tinkerpop.gremlin.javascript; + +public class GenerateGremlinJavascript { + + private GenerateGremlinJavascript() { + // just need the main method + } + + public static void main(String[] args) { + TraversalSourceGenerator.create(args[0]); + GraphTraversalSourceGenerator.create(args[1]); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java new file mode 100644 index 0000000..535de44 --- /dev/null +++ b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tinkerpop.gremlin.javascript.jsr223; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Jorge Bay Gondra + */ +public final class SymbolHelper { + + private final static Map<String, String> TO_JS_MAP = new HashMap<>(); + private final static Map<String, String> FROM_JS_MAP = new HashMap<>(); + + static { + TO_JS_MAP.put("in", "in_"); + TO_JS_MAP.put("from", "from_"); + TO_JS_MAP.forEach((k, v) -> FROM_JS_MAP.put(v, k)); + } + + private SymbolHelper() { + // static methods only, do not instantiate + } + + public static String toJs(final String symbol) { + return TO_JS_MAP.getOrDefault(symbol, symbol); + } + + public static String toJava(final String symbol) { + return FROM_JS_MAP.getOrDefault(symbol, symbol); + } + + public static String decapitalize(String string) { + if (string == null || string.length() == 0) { + return string; + } + char c[] = string.toCharArray(); + c[0] = Character.toLowerCase(c[0]); + return new String(c); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/src/main/javascript/gremlin-javascript/driver/remote-connection.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/driver/remote-connection.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/driver/remote-connection.js new file mode 100644 index 0000000..99b177f --- /dev/null +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/driver/remote-connection.js @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * @author Jorge Bay Gondra + */ +(function defineRemoteConnectionModule() { + "use strict"; + + var t = loadModule.call(this, '../process/traversal.js'); + var inherits = t.inherits; + + function RemoteConnection(url, traversalSource) { + this.url = url; + this.traversalSource = traversalSource; + } + + /** + * @abstract + * @param {Bytecode} bytecode + * @param {Function} callback + */ + RemoteConnection.prototype.submit = function (bytecode, callback) { + throw new Error('submit() needs to be implemented'); + }; + + /** + * @extends {Traversal} + * @constructor + */ + function RemoteTraversal(traversers, sideEffects) { + t.Traversal.call(this, null, null, null); + this.traversers = traversers; + this.sideEffects = sideEffects; + } + + inherits(RemoteTraversal, t.Traversal); + + /** + * + * @param {RemoteConnection} connection + * @extends {TraversalStrategy} + * @constructor + */ + function RemoteStrategy(connection) { + t.TraversalStrategy.call(this); + this.connection = connection; + } + + inherits(RemoteStrategy, t.TraversalStrategy); + + /** @override */ + RemoteStrategy.prototype.apply = function (traversal, callback) { + if (traversal.traversers) { + return; + } + this.connection.submit(traversal.getBytecode(), function (err, remoteTraversal) { + if (err) { + return callback(err); + } + traversal.sideEffects = remoteTraversal.sideEffects; + traversal.traversers = remoteTraversal.traversers; + callback(); + }); + }; + + function loadModule(moduleName) { + if (typeof require !== 'undefined') { + return require(moduleName); + } + if (typeof load !== 'undefined') { + var path = new java.io.File(__DIR__ + moduleName).getCanonicalPath(); + this.__dependencies = this.__dependencies || {}; + return this.__dependencies[path] = (this.__dependencies[path] || load(path)); + } + throw new Error('No module loader was found'); + } + + var toExport = { + RemoteConnection: RemoteConnection, + RemoteStrategy: RemoteStrategy, + RemoteTraversal: RemoteTraversal + }; + if (typeof module !== 'undefined') { + // CommonJS + module.exports = toExport; + return; + } + // Nashorn and rest + return toExport; +}).call(this); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4e768a81/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js new file mode 100644 index 0000000..cda8200 --- /dev/null +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * @author Jorge Bay Gondra + */ +(function exportModule() { + "use strict"; + + function loadModule(moduleName) { + if (typeof require !== 'undefined') { + return require(moduleName); + } + if (typeof load !== 'undefined') { + var path = new java.io.File(__DIR__ + moduleName).getCanonicalPath(); + this.__dependencies = this.__dependencies || {}; + return this.__dependencies[path] = (this.__dependencies[path] || load(path)); + } + throw new Error('No module loader was found'); + } + + var t = loadModule.call(this, './process/traversal.js'); + var gt = loadModule.call(this, './process/graph-traversal.js'); + var graph = loadModule.call(this, './structure/graph.js'); + var gs = loadModule.call(this, './structure/io/graph-serializer.js'); + var rc = loadModule.call(this, './driver/remote-connection.js'); + var toExport = { + driver: { + RemoteConnection: rc.RemoteConnection, + RemoteStrategy: rc.RemoteStrategy, + RemoteTraversal: rc.RemoteTraversal + }, + process: { + Bytecode: t.Bytecode, + EnumValue: t.EnumValue, + inherits: t.inherits, + P: t.P, + parseArgs: t.parseArgs, + Traversal: t.Traversal, + TraversalSideEffects: t.TraversalSideEffects, + TraversalStrategies: t.TraversalStrategies, + TraversalStrategy: t.TraversalStrategy, + Traverser: t.Traverser, + GraphTraversal: gt.GraphTraversal, + GraphTraversalSource: gt.GraphTraversalSource, + statics: gt.statics + }, + structure: { + io: { + GraphSONReader: gs.GraphSONReader, + GraphSONWriter: gs.GraphSONWriter + }, + Edge: graph.Edge, + Graph: graph.Graph, + Path: graph.Path, + Property: graph.Property, + Vertex: graph.Vertex, + VertexProperty: graph.VertexProperty + } + }; + + + if (typeof module !== 'undefined') { + // CommonJS + module.exports = toExport; + return; + } + return toExport; +}).call(this); \ No newline at end of file