pacer 1.1.1-java → 1.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/Gemfile +5 -0
  2. data/lib/pacer/blueprints/tg.rb +2 -2
  3. data/lib/pacer/core/array_route.rb +80 -0
  4. data/lib/pacer/core/graph/element_route.rb +13 -13
  5. data/lib/pacer/core/graph/mixed_route.rb +2 -2
  6. data/lib/pacer/core/hash_route.rb +25 -1
  7. data/lib/pacer/core/route.rb +4 -9
  8. data/lib/pacer/exceptions.rb +6 -5
  9. data/lib/pacer/filter/property_filter/filters.rb +2 -6
  10. data/lib/pacer/filter/range_filter.rb +3 -1
  11. data/lib/pacer/graph/graph_transactions_mixin.rb +48 -12
  12. data/lib/pacer/graph/pacer_graph.rb +41 -10
  13. data/lib/pacer/graph/yaml_encoder.rb +8 -1
  14. data/lib/pacer/loader.rb +1 -0
  15. data/lib/pacer/pipe/loop_pipe.rb +1 -1
  16. data/lib/pacer/pipe/path_wrapping_pipe.rb +2 -2
  17. data/lib/pacer/pipe/wrapping_pipe.rb +1 -1
  18. data/lib/pacer/route/mixin/bulk_operations.rb +2 -2
  19. data/lib/pacer/support/awesome_print.rb +44 -0
  20. data/lib/pacer/transform/join.rb +15 -1
  21. data/lib/pacer/transform/lookup_ids.rb +36 -0
  22. data/lib/pacer/transform/path.rb +3 -1
  23. data/lib/pacer/transform/path_tree.rb +1 -1
  24. data/lib/pacer/version.rb +4 -4
  25. data/lib/pacer/visitors/section.rb +1 -1
  26. data/lib/pacer/wrappers/edge_wrapper.rb +9 -9
  27. data/lib/pacer/wrappers/element_wrapper.rb +11 -0
  28. data/lib/pacer/wrappers/index_wrapper.rb +1 -1
  29. data/lib/pacer/wrappers/path_wrapping_pipe_function.rb +1 -1
  30. data/lib/pacer/wrappers/vertex_wrapper.rb +3 -3
  31. data/lib/pacer/wrappers/wrapper_selector.rb +30 -12
  32. data/lib/pacer/wrappers/wrapping_pipe_function.rb +3 -3
  33. data/pom.xml +4 -4
  34. data/spec/pacer/blueprints/neo4j_spec.rb +50 -8
  35. data/spec/pacer/core/graph/element_route_spec.rb +1 -1
  36. data/spec/pacer/graph/yaml_encoder_spec.rb +5 -1
  37. data/spec/pacer/route/mixin/base_spec.rb +4 -1
  38. data/spec/pacer/wrapper/edge_wrapper_spec.rb +1 -1
  39. data/spec/pacer/wrapper/element_wrapper_spec.rb +10 -3
  40. data/spec/pacer/wrapper/vertex_wrapper_spec.rb +1 -1
  41. data/spec/spec_helper.rb +1 -0
  42. data/spec/support/graph_runner.rb +8 -3
  43. data/spec/support/matchers.rb +1 -1
  44. metadata +5 -4
data/Gemfile CHANGED
@@ -19,6 +19,11 @@ group :development do
19
19
  end
20
20
  end
21
21
 
22
+ if File.directory? "../mcfly"
23
+ gem 'pacer-mcfly', :path => "../mcfly"
24
+ end
25
+
26
+
22
27
 
23
28
  gem 'autotest-standalone'
24
29
  gem 'autotest-growl'
@@ -5,9 +5,9 @@ module Pacer
5
5
  # its standard simple persistant mode.
6
6
  def self.tg(path = nil)
7
7
  if path
8
- PacerGraph.new SimpleEncoder, proc { TinkerGraph.new(path) }
8
+ PacerGraph.new SimpleEncoder, TinkerGraph.new(path)
9
9
  else
10
- PacerGraph.new SimpleEncoder, proc { TinkerGraph.new }
10
+ PacerGraph.new SimpleEncoder, TinkerGraph.new
11
11
  end
12
12
  end
13
13
  end
@@ -24,6 +24,21 @@ The following array route methods are available:
24
24
  #len(n) Filter paths by length
25
25
  n: Number | Range
26
26
 
