pacer-neo4j2 2.0.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +23 -0
- data/Rakefile +35 -0
- data/lib/pacer-neo4j2/algo/block_cost_evaluator.rb +38 -0
- data/lib/pacer-neo4j2/algo/block_estimate_evaluator.rb +32 -0
- data/lib/pacer-neo4j2/algo/block_path_expander.rb +61 -0
- data/lib/pacer-neo4j2/algo/cypher_transform.rb +129 -0
- data/lib/pacer-neo4j2/algo/path_pipe.rb +79 -0
- data/lib/pacer-neo4j2/algo/path_wrapper.rb +134 -0
- data/lib/pacer-neo4j2/algo/traversal_branch_wrapper.rb +47 -0
- data/lib/pacer-neo4j2/algo/wrapping.rb +34 -0
- data/lib/pacer-neo4j2/algo.rb +406 -0
- data/lib/pacer-neo4j2/blueprints_graph.rb +42 -0
- data/lib/pacer-neo4j2/graph.rb +243 -0
- data/lib/pacer-neo4j2/lucene_filter.rb +112 -0
- data/lib/pacer-neo4j2/raw_vertex_wrapping_pipe.rb +18 -0
- data/lib/pacer-neo4j2/rspec.rb +39 -0
- data/lib/pacer-neo4j2/transaction_event_handler.rb +40 -0
- data/lib/pacer-neo4j2/tx_data_wrapper.rb +101 -0
- data/lib/pacer-neo4j2/version.rb +9 -0
- data/lib/pacer-neo4j2-2.0.1-standalone.jar +0 -0
- data/lib/pacer-neo4j2.rb +99 -0
- data/pacer-neo4j2.gemspec +22 -0
- data/pom/standalone.xml +22 -0
- data/pom.xml +95 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 65bbc2ebae5136c5b95bdf14891ecd538522e719
|
4
|
+
data.tar.gz: 84bef1fdf8c9bbb626ef089ef0cedd59dff19ead
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e0a7bd049e14f3f101972f5a0696b6b6d47c30f575658a5cc713edd43605be26f86bbbb53149cbda18be86e7deadc4437053d32d118cf22e2a92e10a4bb1eb6
|
7
|
+
data.tar.gz: fc5480e6b8c60c18d56904b2e13b003607551a8111c40c4b45542d5a69ef7f21091a8a1c4fce8aec394937641f435bc9b2b390cc15ea32a0d0cf212b3a9aef19
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Neo4J Graph Database Adapter for Pacer
|
2
|
+
|
3
|
+
[Pacer](https://github.com/pangloss/pacer) is a
|
4
|
+
[JRuby](http://jruby.org) graph traversal framework built on the
|
5
|
+
[Tinkerpop](http://www.tinkerpop.com) stack.
|
6
|
+
|
7
|
+
This plugin enables full [Neo4J](http://neo4j.org) graph support in Pacer.
|
8
|
+
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
Here is how you open a Neo4J graph in Pacer.
|
13
|
+
|
14
|
+
require 'pacer'
|
15
|
+
require 'pacer-neo4j2'
|
16
|
+
|
17
|
+
# Graph will be created if it doesn't exist
|
18
|
+
graph = Pacer.neo4j 'path/to/graph'
|
19
|
+
|
20
|
+
All other operations are identical across graph implementations (except
|
21
|
+
where certain features are not supported). See Pacer's documentation for
|
22
|
+
more information.
|
23
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
file 'pom.xml' => 'lib/pacer-neo4j2/version.rb' do
|
5
|
+
pom = File.read 'pom.xml'
|
6
|
+
when_writing('Update pom.xml version number') do
|
7
|
+
open 'pom.xml', 'w' do |f|
|
8
|
+
pom.each_line do |line|
|
9
|
+
line.sub!(%r{<gem.version>.*</gem.version>}, "<gem.version>#{ Pacer::Neo4j2::VERSION }</gem.version>")
|
10
|
+
line.sub!(%r{<blueprints.version>.*</blueprints.version>}, "<blueprints.version>#{ Pacer::Neo4j2::BLUEPRINTS_VERSION }</blueprints.version>")
|
11
|
+
line.sub!(%r{<pipes.version>.*</pipes.version>}, "<pipes.version>#{ Pacer::Neo4j2::PIPES_VERSION }</pipes.version>")
|
12
|
+
f << line
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
file Pacer::Neo4j2::JAR_PATH => 'pom.xml' do
|
19
|
+
when_writing("Execute 'mvn package' task") do
|
20
|
+
system('mvn clean package')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
task :note do
|
25
|
+
puts "NOTE: touch lib/pacer-neo4j2/version.rb (or rake touch) to force everything to rebuild"
|
26
|
+
end
|
27
|
+
|
28
|
+
task :build => [:note, Pacer::Neo4j2::JAR_PATH]
|
29
|
+
task :install => [:note, Pacer::Neo4j2::JAR_PATH]
|
30
|
+
|
31
|
+
desc 'Touch version.rb so that the jar rebuilds'
|
32
|
+
task :touch do
|
33
|
+
system 'touch', 'lib/pacer-neo4j2/version.rb'
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
class BlockCostEvaluator
|
5
|
+
import org.neo4j.graphalgo.CostEvaluator
|
6
|
+
import org.neo4j.graphdb.Direction
|
7
|
+
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Edge
|
8
|
+
include CostEvaluator
|
9
|
+
|
10
|
+
DIRS = {
|
11
|
+
Direction::INCOMING => :in,
|
12
|
+
Direction::OUTGOING => :out,
|
13
|
+
Direction::BOTH => :both
|
14
|
+
}
|
15
|
+
|
16
|
+
attr_reader :block, :graph, :default
|
17
|
+
|
18
|
+
def initialize(block, graph, default)
|
19
|
+
@block = block
|
20
|
+
@graph = graph
|
21
|
+
@default = default.to_f
|
22
|
+
end
|
23
|
+
|
24
|
+
def getCost(rel, dir)
|
25
|
+
e = Pacer::Wrappers::EdgeWrapper.new graph, Neo4j2Edge.new(rel, graph.blueprints_graph)
|
26
|
+
result = block.call e, DIRS[dir]
|
27
|
+
if result.is_a? Numeric
|
28
|
+
result.to_f
|
29
|
+
elsif default
|
30
|
+
default
|
31
|
+
else
|
32
|
+
fail Pacer::ClientError, "No cost returned and no default specified: #{ result.inspect }"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
class BlockEstimateEvaluator
|
5
|
+
import org.neo4j.graphalgo.EstimateEvaluator
|
6
|
+
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Vertex
|
7
|
+
include EstimateEvaluator
|
8
|
+
|
9
|
+
attr_reader :block, :graph, :default
|
10
|
+
|
11
|
+
def initialize(block, graph, default)
|
12
|
+
@block = block
|
13
|
+
@graph = graph
|
14
|
+
@default = default.to_f
|
15
|
+
end
|
16
|
+
|
17
|
+
def getCost(node, goal)
|
18
|
+
node = Pacer::Wrappers::VertexWrapper.new graph, Neo4j2Vertex.new(node, graph.blueprints_graph)
|
19
|
+
goal = Pacer::Wrappers::VertexWrapper.new graph, Neo4j2Vertex.new(goal, graph.blueprints_graph)
|
20
|
+
result = block.call node, goal
|
21
|
+
if result.is_a? Numeric
|
22
|
+
result.to_f
|
23
|
+
elsif default
|
24
|
+
default
|
25
|
+
else
|
26
|
+
fail Pacer::ClientError, "No estimate returned and no default specified: #{ result.inspect }"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
class BlockPathExpander
|
5
|
+
import org.neo4j.graphdb.PathExpander
|
6
|
+
import com.tinkerpop.pipes.Pipe
|
7
|
+
|
8
|
+
include PathExpander
|
9
|
+
attr_reader :block, :rev, :graph, :max_depth
|
10
|
+
|
11
|
+
def initialize(block, rev, graph, max_depth)
|
12
|
+
@block = block
|
13
|
+
@rev = rev
|
14
|
+
@graph = graph
|
15
|
+
@max_depth = max_depth
|
16
|
+
end
|
17
|
+
|
18
|
+
def expand(path, state)
|
19
|
+
path = PathWrapper.new(path, graph)
|
20
|
+
if max_depth and path.length >= max_depth
|
21
|
+
result = []
|
22
|
+
else
|
23
|
+
result = block.call path, state
|
24
|
+
end
|
25
|
+
pipe = Pacer::Pipes::NakedPipe.new
|
26
|
+
pipe.set_starts result_to_enumerable(result)
|
27
|
+
pipe
|
28
|
+
end
|
29
|
+
|
30
|
+
def reverse
|
31
|
+
BlockPathExpander.new rev, block, graph, max_depth
|
32
|
+
end
|
33
|
+
|
34
|
+
def result_to_enumerable(result)
|
35
|
+
case result
|
36
|
+
when PathWrapper
|
37
|
+
fail "Don't just return the arguments in your expander, return edges!"
|
38
|
+
when Pacer::Route
|
39
|
+
if result.element_type == :edge
|
40
|
+
result.pipe.starts
|
41
|
+
else
|
42
|
+
fail "Expander must return edges"
|
43
|
+
end
|
44
|
+
when Pacer::Wrappers::EdgeWrapper
|
45
|
+
Pacer::Pipes::EnumerablePipe.new [result]
|
46
|
+
when Pacer::Pipes::WrappingPipe
|
47
|
+
result.starts
|
48
|
+
when Pipe
|
49
|
+
result
|
50
|
+
when Enumerable
|
51
|
+
Pacer::Pipes::EnumerablePipe.new result
|
52
|
+
when nil
|
53
|
+
Pacer::Pipes::EnumerablePipe.new []
|
54
|
+
else
|
55
|
+
fail "Can't figure out what to do with #{ result.class }"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Core
|
3
|
+
module StringRoute
|
4
|
+
def raw_cypher(opts = {})
|
5
|
+
chain_route({element_type: :cypher, transform: Pacer::Transform::Cypher}.merge opts)
|
6
|
+
end
|
7
|
+
|
8
|
+
def cypher(opts = {})
|
9
|
+
raw_cypher(opts).paths
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Graph
|
14
|
+
module VerticesRoute
|
15
|
+
def raw_cypher(query, elements_per_query = nil)
|
16
|
+
reducer(element_type: :array).
|
17
|
+
enter { Set[] }.
|
18
|
+
leave { |x, a| x.nil? or (elements_per_query and a.length % elements_per_query == 0) }.
|
19
|
+
reduce { |v, ids| ids << v.element_id }.
|
20
|
+
map(element_type: :string) { |a| "start v=node(#{a.to_a.join(',')}) #{ query }"}.
|
21
|
+
raw_cypher
|
22
|
+
end
|
23
|
+
|
24
|
+
def cypher(query, elements_per_query = nil)
|
25
|
+
raw_cypher(query, elements_per_query).paths
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module CypherRoute
|
31
|
+
def paths(*columns)
|
32
|
+
chain_route element_type: :path, transform: Pacer::Transform::CypherResults, columns: columns
|
33
|
+
end
|
34
|
+
|
35
|
+
def v(column = nil)
|
36
|
+
chain_route element_type: :vertex, transform: Pacer::Transform::CypherResults, columns: [column].compact, single: true
|
37
|
+
end
|
38
|
+
|
39
|
+
def e(column = nil)
|
40
|
+
chain_route element_type: :edge, transform: Pacer::Transform::CypherResults, columns: [column].compact, single: true
|
41
|
+
end
|
42
|
+
|
43
|
+
def results(*columns)
|
44
|
+
chain_route element_type: :array, transform: Pacer::Transform::CypherResults, columns: columns
|
45
|
+
end
|
46
|
+
end
|
47
|
+
Pacer::RouteBuilder.current.element_types[:cypher] = [CypherRoute]
|
48
|
+
end
|
49
|
+
|
50
|
+
module Transform
|
51
|
+
module Cypher
|
52
|
+
protected
|
53
|
+
|
54
|
+
def attach_pipe(end_pipe)
|
55
|
+
pipe = CypherPipe.new(self)
|
56
|
+
pipe.setStarts end_pipe if end_pipe
|
57
|
+
pipe
|
58
|
+
end
|
59
|
+
|
60
|
+
class CypherPipe < Pacer::Pipes::RubyPipe
|
61
|
+
import org.neo4j.cypher.javacompat.ExecutionEngine
|
62
|
+
|
63
|
+
attr_reader :engine
|
64
|
+
|
65
|
+
def initialize(route)
|
66
|
+
super()
|
67
|
+
graph = route.graph.neo_graph
|
68
|
+
@engine = ExecutionEngine.new graph
|
69
|
+
end
|
70
|
+
|
71
|
+
protected
|
72
|
+
|
73
|
+
def processNextStart
|
74
|
+
engine.execute starts.next
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module CypherResults
|
80
|
+
attr_accessor :columns, :single
|
81
|
+
|
82
|
+
protected
|
83
|
+
|
84
|
+
def attach_pipe(end_pipe)
|
85
|
+
pipe = ResultsPipe.new(self, columns, single)
|
86
|
+
pipe.setStarts end_pipe if end_pipe
|
87
|
+
pipe
|
88
|
+
end
|
89
|
+
|
90
|
+
class ResultsPipe < Pacer::Pipes::RubyPipe
|
91
|
+
import org.neo4j.cypher.javacompat.ExecutionEngine
|
92
|
+
|
93
|
+
include Pacer::Neo4j2::Algo::Wrapping
|
94
|
+
|
95
|
+
attr_reader :columns, :graph, :single
|
96
|
+
attr_accessor :current
|
97
|
+
|
98
|
+
def initialize(route, columns, single)
|
99
|
+
super()
|
100
|
+
@single = single
|
101
|
+
@graph = route.graph
|
102
|
+
@columns = columns if columns and columns.any?
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
|
107
|
+
def processNextStart
|
108
|
+
while true
|
109
|
+
if current
|
110
|
+
if current.first.hasNext
|
111
|
+
if single
|
112
|
+
return wrap_path(current.map(&:next)).first
|
113
|
+
else
|
114
|
+
return wrap_path current.map(&:next)
|
115
|
+
end
|
116
|
+
else
|
117
|
+
self.current = nil
|
118
|
+
end
|
119
|
+
else
|
120
|
+
results = starts.next
|
121
|
+
cols = columns || results.columns.to_a
|
122
|
+
self.current = cols.map { |col| results.columnAs col }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
class PathPipe < Pacer::Pipes::RubyPipe
|
5
|
+
import org.neo4j.graphdb::Node
|
6
|
+
import org.neo4j.graphdb::Relationship
|
7
|
+
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Vertex
|
8
|
+
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Edge
|
9
|
+
|
10
|
+
attr_reader :algo, :target, :graph, :max_hits
|
11
|
+
attr_accessor :current_paths, :hits
|
12
|
+
|
13
|
+
def initialize(algo, graph, target, max_hits)
|
14
|
+
super()
|
15
|
+
@algo = algo
|
16
|
+
@max_hits = max_hits || -1
|
17
|
+
@graph = graph.blueprints_graph
|
18
|
+
@target = unwrap target if target
|
19
|
+
end
|
20
|
+
|
21
|
+
def processNextStart
|
22
|
+
next_raw_path.map do |e|
|
23
|
+
if e.is_a? Node
|
24
|
+
Neo4j2Vertex.new e, graph
|
25
|
+
elsif e.is_a? Relationship
|
26
|
+
Neo4j2Edge.new e, graph
|
27
|
+
else
|
28
|
+
e
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def next_raw_path
|
34
|
+
loop do
|
35
|
+
if current_paths
|
36
|
+
if hits == 0
|
37
|
+
self.current_paths = nil
|
38
|
+
elsif current_paths.hasNext
|
39
|
+
self.hits -= 1
|
40
|
+
return current_paths.next
|
41
|
+
else
|
42
|
+
self.current_paths = nil
|
43
|
+
end
|
44
|
+
else
|
45
|
+
self.hits = max_hits
|
46
|
+
self.current_paths = @algo.findAllPaths(next_raw, target).iterator
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def next_raw
|
52
|
+
unwrap starts.next
|
53
|
+
end
|
54
|
+
|
55
|
+
def unwrap(vertex)
|
56
|
+
if vertex.respond_to? :element
|
57
|
+
vertex.element.raw_element
|
58
|
+
else
|
59
|
+
vertex.raw_element
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class PathFromPathPipe < PathPipe
|
65
|
+
attr_writer :target
|
66
|
+
|
67
|
+
def initialize(algo, graph, max_hits)
|
68
|
+
super(algo, graph, nil, max_hits)
|
69
|
+
end
|
70
|
+
|
71
|
+
def next_raw
|
72
|
+
path = starts.next
|
73
|
+
self.target = unwrap path.to_a.last
|
74
|
+
unwrap path[0]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
# Uses the interface defined here:
|
5
|
+
# http://api.neo4j.org/1.8/org/neo4j/graphdb/Path.html
|
6
|
+
#
|
7
|
+
# Note that I have removed methods that I didn't understand, assuming they are internal.
|
8
|
+
class PathWrapper
|
9
|
+
include Wrapping
|
10
|
+
|
11
|
+
attr_reader :graph, :raw_path
|
12
|
+
|
13
|
+
def initialize(path, graph)
|
14
|
+
@raw_path = path
|
15
|
+
@graph = graph
|
16
|
+
@gv = graph.v
|
17
|
+
@ge = graph.e
|
18
|
+
end
|
19
|
+
|
20
|
+
#Returns the end vertex of this path.
|
21
|
+
def end_v
|
22
|
+
wrap_vertex raw_path.endNode
|
23
|
+
end
|
24
|
+
|
25
|
+
# Iterates through both the vertices and edges of this path in order.
|
26
|
+
def path
|
27
|
+
wrap_path raw_path.iterator
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_a
|
31
|
+
path.to_a
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the last edge in this path.
|
35
|
+
def end_e
|
36
|
+
wrap_edge raw_path.lastRelationship
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the length of this path.
|
40
|
+
def length
|
41
|
+
raw_path.length
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns all the vertices in this path starting from the start vertex going forward towards the end vertex.
|
45
|
+
def v
|
46
|
+
raw_path.nodes.map { |n| wrap_vertex n }.to_route based_on: @gv
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns all the edges in between the vertices which this path consists of.
|
50
|
+
def e
|
51
|
+
raw_path.relationships.map { |r| wrap_edge r }.to_route based_on @ge
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns all the vertices in this path in reversed order, i.e.
|
55
|
+
def reverse_v
|
56
|
+
raw_path.reverseNodes.map { |n| wrap_vertex n }.to_route based_on @gv
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns all the edges in between the vertices which this path consists of in reverse order, i.e.
|
60
|
+
def reverse_e
|
61
|
+
raw_path.reverseRelationships.map { |r| wrap_edge r }.to_route based_on @ge
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the start vertex of this path.
|
65
|
+
def start_v
|
66
|
+
wrap_vertex raw_path.startNode
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
"#{ start_v.inspect }-(#{length})->#{end_v.inspect}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def inspect
|
74
|
+
"#<Path #{ to_s }>"
|
75
|
+
end
|
76
|
+
|
77
|
+
# skips route creation = faster but less features
|
78
|
+
def out_edges(*args)
|
79
|
+
end_v.out_edges(*args)
|
80
|
+
end
|
81
|
+
|
82
|
+
# skips route creation = faster but less features
|
83
|
+
def in_edges(*args)
|
84
|
+
end_v.in_edges(*args)
|
85
|
+
end
|
86
|
+
|
87
|
+
# skips route creation = faster but less features
|
88
|
+
def both_edges(*args)
|
89
|
+
end_v.both_edges(*args)
|
90
|
+
end
|
91
|
+
|
92
|
+
# skips route creation = faster but less features
|
93
|
+
def out_vertices(*args)
|
94
|
+
end_v.out_vertices(*args)
|
95
|
+
end
|
96
|
+
|
97
|
+
# skips route creation = faster but less features
|
98
|
+
def in_vertices(*args)
|
99
|
+
end_v.in_vertices(*args)
|
100
|
+
end
|
101
|
+
|
102
|
+
# skips route creation = faster but less features
|
103
|
+
def both_vertices(*args)
|
104
|
+
end_v.both_vertices(*args)
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def out_e(*args)
|
109
|
+
end_v.out_e(*args)
|
110
|
+
end
|
111
|
+
|
112
|
+
def in_e(*args)
|
113
|
+
end_v.in_e(*args)
|
114
|
+
end
|
115
|
+
|
116
|
+
def both_e(*args)
|
117
|
+
end_v.both_e(*args)
|
118
|
+
end
|
119
|
+
|
120
|
+
def out(*args)
|
121
|
+
end_v.out(*args)
|
122
|
+
end
|
123
|
+
|
124
|
+
def in(*args)
|
125
|
+
end_v.in(*args)
|
126
|
+
end
|
127
|
+
|
128
|
+
def both(*args)
|
129
|
+
end_v.both(*args)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
# Uses the interface defined here:
|
5
|
+
# http://api.neo4j.org/1.8/org/neo4j/graphdb/traversal/TraversalBranch.html
|
6
|
+
#
|
7
|
+
# Note that I have removed methods that I didn't understand, assuming they are internal.
|
8
|
+
class TraversalBranchWrapper < PathWrapper
|
9
|
+
# Returns whether or not the traversal should continue further along this branch.
|
10
|
+
def continues?
|
11
|
+
raw_path.continues
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the number of edges this expansion source has expanded.
|
15
|
+
def num_expanded
|
16
|
+
raw_path.expanded
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns whether or not this branch (the Path representation of this
|
20
|
+
# branch at least) should be included in the result of this traversal,
|
21
|
+
# i.e. returned as one of the Paths from f.ex.
|
22
|
+
# TraversalDescription.traverse(org.neo4j.graphdb.Node...)
|
23
|
+
def included?
|
24
|
+
raw_path.includes
|
25
|
+
end
|
26
|
+
|
27
|
+
# The parent expansion source which created this TraversalBranch.
|
28
|
+
def parent
|
29
|
+
TraversalBranchWrapper.new raw_path.parent, graph
|
30
|
+
end
|
31
|
+
|
32
|
+
# Explicitly tell this branch to be pruned so that consecutive calls to #next() is guaranteed to return null.
|
33
|
+
def prune!
|
34
|
+
raw_path.prune
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"#{super} num_expanded: #{ num_expanded }#{ continues? ? ' continues' : '' }#{ included? ? ' included' : '' }"
|
39
|
+
end
|
40
|
+
|
41
|
+
def inspect
|
42
|
+
"#<TBR #{to_s}>"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Neo4j2
|
3
|
+
module Algo
|
4
|
+
module Wrapping
|
5
|
+
import org.neo4j.graphdb.Node
|
6
|
+
import org.neo4j.graphdb.Relationship
|
7
|
+
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Vertex
|
8
|
+
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Edge
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def wrap_path(p)
|
13
|
+
p.collect do |e|
|
14
|
+
if e.is_a? Node
|
15
|
+
wrap_vertex e
|
16
|
+
elsif e.is_a? Relationship
|
17
|
+
wrap_edge e
|
18
|
+
else
|
19
|
+
e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def wrap_vertex(v)
|
25
|
+
Pacer::Wrappers::VertexWrapper.new graph, Neo4j2Vertex.new(v, graph.blueprints_graph)
|
26
|
+
end
|
27
|
+
|
28
|
+
def wrap_edge(e)
|
29
|
+
Pacer::Wrappers::EdgeWrapper.new graph, Neo4j2Edge.new(e, graph.blueprints_graph)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|