pacer 1.0.3-java → 1.1.0-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.
- data/Gemfile +1 -6
- data/lib/{pacer-1.0.3-standalone.jar → pacer-1.1.0-standalone.jar} +0 -0
- data/lib/pacer.rb +4 -0
- data/lib/pacer/blueprints/payload_elements.rb +44 -0
- data/lib/pacer/core/graph.rb +1 -0
- data/lib/pacer/core/graph/element_route.rb +3 -2
- data/lib/pacer/core/graph/path_route.rb +138 -0
- data/lib/pacer/core/route.rb +145 -1
- data/lib/pacer/filter/empty_filter.rb +2 -0
- data/lib/pacer/filter/loop_filter.rb +85 -0
- data/lib/pacer/filter/property_filter/filters.rb +6 -1
- data/lib/pacer/graph/graph_transactions_mixin.rb +6 -1
- data/lib/pacer/graph/pacer_graph.rb +47 -30
- data/lib/pacer/graph/yaml_encoder.rb +2 -0
- data/lib/pacer/loader.rb +9 -0
- data/lib/pacer/pipe/block_filter_pipe.rb +3 -2
- data/lib/pacer/pipe/loop_pipe.rb +23 -17
- data/lib/pacer/pipe/multi_pipe.rb +40 -0
- data/lib/pacer/pipe/naked_pipe.rb +21 -0
- data/lib/pacer/pipe/unwrapping_pipe.rb +4 -0
- data/lib/pacer/pipe/wrapping_pipe.rb +4 -0
- data/lib/pacer/pipes.rb +2 -1
- data/lib/pacer/route/mixin/route_operations.rb +15 -0
- data/lib/pacer/route_builder.rb +8 -11
- data/lib/pacer/side_effect/counted.rb +1 -0
- data/lib/pacer/side_effect/group_count.rb +1 -1
- data/lib/pacer/support/array.rb +18 -0
- data/lib/pacer/support/enumerable.rb +4 -0
- data/lib/pacer/transform/cap.rb +31 -0
- data/lib/pacer/transform/flat_map.rb +9 -0
- data/lib/pacer/transform/make_pairs.rb +29 -0
- data/lib/pacer/transform/map.rb +50 -2
- data/lib/pacer/transform/path.rb +27 -42
- data/lib/pacer/transform/path_tree.rb +111 -0
- data/lib/pacer/transform/payload.rb +50 -0
- data/lib/pacer/transform/process.rb +15 -0
- data/lib/pacer/transform/wrapped_path.rb +23 -0
- data/lib/pacer/utils/graph_analysis.rb +21 -7
- data/lib/pacer/version.rb +1 -1
- data/lib/pacer/wrappers/edge_wrapper.rb +18 -7
- data/lib/pacer/wrappers/element_wrapper.rb +4 -0
- data/lib/pacer/wrappers/index_wrapper.rb +1 -1
- data/lib/pacer/wrappers/path_wrapping_pipe_function.rb +85 -0
- data/lib/pacer/wrappers/vertex_wrapper.rb +33 -3
- data/pom.xml +1 -1
- data/spec/pacer/filter/property_filter/edge_filters_spec.rb +63 -0
- data/spec/pacer/filter/property_filter/filters_spec.rb +17 -7
- data/spec/pacer/transform/join_spec.rb +0 -1
- data/spec/pacer/transform/path_tree_spec.rb +97 -0
- data/spec/spec_helper.rb +2 -2
- metadata +18 -3
@@ -11,6 +11,21 @@ module Pacer
|
|
11
11
|
module Process
|
12
12
|
attr_accessor :block
|
13
13
|
|
14
|
+
def help(section = nil)
|
15
|
+
case section
|
16
|
+
when nil
|
17
|
+
puts <<HELP
|
18
|
+
The process method executes the given block for each element that is
|
19
|
+
passed through the route. After the block is called, the element that
|
20
|
+
was passed to it is emitted to be handled by the next step in the route.
|
21
|
+
|
22
|
+
It is Pacer's lazy version of the #each method.
|
23
|
+
|
24
|
+
HELP
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
14
29
|
protected
|
15
30
|
|
16
31
|
def attach_pipe(end_pipe)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Core
|
3
|
+
module Graph
|
4
|
+
module PathRoute
|
5
|
+
def wrapped(*exts)
|
6
|
+
chain_route transform: :wrap_path, element_type: :path
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Transform
|
13
|
+
module WrapPath
|
14
|
+
protected
|
15
|
+
|
16
|
+
def attach_pipe(end_pipe)
|
17
|
+
pipe = Pacer::Pipes::PathWrappingPipe.new(graph)
|
18
|
+
pipe.setStarts end_pipe
|
19
|
+
pipe
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -8,14 +8,28 @@ module Pacer
|
|
8
8
|
def structure(graph, type_field = :type)
|
9
9
|
result = Pacer.tg
|
10
10
|
result.vertex_name = proc do |v|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
case v[:element_type]
|
12
|
+
when 'vertex'
|
13
|
+
"vertex '#{ v[:type] }' (#{ v[:count] })"
|
14
|
+
when 'edge'
|
15
|
+
"edge '#{ v[:label] }' (#{ v[:count] })"
|
16
|
+
when 'property keys'
|
17
|
+
if v[:keys].empty?
|
18
|
+
"has no properties"
|
19
|
+
else
|
20
|
+
"has properties: #{ v[:keys].join ', ' } (#{ v[:count] })"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
result.edge_name = proc do |e|
|
25
|
+
if e.label == 'properties'
|
26
|
+
"#{ e[:count] }"
|
27
|
+
else
|
28
|
+
"#{ e[:count] } '#{ e.label }' edges to"
|
17
29
|
end
|
18
30
|
end
|
31
|
+
|
32
|
+
|
19
33
|
graph.v[type_field].fast_group_count.to_h.each do |type, count|
|
20
34
|
result.create_vertex :element_type => 'vertex', :type_field => type_field, :type => type, :count => count
|
21
35
|
end
|
@@ -28,7 +42,7 @@ module Pacer
|
|
28
42
|
end
|
29
43
|
result.v(:element_type => 'edge').each do |edge_node|
|
30
44
|
puts "edges with label #{ edge_node[:label] }: #{ edge_node[:count] }"
|
31
|
-
edge_route = graph.e(
|
45
|
+
edge_route = graph.e(edge_node[:label]).e(self)
|
32
46
|
edge_route.property_variations result, edge_node
|
33
47
|
end
|
34
48
|
result.v.each do |type_node|
|
data/lib/pacer/version.rb
CHANGED
@@ -4,9 +4,12 @@ module Pacer::Wrappers
|
|
4
4
|
include Pacer::Core::Graph::EdgesRoute
|
5
5
|
|
6
6
|
def_delegators :@element,
|
7
|
-
|
8
|
-
:
|
9
|
-
|
7
|
+
# Object
|
8
|
+
:equals, :toString, :hashCode,
|
9
|
+
# Element
|
10
|
+
:getId, :getPropertyKeys, :getProperty, :setProperty, :removeProperty, :getRawElement,
|
11
|
+
# Edge
|
12
|
+
:getLabel, :getVertex, :getRawEdge
|
10
13
|
|
11
14
|
class << self
|
12
15
|
def wrappers
|
@@ -128,7 +131,7 @@ module Pacer::Wrappers
|
|
128
131
|
# @yield [e] Optional block yields the edge after it has been created.
|
129
132
|
# @return [Pacer::Wrappers::EdgeWrapper] the new edge
|
130
133
|
#
|
131
|
-
# @raise [
|
134
|
+
# @raise [Pacer::ElementNotFound] If this the associated vertices don't exist and :create_vertices is not set
|
132
135
|
def clone_into(target_graph, opts = {})
|
133
136
|
e_idx = target_graph.temp_index("tmp-e-#{graph.graph_id}", :edge, :create => true)
|
134
137
|
e = e_idx.first('id', element_id)
|
@@ -143,7 +146,7 @@ module Pacer::Wrappers
|
|
143
146
|
if not iv or not ov
|
144
147
|
message = "Vertex not found for #{ self.inspect }: #{ iv.inspect } -> #{ ov.inspect }"
|
145
148
|
puts message if opts[:show_missing_vertices]
|
146
|
-
|
149
|
+
fail Pacer::ElementNotFound, message unless opts[:ignore_missing_vertices]
|
147
150
|
return nil
|
148
151
|
end
|
149
152
|
e = target_graph.create_edge(element_id, ov, iv, label, properties)
|
@@ -160,13 +163,13 @@ module Pacer::Wrappers
|
|
160
163
|
# @yield [e] Optional block yields the edge after it has been created.
|
161
164
|
# @return [Pacer::Wrappers::EdgeWrapper] the new edge
|
162
165
|
#
|
163
|
-
# @raise [
|
166
|
+
# @raise [Pacer::ElementNotFound] If this the associated vertices don't exist
|
164
167
|
def copy_into(target_graph)
|
165
168
|
v_idx = target_graph.temp_index("tmp-v-#{graph.graph_id}", :vertex, :create => true)
|
166
169
|
iv = v_idx.first('id', in_vertex.element_id) || target_graph.vertex(in_vertex.element_id)
|
167
170
|
ov = v_idx.first('id', out_vertex.element_id) || target_graph.vertex(out_vertex.element_id)
|
168
171
|
|
169
|
-
|
172
|
+
fail Pacer::ElementNotFound 'vertices not found' if not iv or not ov
|
170
173
|
e = target_graph.create_edge nil, ov, iv, label, properties
|
171
174
|
yield e if block_given?
|
172
175
|
e
|
@@ -197,5 +200,13 @@ module Pacer::Wrappers
|
|
197
200
|
def hash
|
198
201
|
-element.hash
|
199
202
|
end
|
203
|
+
|
204
|
+
def element_payload=(data)
|
205
|
+
if element.is_a? Pacer::Payload::Edge
|
206
|
+
element.payload = data
|
207
|
+
else
|
208
|
+
@element = Pacer::Payload::Edge.new element, data
|
209
|
+
end
|
210
|
+
end
|
200
211
|
end
|
201
212
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Wrappers
|
3
|
+
class PathWrappingPipeFunction
|
4
|
+
include com.tinkerpop.pipes.PipeFunction
|
5
|
+
|
6
|
+
attr_reader :block, :graph, :wrapper
|
7
|
+
|
8
|
+
def initialize(back, block)
|
9
|
+
@block = block
|
10
|
+
if back
|
11
|
+
@graph = back.graph
|
12
|
+
end
|
13
|
+
@wrapper = WrapperSelector.build
|
14
|
+
end
|
15
|
+
|
16
|
+
def arity
|
17
|
+
block.arity
|
18
|
+
end
|
19
|
+
|
20
|
+
def compute(path)
|
21
|
+
if path.first.is_a? Pacer::Wrappers::ElementWrapper
|
22
|
+
block.call path
|
23
|
+
else
|
24
|
+
p = path.map do |element|
|
25
|
+
wrapper.new graph, element
|
26
|
+
end
|
27
|
+
block.call p
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
alias call compute
|
32
|
+
|
33
|
+
def call_with_args(element, *args)
|
34
|
+
if path.first.is_a? Pacer::Wrappers::ElementWrapper
|
35
|
+
block.call path, *args
|
36
|
+
else
|
37
|
+
p = path.map do |element|
|
38
|
+
wrapper.new graph, element
|
39
|
+
end
|
40
|
+
block.call p, *args
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class PathUnwrappingPipeFunction
|
46
|
+
include com.tinkerpop.pipes.PipeFunction
|
47
|
+
|
48
|
+
attr_reader :block
|
49
|
+
|
50
|
+
def initialize(block)
|
51
|
+
@block = block
|
52
|
+
end
|
53
|
+
|
54
|
+
def arity
|
55
|
+
block.arity
|
56
|
+
end
|
57
|
+
|
58
|
+
def compute(path)
|
59
|
+
unwrap block.call path
|
60
|
+
end
|
61
|
+
|
62
|
+
alias call compute
|
63
|
+
|
64
|
+
def call_with_args(path, *args)
|
65
|
+
unwrap block.call path, *args
|
66
|
+
end
|
67
|
+
|
68
|
+
def unwrap(p)
|
69
|
+
if p.is_a? Array
|
70
|
+
p.map do |e|
|
71
|
+
if e.is_a? ElementWrapper
|
72
|
+
e.element
|
73
|
+
else
|
74
|
+
e
|
75
|
+
end
|
76
|
+
end
|
77
|
+
elsif p.is_a? ElementWrapper
|
78
|
+
p.element
|
79
|
+
else
|
80
|
+
p
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -4,9 +4,12 @@ module Pacer::Wrappers
|
|
4
4
|
include Pacer::Core::Graph::VerticesRoute
|
5
5
|
|
6
6
|
def_delegators :@element,
|
7
|
-
|
8
|
-
:
|
9
|
-
|
7
|
+
# Object
|
8
|
+
:equals, :toString, :hashCode,
|
9
|
+
# Element
|
10
|
+
:getId, :getPropertyKeys, :getProperty, :setProperty, :removeProperty, :getRawElement,
|
11
|
+
# Vertex
|
12
|
+
:getEdges, :getVertices, :query, :getRawVertex
|
10
13
|
|
11
14
|
class << self
|
12
15
|
def wrappers
|
@@ -164,6 +167,18 @@ module Pacer::Wrappers
|
|
164
167
|
get_edges_helper Pacer::Pipes::BOTH, *labels_and_extensions
|
165
168
|
end
|
166
169
|
|
170
|
+
def out_vertices(*labels_and_extensions)
|
171
|
+
get_vertices_helper Pacer::Pipes::OUT, *labels_and_extensions
|
172
|
+
end
|
173
|
+
|
174
|
+
def in_vertices(*labels_and_extensions)
|
175
|
+
get_vertices_helper Pacer::Pipes::IN, *labels_and_extensions
|
176
|
+
end
|
177
|
+
|
178
|
+
def both_vertices(*labels_and_extensions)
|
179
|
+
get_vertices_helper Pacer::Pipes::BOTH, *labels_and_extensions
|
180
|
+
end
|
181
|
+
|
167
182
|
# Test equality to another object.
|
168
183
|
#
|
169
184
|
# Elements are equal if they are the same type and have the same id
|
@@ -190,6 +205,14 @@ module Pacer::Wrappers
|
|
190
205
|
element.hash
|
191
206
|
end
|
192
207
|
|
208
|
+
def element_payload=(data)
|
209
|
+
if element.is_a? Pacer::Payload::Vertex
|
210
|
+
element.payload = data
|
211
|
+
else
|
212
|
+
@element = Pacer::Payload::Vertex.new element, data
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
193
216
|
protected
|
194
217
|
|
195
218
|
def get_edges_helper(direction, *labels_and_extensions)
|
@@ -199,6 +222,13 @@ module Pacer::Wrappers
|
|
199
222
|
pipe
|
200
223
|
end
|
201
224
|
|
225
|
+
def get_vertices_helper(direction, *labels_and_extensions)
|
226
|
+
labels, exts = split_labels_and_extensions(labels_and_extensions)
|
227
|
+
pipe = Pacer::Pipes::WrappingPipe.new graph, :vertex, exts
|
228
|
+
pipe.setStarts element.getVertices(direction, *labels).iterator
|
229
|
+
pipe
|
230
|
+
end
|
231
|
+
|
202
232
|
def split_labels_and_extensions(mixed)
|
203
233
|
labels = Set[]
|
204
234
|
exts = []
|
data/pom.xml
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
<artifactId>pacer</artifactId>
|
8
8
|
<!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
|
9
9
|
<properties>
|
10
|
-
<gem.version>1.0
|
10
|
+
<gem.version>1.1.0</gem.version>
|
11
11
|
<blueprints.version>2.1.0</blueprints.version>
|
12
12
|
<pipes.version>2.1.0</pipes.version>
|
13
13
|
<gremlin.version>2.1.0</gremlin.version>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# edge filters are also tested in filters_spec
|
4
|
+
module Pacer::Filter::PropertyFilter
|
5
|
+
Run.tg do
|
6
|
+
describe EdgeFilters do
|
7
|
+
subject { filters }
|
8
|
+
|
9
|
+
context 'symbol label' do
|
10
|
+
let(:filters) { Pacer::Route.edge_filters [:label] }
|
11
|
+
|
12
|
+
its(:any?) { should be_true }
|
13
|
+
its(:labels) { should == ['label'] }
|
14
|
+
its(:extensions_only?) { should be_false }
|
15
|
+
its(:extensions) { should be_empty }
|
16
|
+
its(:route_modules) { should be_empty }
|
17
|
+
its(:wrapper) { should be_nil }
|
18
|
+
its(:blocks) { should be_empty }
|
19
|
+
its(:properties) { should be_empty }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'symbol labels' do
|
23
|
+
let(:filters) { Pacer::Route.edge_filters [:label, :label2] }
|
24
|
+
|
25
|
+
its(:any?) { should be_true }
|
26
|
+
its(:labels) { should == ['label', 'label2'] }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'labels arrays' do
|
30
|
+
let(:filters) { Pacer::Route.edge_filters ["label", [:label2]] }
|
31
|
+
|
32
|
+
its(:any?) { should be_true }
|
33
|
+
its(:labels) { should == ['label', 'label2'] }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'labels and properties' do
|
37
|
+
let(:filters) { Pacer::Route.edge_filters [:label, { prop: 'value' }] }
|
38
|
+
|
39
|
+
its(:any?) { should be_true }
|
40
|
+
its(:labels) { should == ['label'] }
|
41
|
+
its(:properties) { should == [['prop', 'value']] }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'labels and extension' do
|
45
|
+
let(:filters) { Pacer::Route.edge_filters [:label, TP::Person] }
|
46
|
+
|
47
|
+
its(:any?) { should be_true }
|
48
|
+
its(:labels) { should == ['label'] }
|
49
|
+
its(:extensions) { should == [TP::Person] }
|
50
|
+
its(:properties) { should == [ %w[ type person ] ] }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'labels and simple extension' do
|
54
|
+
let(:filters) { Pacer::Route.edge_filters [:label, Tackle::SimpleMixin] }
|
55
|
+
|
56
|
+
its(:any?) { should be_true }
|
57
|
+
its(:labels) { should == ['label'] }
|
58
|
+
its(:extensions) { should == [Tackle::SimpleMixin] }
|
59
|
+
its(:properties) { should be_empty }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -3,17 +3,17 @@ require 'spec_helper'
|
|
3
3
|
module Pacer::Filter::PropertyFilter
|
4
4
|
|
5
5
|
Run.tg do
|
6
|
-
|
6
|
+
shared_examples Filters do
|
7
7
|
subject { filters }
|
8
8
|
|
9
9
|
context 'no properties' do
|
10
|
-
let(:filters) { Pacer::Route.
|
10
|
+
let(:filters) { Pacer::Route.send filter_method, [] }
|
11
11
|
|
12
12
|
its(:any?) { should be_false }
|
13
13
|
end
|
14
14
|
|
15
15
|
context 'no properties' do
|
16
|
-
let(:filters) { Pacer::Route.
|
16
|
+
let(:filters) { Pacer::Route.send filter_method, [Tackle::SimpleMixin] }
|
17
17
|
|
18
18
|
its(:any?) { should be_true }
|
19
19
|
its(:extensions_only?) { should be_true }
|
@@ -25,7 +25,7 @@ module Pacer::Filter::PropertyFilter
|
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'simple properties' do
|
28
|
-
let(:filters) { Pacer::Route.
|
28
|
+
let(:filters) { Pacer::Route.send filter_method, [name: 'Darrick', nickname: 'pangloss'] }
|
29
29
|
|
30
30
|
its(:any?) { should be_true }
|
31
31
|
its(:extensions_only?) { should be_false }
|
@@ -37,7 +37,7 @@ module Pacer::Filter::PropertyFilter
|
|
37
37
|
end
|
38
38
|
|
39
39
|
context 'with extensions' do
|
40
|
-
let(:filters) { Pacer::Route.
|
40
|
+
let(:filters) { Pacer::Route.send filter_method, [TP::Person, name: 'Darrick', nickname: 'pangloss'] }
|
41
41
|
|
42
42
|
its(:any?) { should be_true }
|
43
43
|
its(:extensions) { should == [TP::Person] }
|
@@ -113,7 +113,7 @@ module Pacer::Filter::PropertyFilter
|
|
113
113
|
|
114
114
|
context 'with route module' do
|
115
115
|
# TODO: should this feature be removed?
|
116
|
-
let(:filters) { Pacer::Route.
|
116
|
+
let(:filters) { Pacer::Route.send filter_method, [TP::Pangloss] }
|
117
117
|
|
118
118
|
its(:any?) { should be_true }
|
119
119
|
its(:extensions_only?) { should be_false }
|
@@ -125,7 +125,7 @@ module Pacer::Filter::PropertyFilter
|
|
125
125
|
end
|
126
126
|
|
127
127
|
context 'with manual index' do
|
128
|
-
let(:filters) { Pacer::Route.
|
128
|
+
let(:filters) { Pacer::Route.send filter_method, [tokens: { short: '555555' }, name: 'Darrick'] }
|
129
129
|
|
130
130
|
its(:any?) { should be_true }
|
131
131
|
its(:extensions) { should be_empty }
|
@@ -165,5 +165,15 @@ module Pacer::Filter::PropertyFilter
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
end
|
168
|
+
|
169
|
+
describe 'vertex' do
|
170
|
+
let(:filter_method) { :filters }
|
171
|
+
it_uses Filters
|
172
|
+
end
|
173
|
+
|
174
|
+
describe 'edge' do
|
175
|
+
let(:filter_method) { :edge_filters }
|
176
|
+
it_uses Filters
|
177
|
+
end
|
168
178
|
end
|
169
179
|
end
|