27
+ #map_in Map on each array
28
+ #reduce_in Reduce on each array
29
+ #select_in Select on each array
30
+ #reject_in Reject on each array
31
+
32
+ #select_case(*cases) Simplified select on each array without needing a block
33
+ #reject_case(*cases)
34
+ cases: the same type of objects you would give to case statements
35
+ (ie. exact match, regex, type, etc)
36
+
37
+ #vertices(*exts) Filter each array to only its vertices
38
+ #edges(*exts) " " " edges
39
+ #elements(*exts) " " " elements
40
+ exts: extensions to add to the filtered elements
41
+
27
42
  HELP
28
43
  else
29
44
  super
@@ -43,6 +58,10 @@ HELP
43
58
  scatter(element_type: :array)
44
59
  end
45
60
 
61
+ def flatten(*opts)
62
+ scatter(*opts)
63
+ end
64
+
46
65
  def compacted
47
66
  map element_type: element_type, route_name: 'compact' do |a|
48
67
  a.compact
@@ -72,6 +91,67 @@ HELP
72
91
  n === path.length
73
92
  end
74
93
  end
94
+
95
+ def map_in(&block)
96
+ map element_type: element_type do |e|
97
+ e.map(&block)
98
+ end
99
+ end
100
+
101
+ def reduce_in(initial, &block)
102
+ map { |e| e.reduce(initial, &block) }
103
+ end
104
+
105
+ def select_case(*cases)
106
+ map element_type: element_type do |e|
107
+ e.select { |x| cases.any? { |c| c === x } }
108
+ end
109
+ end
110
+
111
+ def reject_case(*cases)
112
+ map element_type: element_type do |e|
113
+ e.reject { |x| cases.any? { |c| c === x } }
114
+ end
115
+ end
116
+
117
+ def vertices(*exts)
118
+ r = select_case Pacer::Vertex
119
+ if exts.any?
120
+ r.map_in { |e| e.add_extensions exts }
121
+ else
122
+ r
123
+ end
124
+ end
125
+
126
+ def edges(*exts)
127
+ r = select_case Pacer::Edge
128
+ if exts.any?
129
+ r.map_in { |e| e.add_extensions exts }
130
+ else
131
+ r
132
+ end
133
+ end
134
+
135
+ def elements(*exts)
136
+ r = select_case Pacer::Element
137
+ if exts.any?
138
+ r.map_in { |e| e.add_extensions exts }
139
+ else
140
+ r
141
+ end
142
+ end
143
+
144
+ def select_in(&block)
145
+ map element_type: element_type do |e|
146
+ e.select(&block)
147
+ end
148
+ end
149
+
150
+ def reject_in(&block)
151
+ map element_type: element_type do |e|
152
+ e.select(&block)
153
+ end
154
+ end
75
155
  end
76
156
  end
77
157
  end
@@ -3,10 +3,6 @@ module Pacer::Core::Graph
3
3
  # Basic methods for routes shared between all route types that emit
4
4
  # routes: {VerticesRoute}, {EdgesRoute} and {MixedRoute}
5
5
  module ElementRoute
6
- def graph
7
- config[:graph]
8
- end
9
-
10
6
  # Attach a filter to the current route.
11
7
  #
12
8
  # @param [Array<Hash, extension>, Hash, extension] filter see {Pacer::Route#property_filter}
@@ -34,7 +30,7 @@ module Pacer::Core::Graph
34
30
  # rather than the elements themselves.
35
31
  # @return [Core::Route]
36
32
  def properties
37
- map { |v| v.properties }
33
+ map(element_type: :hash) { |v| v.properties }
38
34
  end
39
35
 
40
36
  # Create a new TinkerGraph based on the paths of all matching elements.
@@ -76,26 +72,30 @@ module Pacer::Core::Graph
76
72
  def [](prop_or_subset)
77
73
  case prop_or_subset
78
74
  when String, Symbol
79
- route = chain_route(:element_type => :object,
80
- :pipe_class => Pacer::Pipes::PropertyPipe,
81
- :pipe_args => [prop_or_subset.to_s],
82
- :lookahead_replacement => proc { |r| r.back.property?(prop_or_subset) })
83
- route.map(route_name: 'decode', remove_from_lookahead: true) do |v|
84
- graph.decode_property(v)
85
- end
75
+ typed_property(:object, prop_or_subset)
86
76
  when Fixnum
87
77
  range(prop_or_subset, prop_or_subset)
88
78
  when Range
89
79
  range(prop_or_subset.begin, prop_or_subset.end)
90
80
  when Array
91
81
  if prop_or_subset.all? { |i| i.is_a? String or i.is_a? Symbol }
92
- map do |element|
82
+ map(element_type: :array) do |element|
93
83
  element[prop_or_subset]
94
84
  end
95
85
  end
96
86
  end
97
87
  end
98
88
 
