pacer 1.1.1-java → 1.2.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.
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