pacer 1.0.3-java → 1.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/Gemfile +1 -6
  2. data/lib/{pacer-1.0.3-standalone.jar → pacer-1.1.0-standalone.jar} +0 -0
  3. data/lib/pacer.rb +4 -0
  4. data/lib/pacer/blueprints/payload_elements.rb +44 -0
  5. data/lib/pacer/core/graph.rb +1 -0
  6. data/lib/pacer/core/graph/element_route.rb +3 -2
  7. data/lib/pacer/core/graph/path_route.rb +138 -0
  8. data/lib/pacer/core/route.rb +145 -1
  9. data/lib/pacer/filter/empty_filter.rb +2 -0
  10. data/lib/pacer/filter/loop_filter.rb +85 -0
  11. data/lib/pacer/filter/property_filter/filters.rb +6 -1
  12. data/lib/pacer/graph/graph_transactions_mixin.rb +6 -1
  13. data/lib/pacer/graph/pacer_graph.rb +47 -30
  14. data/lib/pacer/graph/yaml_encoder.rb +2 -0
  15. data/lib/pacer/loader.rb +9 -0
  16. data/lib/pacer/pipe/block_filter_pipe.rb +3 -2
  17. data/lib/pacer/pipe/loop_pipe.rb +23 -17
  18. data/lib/pacer/pipe/multi_pipe.rb +40 -0
  19. data/lib/pacer/pipe/naked_pipe.rb +21 -0
  20. data/lib/pacer/pipe/unwrapping_pipe.rb +4 -0
  21. data/lib/pacer/pipe/wrapping_pipe.rb +4 -0
  22. data/lib/pacer/pipes.rb +2 -1
  23. data/lib/pacer/route/mixin/route_operations.rb +15 -0
  24. data/lib/pacer/route_builder.rb +8 -11
  25. data/lib/pacer/side_effect/counted.rb +1 -0
  26. data/lib/pacer/side_effect/group_count.rb +1 -1
  27. data/lib/pacer/support/array.rb +18 -0
  28. data/lib/pacer/support/enumerable.rb +4 -0
  29. data/lib/pacer/transform/cap.rb +31 -0
  30. data/lib/pacer/transform/flat_map.rb +9 -0
  31. data/lib/pacer/transform/make_pairs.rb +29 -0
  32. data/lib/pacer/transform/map.rb +50 -2
  33. data/lib/pacer/transform/path.rb +27 -42
  34. data/lib/pacer/transform/path_tree.rb +111 -0
  35. data/lib/pacer/transform/payload.rb +50 -0
  36. data/lib/pacer/transform/process.rb +15 -0
  37. data/lib/pacer/transform/wrapped_path.rb +23 -0
  38. data/lib/pacer/utils/graph_analysis.rb +21 -7
  39. data/lib/pacer/version.rb +1 -1
  40. data/lib/pacer/wrappers/edge_wrapper.rb +18 -7
  41. data/lib/pacer/wrappers/element_wrapper.rb +4 -0
  42. data/lib/pacer/wrappers/index_wrapper.rb +1 -1
  43. data/lib/pacer/wrappers/path_wrapping_pipe_function.rb +85 -0
  44. data/lib/pacer/wrappers/vertex_wrapper.rb +33 -3
  45. data/pom.xml +1 -1
  46. data/spec/pacer/filter/property_filter/edge_filters_spec.rb +63 -0
  47. data/spec/pacer/filter/property_filter/filters_spec.rb +17 -7
  48. data/spec/pacer/transform/join_spec.rb +0 -1
  49. data/spec/pacer/transform/path_tree_spec.rb +97 -0
  50. data/spec/spec_helper.rb +2 -2
  51. 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
- if v[:element_type] == 'vertex'
12
- "vertex '#{v[:type]}' (#{v[:count]})"
13
- elsif v[:element_type] == 'edge'
14
- "edge :#{v[:label]} (#{v[:count]})"
15
- elsif v[:element_type] == 'property keys'
16
- "properties #{v[:number]} keys (#{v[:count]})"
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(self, edge_node[:label])
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
@@ -1,6 +1,6 @@
1
1
  module Pacer
2
2
  unless const_defined? :VERSION
3
- VERSION = "1.0.3"
3
+ VERSION = "1.1.0"
4
4
 
5
5
  JAR = "pacer-#{ VERSION }-standalone.jar"
6
6
  JAR_PATH = "lib/#{ JAR }"
@@ -4,9 +4,12 @@ module Pacer::Wrappers
4
4
  include Pacer::Core::Graph::EdgesRoute
5
5
 
6
6
  def_delegators :@element,
7
- :getId, :getLabel, :getPropertyKeys, :getProperty, :setProperty, :removeProperty,
8
- :getVertex,
9
- :getRawEdge
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 [StandardError] If this the associated vertices don't exist and :create_vertices is not set
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
- raise message unless opts[:ignore_missing_vertices]
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 [StandardError] If this the associated vertices don't exist
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
- raise 'vertices not found' if not iv or not ov
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
@@ -160,6 +160,10 @@ module Pacer::Wrappers
160
160
  display_name.to_s <=> other.display_name.to_s
161
161
  end
162
162
 
163
+ def element_payload
164
+ element.payload if element.is_a? Pacer::Payload::Element
165
+ end
166
+
163
167
  protected
164
168
 
165
169
  def after_initialize
@@ -40,7 +40,7 @@ module Pacer::Wrappers
40
40
  if element.is_a? ElementWrapper
41
41
  element = element.element
42
42
  end
43
- index.put key, value, element
43
+ index.put key.to_s, value, element
44
44
  end
45
45
  end
46
46
  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
- :getId, :getPropertyKeys, :getProperty, :setProperty, :removeProperty,
8
- :getEdges,
9
- :getRawVertex
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.3</gem.version>
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
- describe Filters do
6
+ shared_examples Filters do
7
7
  subject { filters }
8
8
 
9
9
  context 'no properties' do
10
- let(:filters) { Pacer::Route.filters [] }
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.filters [Tackle::SimpleMixin] }
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.filters([name: 'Darrick', nickname: 'pangloss']) }
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.filters([TP::Person, name: 'Darrick', nickname: 'pangloss']) }
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.filters [TP::Pangloss] }
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.filters [tokens: { short: '555555' }, name: 'Darrick'] }
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