89
+ def typed_property(element_type, name)
90
+ route = chain_route(:element_type => :object,
91
+ :pipe_class => Pacer::Pipes::PropertyPipe,
92
+ :pipe_args => [name.to_s],
93
+ :lookahead_replacement => proc { |r| r.back.property?(name) })
94
+ route.map(route_name: 'decode', remove_from_lookahead: true, element_type: element_type) do |v|
95
+ graph.decode_property(v)
96
+ end
97
+ end
98
+
99
99
  # Map each element to a property but filter out elements that do not
100
100
  # have the given property.
101
101
  # @param [#to_s] name the property name
@@ -7,7 +7,7 @@ module Pacer::Core::Graph
7
7
  def v(*args, &block)
8
8
  route = chain_route :element_type => :vertex,
9
9
  :pipe_class => Pacer::Pipes::TypeFilterPipe,
10
- :pipe_args => Pacer::Wrappers::VertexWrapper,
10
+ :pipe_args => graph.base_vertex_wrapper,
11
11
  :wrapper => wrapper,
12
12
  :extensions => extensions
13
13
  Pacer::Route.property_filter(route, args, block)
@@ -17,7 +17,7 @@ module Pacer::Core::Graph
17
17
  def e(*args, &block)
18
18
  route = chain_route :element_type => :edge,
19
19
  :pipe_class => Pacer::Pipes::TypeFilterPipe,
20
- :pipe_args => Pacer::Wrappers::EdgeWrapper,
20
+ :pipe_args => graph.base_edge_wrapper,
21
21
  :wrapper => wrapper,
22
22
  :extensions => extensions
23
23
  Pacer::Route.property_filter(route, args, block)
@@ -2,7 +2,31 @@ module Pacer
2
2
  module Core
3
3
  module HashRoute
4
4
  def lengths
5
- map(element_type: :integer) { |s| s.length }
5
+ map(element_type: :integer) { |h| h.length }
6
+ end
7
+
8
+ def keys
9
+ map(element_type: :array) { |h| h.keys }
10
+ end
11
+
12
+ def values
13
+ map(element_type: :array) { |h| h.values }
14
+ end
15
+
16
+ def pairs
17
+ map(element_type: :array) { |h| h.to_a }
18
+ end
19
+
20
+ def [](k)
21
+ map { |h| h[k] }
22
+ end
23
+
24
+ def set(k, v)
25
+ process { |h| h[k] = v }
26
+ end
27
+
28
+ def fetch(k, *d, &block)
29
+ map { |h| h.fetch(k, *d, &block) }
6
30
  end
7
31
  end
8
32
  end
@@ -26,11 +26,6 @@ module Pacer
26
26
  # @return [true, false]
27
27
  attr_accessor :hide_elements
28
28
 
29
- # Set which graph this route will operate on.
30
- #
31
- # @todo move this to graph routes.
32
- attr_writer :graph
33
-
34
29
  # If this piece of the route is useless in a lookahead, set this to true
35
30
  # and when it is at the tail of a lookahead, it will be removed
36
31
  # automatically. (for instance the property decoder, or wrap/unwrap)
@@ -49,12 +44,12 @@ module Pacer
49
44
 
50
45
  # Return which graph this route operates on.
51
46
  #
52
- # @todo move this to graph routes.
53
- #
54
47
  # @return [PacerGraph]
55
48
  def graph
56
- @graph = nil unless defined? @graph
57
- @graph ||= (@back || @source).graph rescue nil
49
+ config.fetch :graph do
50
+ src = @back || @source
51
+ src.graph if src.respond_to? :graph
52
+ end
58
53
  end
59
54
 
60
55
  # Returns true if the given graph is the one this route operates on.
@@ -6,11 +6,12 @@ module Pacer
6
6
 
7
7
  class LogicError < Error; end
8
8
  class ClientError < LogicError; end
9
- class TransactionConcludedError < ClientError; end
10
- class NestedTransactionError < ClientError; end
11
- class NestedTransactionRollback < ClientError; end
12
- class NestedMockTransactionRollback < NestedTransactionRollback; end
13
- class MockTransactionRollback < ClientError; end
9
+ class TransactionError < ClientError; end
10
+ class TransactionConcludedError < TransactionError; end
11
+ class NestedTransactionError < TransactionError; end
12
+ class NestedTransactionRollback < TransactionError; end
13
+ class NestedMockTransactionRollback < NestedTransactionRollback; end
14
+ class MockTransactionRollback < TransactionError; end
14
15
  class UnsupportedOperation < ClientError; end
15
16
 
16
17
  class InternalError < LogicError; end
@@ -57,12 +57,6 @@ module Pacer
57
57
  # @attr [Boolean] search_manual_indices
