pacer-neo4j2 2.0.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|