58
58
  attr_accessor :search_manual_indices
59
59
 
60
- protected
61
-
62
- attr_accessor :non_ext_props
63
-
64
- public
65
-
66
60
  def initialize(filters)
67
61
  @properties = []
68
62
  @blocks = []
@@ -163,6 +157,8 @@ module Pacer
163
157
 
164
158
  protected
165
159
 
160
+ attr_accessor :non_ext_props
161
+
166
162
  def add_filter(filter, extension)
167
163
  case filter
168
164
  when Hash
@@ -11,10 +11,12 @@ module Pacer
11
11
  def limit(max)
12
12
  chain_route :filter => :range, :limit => max
13
13
  end
14
+ alias take limit
14
15
 
15
16
  def offset(amount)
16
17
  chain_route :filter => :range, :offset => amount
17
18
  end
19
+ alias drop offset
18
20
 
19
21
  def at(pos)
20
22
  chain_route :filter => :range, :index => pos
@@ -83,7 +85,7 @@ module Pacer
83
85
  from = @range.begin
84
86
  to = @range.end
85
87
  if @range.exclude_end?
86
- if to == 0
88
+ if to == 0
87
89
  pipe = Pacer::Pipes::NeverPipe.new
88
90
  pipe.set_starts end_pipe if end_pipe
89
91
  return pipe
@@ -50,8 +50,38 @@ module Pacer
50
50
  # Set this to true if you don't want to use transactions.
51
51
  #
52
52
  # By default, transactions are enabled.
53
+ #
54
+ # Note that this does not prevent blueprints implicit transactions from
55
+ # being created.
53
56
  attr_accessor :disable_transactions
54
57
 
58
+ # This is to work around the bad transaction design in Blueprints.
59
+ # Blueprints will always automatically start a transaction for you that it
60
+ # doesn't commits automatically and which you can not check the status of
61
+ # in any way. To deal with that, Pacer will (by default) commit implicit
62
+ # transactions before an explicit transaction is created. You can change
63
+ # that behavior by setting one of :commit, :rollback or :ignore. Ignore
64
+ # effectively folds changes from before the transaction into the current
65
+ # transaction.
66
+ attr_accessor :implicit_transaction
67
+
68
+ def close_implicit_transaction
69
+ case implicit_transaction
70
+ when nil, :commit
71
+ commit_implicit_transaction
72
+ when :rollback
73
+ rollback_implicit_transaction
74
+ end
75
+ end
76
+
77
+ def rollback_implicit_transaction
78
+ blueprints_graph.stopTransaction TransactionalGraph::Conclusion::FAILURE
79
+ end
80
+
81
+ def commit_implicit_transaction
82
+ blueprints_graph.stopTransaction TransactionalGraph::Conclusion::SUCCESS
83
+ end
84
+
55
85
  private
56
86
 
57
87
  def threadlocal_graph_info
@@ -63,20 +93,26 @@ module Pacer
63
93
  tgi = threadlocal_graph_info
64
94
  tx_depth = tgi[:tx_depth] ||= 0
65
95
  tgi[:tx_depth] += 1
66
- if (not disable_transactions) and blueprints_graph.is_a? TransactionalGraph
67
- if tx_depth == 0
68
- base_tx_finalizers
69
- elsif opts[:nesting] == true
70
- nested_tx_finalizers
71
- else
72
- fail NestedTransactionError, "To use nested transactions, use nesting: true"
73
- end
74
- else
75
- if tx_depth == 0
76
- mock_base_tx_finalizers
96
+ begin
97
+ if (not disable_transactions) and blueprints_graph.is_a? TransactionalGraph
98
+ if tx_depth == 0
99
+ close_implicit_transaction
100
+ base_tx_finalizers
101
+ elsif opts[:nesting] == true
102
+ nested_tx_finalizers
103
+ else
104
+ fail NestedTransactionError, "To use nested transactions, use nesting: true"
105
+ end
77
106
  else
78
- mock_nested_tx_finalizers
107
+ if tx_depth == 0
108
+ mock_base_tx_finalizers
109
+ else
110
+ mock_nested_tx_finalizers
111
+ end
79
112
  end
113
+ rescue Exception
114
+ tgi[:tx_depth] -= 1
115
+ raise
80
116
  end
81
117
  end
82
118
 
@@ -8,7 +8,11 @@ module Pacer
8
8
 
9
9
  attr_reader :blueprints_graph, :encoder
10
10
 
11
- def initialize(encoder, open, shutdown = nil)
11
+ attr_accessor :base_vertex_wrapper, :base_edge_wrapper
12
+
13
+ def initialize(encoder, open, shutdown = nil, graph_id = nil)
14
+ self.base_vertex_wrapper = Pacer::Wrappers::VertexWrapper
15
+ self.base_edge_wrapper = Pacer::Wrappers::EdgeWrapper
12
16
  if open.is_a? Proc
13
17
  @reopen = open
14
18
  else
@@ -17,6 +21,7 @@ module Pacer
17
21
  @shutdown = shutdown
18
22
  reopen
19
23
  @encoder = encoder
24
+ @graph_id = graph_id
20
25
  end
21
26
 
22
27
  # The current graph
@@ -47,6 +52,10 @@ module Pacer
47
52
  self
48
53
  end
49
54
 
55
+ def copy_object
56
+ self.class.new @encoder, @reopen, @shutdown, graph_id
57
+ end
58
+
50
59
  def use_wrapper(klass)
51
60
  reopen = proc do
52
61
  klass.new unwrap_graph(@reopen.call)
@@ -59,7 +68,7 @@ module Pacer
59
68
  end
60
69
 
61
70
  def graph_id
62
- blueprints_graph.object_id
71
+ @graph_id ||= blueprints_graph.object_id
63
72
  end
64
73
 
65
74
  def equals(other)
@@ -85,7 +94,7 @@ module Pacer
85
94
  v = wrapper.new graph, v
86
95
  modules.delete wrapper
87
96
  else
88
- v = Pacer::Wrappers::VertexWrapper.new graph, v
97
+ v = base_vertex_wrapper.new graph, v
89
98
  end
90
99
  v.add_extensions modules
91
100
  else
@@ -112,7 +121,7 @@ module Pacer
112
121
  v = wrapper.new graph, v
113
122
  modules.delete wrapper
114
123
  else
115
- v = Pacer::Wrappers::EdgeWrapper.new graph, v
124
+ v = base_edge_wrapper.new graph, v
116
125
  end
117
126
  v.add_extensions modules
118
127
  end
@@ -136,7 +145,7 @@ module Pacer
136
145
  if wrapper
137
146
  vertex = wrapper.new graph, raw_vertex
138
147
  else
139
- vertex = Pacer::Wrappers::VertexWrapper.new graph, raw_vertex
148
+ vertex = base_vertex_wrapper.new graph, raw_vertex
140
149
  end
141
150
  if modules.any?
142
151
  vertex = vertex.add_extensions modules
@@ -162,7 +171,7 @@ module Pacer
162
171
  if wrapper
163
172
  edge = wrapper.new graph, raw_edge
164
173
  else
165
- edge = Pacer::Wrappers::EdgeWrapper.new graph, raw_edge
174
+ edge = base_edge_wrapper.new graph, raw_edge
166
175
  end
167
176
  if modules.any?
168
177
  edge = edge.add_extensions modules
@@ -310,10 +319,12 @@ module Pacer
310
319
  @temp_indices ||= {}
311
320
  idx = @temp_indices[name]
312
321
  unless idx
313
- if name and type and opts[:create]
314
- idx = @temp_indices[name] = Pacer::Graph::HashIndex.new type, name
315
- elsif opts[:create]
316
- idx = Pacer::Graph::HashIndex.new type, nil
322
+ if opts[:temp] != false
323
+ if name and type and opts[:create]
324
+ idx = @temp_indices[name] = Pacer::Graph::HashIndex.new type, name
325
+ elsif opts[:create]
326
+ idx = Pacer::Graph::HashIndex.new type, nil
327
+ end
317
328
  end
318
329
  end
319
330
  Pacer::Wrappers::IndexWrapper.new self, idx, idx.type if idx
@@ -382,6 +393,26 @@ module Pacer
382
393
  []
383
394
  end
384
395
  end
396
+
397
+ def vertices_by_key(key, value, *extensions)
398
+ if key_indices(:vertex).include? key.to_s
399
+ pipe = Pacer::Pipes::WrappingPipe.new self, :vertex, extensions
400
+ pipe.setStarts blueprints_graph.getVertices(key.to_s, value).iterator
401
+ pipe
402
+ else
403
+ fail ClientError, "The key #{ key } is not indexed"
404
+ end
405
+ end
406
+
407
+ def edges_by_key(key, value, *extensions)
408
+ if key_indices(:edge).include? key.to_s
409
+ pipe = Pacer::Pipes::WrappingPipe.new self, :edge, extensions
410
+ pipe.setStarts blueprints_graph.getEdges(key.to_s, value).iterator
411
+ pipe
412
+ else
413
+ fail ClientError, "The key #{ key } is not indexed"
414
+ end
415
+ end
385
416
  end
386
417
  include KeyIndices
387
418