pacer 1.0.2-java → 1.0.3-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 (48) hide show
  1. data/blog/2012-09-18-pacer-1.0.md +63 -0
  2. data/lib/pacer/core/graph/element_route.rb +8 -4
  3. data/lib/pacer/core/graph/vertices_route.rb +1 -1
  4. data/lib/pacer/core/route.rb +20 -0
  5. data/lib/pacer/exceptions.rb +1 -0
  6. data/lib/pacer/filter/future_filter.rb +2 -0
  7. data/lib/pacer/graph/graph_transactions_mixin.rb +13 -12
  8. data/lib/pacer/graph/hash_index.rb +29 -0
  9. data/lib/pacer/graph/pacer_graph.rb +23 -6
  10. data/lib/pacer/graph/simple_encoder.rb +9 -4
  11. data/lib/pacer/graph/yaml_encoder.rb +18 -31
  12. data/lib/pacer/loader.rb +93 -0
  13. data/lib/pacer/route/mixin/bulk_operations.rb +1 -1
  14. data/lib/pacer/route.rb +0 -151
  15. data/lib/pacer/route_builder.rb +142 -0
  16. data/lib/pacer/side_effect/as.rb +1 -3
  17. data/lib/pacer/version.rb +1 -1
  18. data/lib/pacer/wrappers/edge_wrapper.rb +13 -16
  19. data/lib/pacer/wrappers/element_wrapper.rb +12 -22
  20. data/lib/pacer/wrappers/vertex_wrapper.rb +7 -4
  21. data/lib/{pacer-1.0.2-standalone.jar → pacer-1.0.3-standalone.jar} +0 -0
  22. data/lib/pacer.rb +9 -15
  23. data/pom.xml +1 -1
  24. data/spec/pacer/blueprints/dex_spec.rb +1 -154
  25. data/spec/pacer/blueprints/neo4j_spec.rb +8 -154
  26. data/spec/pacer/blueprints/orient_spec.rb +5 -0
  27. data/spec/pacer/blueprints/tg_spec.rb +1 -76
  28. data/spec/pacer/core/graph/vertices_route_spec.rb +32 -5
  29. data/spec/pacer/graph/pacer_graph_spec.rb +304 -336
  30. data/spec/pacer/graph/simple_encoder_spec.rb +78 -0
  31. data/spec/pacer/graph/yaml_encoder_spec.rb +71 -0
  32. data/spec/pacer/transform/join_spec.rb +1 -1
  33. data/spec/pacer/utils/tsort_spec.rb +1 -3
  34. data/spec/pacer/wrapper/edge_wrapper_spec.rb +46 -40
  35. data/spec/pacer/wrapper/element_wrapper_spec.rb +8 -13
  36. data/spec/support/graph_runner.rb +12 -3
  37. metadata +13 -14
  38. data/lib/pacer/blueprints.rb +0 -3
  39. data/lib/pacer/core.rb +0 -8
  40. data/lib/pacer/filter.rb +0 -17
  41. data/lib/pacer/graph.rb +0 -12
  42. data/lib/pacer/route/mixins.rb +0 -2
  43. data/lib/pacer/routes.rb +0 -6
  44. data/lib/pacer/side_effect.rb +0 -11
  45. data/lib/pacer/support.rb +0 -10
  46. data/lib/pacer/transform.rb +0 -16
  47. data/lib/pacer/visitors.rb +0 -7
  48. data/lib/pacer/wrappers.rb +0 -21
@@ -0,0 +1,63 @@
1
+ What's new in Pacer 1.0
2
+ ===
3
+
4
+ We're very excited about the latest version of Pacer. We've used Pacer
5
+ 0.9 for almost a year now and it's served us very well, but in that time
6
+ we found a few pieces that we weren't happy with. We've addressed those
7
+ issues and also made improvements in its architecture, consistency, and
8
+ performance. So, here's what's new in Pacer 1.0:
9
+
10
+ * The already comprehensive spec suite has been improved and also
11
+ runs almost 10x faster.
12
+
13
+ * Graphs and elements are always wrapped. Previously, Pacer
14
+ patched the raw Java classes to add the methods it needs in addition
15
+ to allowing elements to be wrapped. By choosing to always use
16
+ wrapping, we can provide a cleaner, easier, and more consistent
17
+ interface.
18
+ * It uses the current [Tinkerpop](http://tinkerpop.com/) 2.1 stack with the most current versions
19
+ of all of its supported databases including [Neo4j](http://neo4j.org),
20
+ [Dex](http://www.sparsity-technologies.com/dex.php),
21
+ [OrientDB](http://www.orientdb.org/index.htm), and
22
+ [TinkerGraph](https://github.com/tinkerpop/blueprints/wiki/TinkerGraph). This is great news because
23
+ the Tinkerpop stack and the graphs that it supports are constantly
24
+ improving.
25
+ * The pacer-[graphdb] gems are no longer required but are all updated as a
26
+ convenient way to get the dependent jars without the pain of using maven.
27
+ * Pacer can fully support all of [Blueprints](https://github.com/tinkerpop/blueprints/wiki)'
28
+ WrapperGraph implementations. If you need the functionality behind one of the wrappers or want to
29
+ create your own, simply initialize a new PacerGraph with the wrapped
30
+ graph.
31
+ * Pacer is now able to fully support all [Gremlin](https://github.com/tinkerpop/gremlin/wiki) pipes including those
32
+ that require PipeFunctions, making all features in Gremlin available
33
+ to Pacer in addition to Pacer's own unique features.
34
+ * Many internal details of the implementation have been improved to make
35
+ Pacer's source much easier to understand and extend. This provides a
36
+ solid base on which to develop sophisticated projects.
37
+
38
+
39
+ Breaking changes and upgrade notes
40
+ ---
41
+
42
+ Breaking changes have been kept to a minimum but there were a number of
43
+ places that we weren't happy with the previous implementation and have
44
+ addressed them.
45
+
46
+ * Pacer now requires [JRuby](http://jruby.org/) 1.7. This latest version of JRuby handles Java
47
+ exceptions significantly more cleanly which eliminated a problem we
48
+ previously had to work around in numerous places. In addition it is
49
+ now in 1.9 mode by default, starts up faster, and conforms to the more
50
+ recent Ruby 1.9.3 which brings valuable improvements to the standard
51
+ Ruby libraries.
52
+
53
+ * To find an index, the `#index_name` method has been renamed to `#index`.
54
+ * All `#element_type` methods now return simply `:vertex`, `:edge`, `:mixed`
55
+ or `:object`.
56
+ * The `#extensions` method sometimes returned a Set and sometimes an Array. Now it
57
+ always returns an Array.
58
+ * Elements yielded to a block within a route no longer have the
59
+ BlockFilterElement extension added to them. In the rare occasion that
60
+ you need to use the `#back` or `#vars` methods within a block, they
61
+ can be easily accessed by referring to the route itself within the
62
+ block. To see an example, refer to the `as_spec.rb` file.
63
+
@@ -75,9 +75,13 @@ module Pacer::Core::Graph
75
75
  def [](prop_or_subset)
76
76
  case prop_or_subset
77
77
  when String, Symbol
78
- chain_route(:element_type => :object,
78
+ route = chain_route(:element_type => :object,
79
79
  :pipe_class => Pacer::Pipes::PropertyPipe,
80
- :pipe_args => [prop_or_subset.to_s])
80
+ :pipe_args => [prop_or_subset.to_s],
81
+ :lookahead_replacement => proc { |r| r.back.property?(prop_or_subset) })
82
+ route.map(route_name: 'decode', remove_from_lookahead: true) do |v|
83
+ graph.decode_property(v)
84
+ end
81
85
  when Fixnum
82
86
  range(prop_or_subset, prop_or_subset)
83
87
  when Range
@@ -85,7 +89,7 @@ module Pacer::Core::Graph
85
89
  when Array
86
90
  if prop_or_subset.all? { |i| i.is_a? String or i.is_a? Symbol }
87
91
  map do |element|
88
- prop_or_subset.collect { |i| element.getProperty(i.to_s) }
92
+ element[prop_or_subset]
89
93
  end
90
94
  end
91
95
  end
@@ -98,7 +102,7 @@ module Pacer::Core::Graph
98
102
  def property?(name)
99
103
  chain_route(:element_type => :object,
100
104
  :pipe_class => Pacer::Pipes::PropertyPipe,
101
- :pipe_args => [name.to_s, true])
105
+ :pipe_args => [name.to_s, false])
102
106
  end
103
107
 
104
108
  # Attach a route to the element id for each element emitted by the
@@ -174,7 +174,7 @@ module Pacer::Core::Graph
174
174
  has_props = !props.empty?
175
175
  edge_ids = []
176
176
  counter = 0
177
- graph.transaction do |commit, rollback|
177
+ graph.transaction(nesting: true) do |commit, rollback|
178
178
  v.each do |from_v|
179
179
  to_vertices.each do |to_v|
180
180
  counter += 1
@@ -31,6 +31,22 @@ module Pacer
31
31
  # @todo move this to graph routes.
32
32
  attr_writer :graph
33
33
 
34
+ # If this piece of the route is useless in a lookahead, set this to true
35
+ # and when it is at the tail of a lookahead, it will be removed
36
+ # automatically. (for instance the property decoder, or wrap/unwrap)
37
+ attr_accessor :remove_from_lookahead
38
+
39
+ # If a route's function won't do the expected thing in a lookahead, set a
40
+ # proc here that will correct the route. For instance:
41
+ #
42
+ # g.v.lookahead { |v| v[:prop] }
43
+ #
44
+ # gets transformed to:
45
+ #
46
+ # g.v.lookahead { |v| v.property?(:prop) }
47
+ #
48
+ attr_accessor :lookahead_replacement
49
+
34
50
  # Return which graph this route operates on.
35
51
  #
36
52
  # @todo move this to graph routes.
@@ -46,6 +62,10 @@ module Pacer
46
62
  graph.equals g
47
63
  end
48
64
 
65
+ def chain_route(args_hash)
66
+ Pacer::RouteBuilder.current.chain self, args_hash
67
+ end
68
+
49
69
  # The arguments passed to the pipe constructor.
50
70
  #
51
71
  # @overload pipe_args
@@ -7,6 +7,7 @@ module Pacer
7
7
  class LogicError < Error; end
8
8
  class ClientError < LogicError; end
9
9
  class TransactionConcludedError < ClientError; end
10
+ class NestedTransactionError < ClientError; end
10
11
  class NestedTransactionRollback < ClientError; end
11
12
  class NestedMockTransactionRollback < NestedTransactionRollback; end
12
13
  class MockTransactionRollback < ClientError; end
@@ -44,6 +44,8 @@ module Pacer
44
44
  block, negate = @future_filter
45
45
  @future_filter = nil
46
46
  route = block.call(Pacer::Route.empty(self))
47
+ route = route.back while route.remove_from_lookahead
48
+ route = route.lookahead_replacement.call(route) if route.lookahead_replacement
47
49
  if min or max
48
50
  route = route.has_count_route(:min => min, :max => max).is(true)
49
51
  end
@@ -1,14 +1,9 @@
1
1
  module Pacer
2
2
  import com.tinkerpop.blueprints.TransactionalGraph
3
3
 
4
- # Add features to transactions to allow them to be more rubyish and
5
- # more convenient to use.
6
- #
7
- # TODO: the method names in this module need to be cleaned up.
8
- # TODO: some methods may be able to be eliminated.
9
4
  module GraphTransactionsMixin
10
5
  def in_transaction?
11
- threadlocal_graph_info[:tx_depth] > 0
6
+ threadlocal_graph_info.fetch(:tx_depth, 0) > 0
12
7
  end
13
8
 
14
9
  # Basic usage:
@@ -34,8 +29,12 @@ module Pacer
34
29
  # Also considering a 3rd callback that could be used to get info about the
35
30
  # current transaction stack like depth, number of commits/rollbacks, possibly the number of
36
31
  # mutations it wraps and even some event registration stuff could be made available.
37
- def transaction
38
- commit, rollback = start_transaction!
32
+ #
33
+ # opts:
34
+ # nesting: true -- allow mock nested transactions
35
+ # nesting: false -- (default) raise an exception instead of starting a nested transaction
36
+ def transaction(opts = {})
37
+ commit, rollback = start_transaction! opts
39
38
  begin
40
39
  r = yield commit, rollback
41
40
  commit.call
@@ -55,15 +54,17 @@ module Pacer
55
54
  graphs[blueprints_graph.object_id] ||= {}
56
55
  end
57
56
 
58
- def start_transaction!
57
+ def start_transaction!(opts)
59
58
  tgi = threadlocal_graph_info
60
59
  tx_depth = tgi[:tx_depth] ||= 0
61
60
  tgi[:tx_depth] += 1
62
61
  if blueprints_graph.is_a? TransactionalGraph
63
62
  if tx_depth == 0
64
63
  base_tx_finalizers
65
- else
64
+ elsif opts[:nesting] == true
66
65
  nested_tx_finalizers
66
+ else
67
+ fail NestedTransactionError, "To use nested transactions, use nesting: true"
67
68
  end
68
69
  else
69
70
  if tx_depth == 0
@@ -75,14 +76,14 @@ module Pacer
75
76
  end
76
77
 
77
78
  def finish_transaction!
78
- threadlocal_graph_info[:tx_depth] -= 1
79
+ threadlocal_graph_info[:tx_depth] -= 1 rescue nil
79
80
  end
80
81
 
81
82
  def base_tx_finalizers
82
83
  tx_id = threadlocal_graph_info[:tx_id] = rand
83
84
  commit = -> do
84
85
  if tx_id != threadlocal_graph_info[:tx_id]
85
- fail InternalError
86
+ fail InternalError, 'Can not commit transaction outside its original block'
86
87
  end
87
88
  puts "transaction committed" if Pacer.verbose == :very
88
89
  blueprints_graph.stopTransaction TransactionalGraph::Conclusion::SUCCESS
@@ -0,0 +1,29 @@
1
+ module Pacer::Graph
2
+ class HashIndex
3
+ attr_reader :name, :type
4
+
5
+ def initialize(element_type, name)
6
+ @type = type
7
+ @name = name
8
+ @data = Hash.new do |h, k|
9
+ h[k] = Hash.new { |h, k| h[k] = Set[] }
10
+ end
11
+ end
12
+
13
+ def get(key, value)
14
+ Pacer::Pipes::EnumerablePipe.new data[key][value]
15
+ end
16
+
17
+ def put(key, value, element)
18
+ data[key][value] << element
19
+ end
20
+
21
+ def count(key, value)
22
+ data[key][value].count
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :data
28
+ end
29
+ end
@@ -188,10 +188,6 @@ module Pacer
188
188
  end
189
189
 
190
190
  module Encoding
191
- def sanitize_properties(props)
192
- encoder.sanitize_properties props
193
- end
194
-
195
191
  def encode_property(value)
196
192
  encoder.encode_property value
197
193
  end
@@ -270,7 +266,7 @@ module Pacer
270
266
  # @option opts [true] :create create the index if it doesn't exist
271
267
  # @return [Pacer::IndexMixin]
272
268
  def index(name, type = nil, opts = {})
273
- return unless features.supportsIndices
269
+ return temp_index(name, type, opts) unless features.supportsIndices
274
270
  name = name.to_s
275
271
  if type
276
272
  type = index_class element_type type
@@ -285,7 +281,7 @@ module Pacer
285
281
  end
286
282
 
287
283
  def drop_index(idx)
288
- return unless features.supportsIndices
284
+ return drop_temp_index(idx) unless features.supportsIndices
289
285
  if idx.is_a? String or idx.is_a? Symbol
290
286
  blueprints_graph.dropIndex idx
291
287
  else
@@ -293,6 +289,27 @@ module Pacer
293
289
  end
294
290
  end
295
291
 
292
+ def temp_index(name, type = nil, opts = {})
293
+ @temp_indices ||= {}
294
+ idx = @temp_indices[name]
295
+ unless idx
296
+ if name and type and opts[:create]
297
+ idx = @temp_indices[name] = Pacer::Graph::HashIndex.new type, name
298
+ elsif opts[:create]
299
+ idx = Pacer::Graph::HashIndex.new type, nil
300
+ end
301
+ end
302
+ Pacer::Wrappers::IndexWrapper.new self, idx, idx.type if idx
303
+ end
304
+
305
+ def drop_temp_index(idx)
306
+ @temp_indices.delete idx.name
307
+ end
308
+
309
+ def drop_temp_indices
310
+ @temp_indices = {}
311
+ end
312
+
296
313
  # Return an object that can be compared to the return value of
297
314
  # Index#index_class.
298
315
  def index_class(et)
@@ -1,20 +1,25 @@
1
1
  module Pacer
2
2
  class SimpleEncoder
3
- def self.sanitize_properties(props)
4
- props
5
- end
3
+ JBoolean = java.lang.Boolean
4
+ JFalse = false.to_java
6
5
 
7
6
  def self.encode_property(value)
8
7
  if value.is_a? String
9
8
  value = value.strip
10
9
  value unless value == ''
10
+ elsif false == value
11
+ JFalse
11
12
  else
12
13
  value
13
14
  end
14
15
  end
15
16
 
16
17
  def self.decode_property(value)
17
- value
18
+ if value.is_a? JBoolean and value == JFalse
19
+ false
20
+ else
21
+ value
22
+ end
18
23
  end
19
24
  end
20
25
  end
@@ -5,13 +5,6 @@ module Pacer
5
5
  # Neo4j could and for everything else it uses (slow (but easy))
6
6
  # human-readable YAML encoding.
7
7
  class YamlEncoder
8
- def self.sanitize_properties(props)
9
- pairs = props.map do |name, value|
10
- [name, encode_property(value)]
11
- end
12
- Hash[pairs]
13
- end
14
-
15
8
  def self.encode_property(value)
16
9
  case value
17
10
  when nil
@@ -22,12 +15,12 @@ module Pacer
22
15
  value
23
16
  when Numeric
24
17
  if value.is_a? Bignum
25
- value.to_yaml
18
+ dump value
26
19
  else
27
- value
20
+ value.to_java
28
21
  end
29
22
  when true, false
30
- value
23
+ value.to_java
31
24
  when Array
32
25
  if value.length == 0
33
26
  value_type = Fixnum
@@ -51,33 +44,27 @@ module Pacer
51
44
  when String
52
45
  value.to_java :string
53
46
  else
54
- value.to_yaml
47
+ dump value
55
48
  end
56
49
  else
57
- value.to_yaml
50
+ dump value
58
51
  end
59
52
  end
60
53
 
61
- if 'x'.to_yaml[0, 5] == '%YAML'
62
- def self.decode_property(value)
63
- if value.is_a? String and value[0, 5] == '%YAML'
64
- YAML.load(value)
65
- elsif value.is_a? ArrayJavaProxy
66
- value.to_a
67
- else
68
- value
69
- end
70
- end
71
- else
72
- def self.decode_property(value)
73
- if value.is_a? String and value[0, 3] == '---'
74
- YAML.load(value)
75
- elsif value.is_a? ArrayJavaProxy
76
- value.to_a
77
- else
78
- value
79
- end
54
+ def self.decode_property(value)
55
+ if value.is_a? String and value[0, 1] == ' '
56
+ YAML.load(value[1..-1])
57
+ elsif value.is_a? ArrayJavaProxy
58
+ value.to_a
59
+ else
60
+ value
80
61
  end
81
62
  end
63
+
64
+ private
65
+
66
+ def self.dump(value)
67
+ " #{ YAML.dump value }"
68
+ end
82
69
  end
83
70
  end
@@ -0,0 +1,93 @@
1
+ module Pacer
2
+ import com.tinkerpop.blueprints.Graph
3
+ import com.tinkerpop.blueprints.Element
4
+ import com.tinkerpop.blueprints.Vertex
5
+ import com.tinkerpop.blueprints.Edge
6
+
7
+ module Core end
8
+ module Routes end
9
+ module Wrappers end
10
+ module Support end
11
+ module Visitors end
12
+ module Filter end
13
+ module Transform end
14
+ module SideEffect end
15
+ end
16
+
17
+
18
+ require 'pacer/exceptions'
19
+ require 'pacer/pipes'
20
+
21
+ require 'pacer/core/route'
22
+ require 'pacer/core/graph'
23
+ require 'pacer/core/side_effect'
24
+
25
+ require 'pacer/graph/graph_transactions_mixin'
26
+ require 'pacer/graph/pacer_graph'
27
+ require 'pacer/graph/simple_encoder'
28
+ require 'pacer/graph/yaml_encoder'
29
+ require 'pacer/graph/graph_ml'
30
+ require 'pacer/graph/hash_index'
31
+
32
+ require 'pacer/route/mixin/bulk_operations'
33
+ require 'pacer/route/mixin/route_operations'
34
+
35
+ require 'forwardable'
36
+ require 'pacer/wrappers/element_wrapper'
37
+ require 'pacer/wrappers/vertex_wrapper'
38
+ require 'pacer/wrappers/edge_wrapper'
39
+ require 'pacer/wrappers/index_wrapper'
40
+ require 'pacer/wrappers/wrapper_selector'
41
+ require 'pacer/wrappers/wrapping_pipe_function'
42
+
43
+ require 'pacer/route_builder'
44
+ require 'pacer/function_resolver'
45
+ require 'pacer/route'
46
+
47
+ require 'pacer/blueprints/tg'
48
+ require 'pacer/blueprints/ruby_graph'
49
+ require 'pacer/blueprints/multi_graph'
50
+
51
+ require 'pacer/support/array_list'
52
+ require 'pacer/support/enumerable'
53
+ require 'pacer/support/proc'
54
+ require 'pacer/support/hash'
55
+ require 'pacer/support/native_exception'
56
+ require 'pacer/support/nil_class'
57
+
58
+ require 'pacer/utils'
59
+
60
+ require 'pacer/visitors/visits_section'
61
+ require 'pacer/visitors/section'
62
+
63
+ require 'pacer/filter/collection_filter'
64
+ require 'pacer/filter/empty_filter'
65
+ require 'pacer/filter/future_filter'
66
+ require 'pacer/filter/property_filter'
67
+ require 'pacer/filter/range_filter'
68
+ require 'pacer/filter/uniq_filter'
69
+ require 'pacer/filter/index_filter'
70
+ require 'pacer/filter/loop_filter'
71
+ require 'pacer/filter/block_filter'
72
+ require 'pacer/filter/object_filter'
73
+ require 'pacer/filter/where_filter'
74
+ require 'pacer/filter/random_filter'
75
+
76
+ require 'pacer/transform/cap'
77
+ require 'pacer/transform/stream_sort'
78
+ require 'pacer/transform/stream_uniq'
79
+ require 'pacer/transform/gather'
80
+ require 'pacer/transform/map'
81
+ require 'pacer/transform/process'
82
+ require 'pacer/transform/join'
83
+ require 'pacer/transform/path'
84
+ require 'pacer/transform/scatter'
85
+ require 'pacer/transform/has_count_cap'
86
+ require 'pacer/transform/sort_section'
87
+
88
+ require 'pacer/side_effect/aggregate'
89
+ require 'pacer/side_effect/as'
90
+ require 'pacer/side_effect/group_count'
91
+ require 'pacer/side_effect/is_unique'
92
+ require 'pacer/side_effect/counted'
93
+ require 'pacer/side_effect/visitor'
@@ -24,7 +24,7 @@ module Pacer::Routes
24
24
  target_graph.in_bulk_job = true
25
25
  size ||= target_graph.bulk_job_size
26
26
  counter = 0
27
- target_graph.transaction do |commit, rollback|
27
+ target_graph.transaction(nesting: true) do |commit, rollback|
28
28
  each_slice(size) do |slice|
29
29
  print counter if Pacer.verbose?
30
30
  counter += size
data/lib/pacer/route.rb CHANGED
@@ -1,155 +1,4 @@
1
- [Pacer::Core::Route, Pacer::Wrappers::ElementWrapper].each do |klass|
2
- klass.class_eval %{
3
- def chain_route(args_hash)
4
- Pacer::RouteBuilder.current.chain self, args_hash
5
- end
6
- }
7
- end
8
-
9
1
  module Pacer
10
-
11
- class RouteBuilder
12
- class << self
13
- attr_writer :current
14
-
15
- def current
16
- @current ||= RouteBuilder.new
17
- end
18
- end
19
-
20
- attr_reader :types
21
-
22
- def initialize
23
- @types = Hash.new do |h, type_def|
24
- h[type_def] = Class.new(Route) do
25
- type_def.each do |mods|
26
- mods.each do |mod|
27
- include mod
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- def chain(source, args)
35
- types[type_def(source, args)].new source, configuration(source, args), arguments(source, args)
36
- end
37
-
38
- protected
39
-
40
- def source_value(source, name)
41
- source.send name if source.respond_to? name
42
- end
43
-
44
- def type_def(source, args)
45
- [
46
- type_modules(source, args),
47
- function_modules(source, args),
48
- other_modules(source, args),
49
- extension_modules(source, args)
50
- ]
51
- end
52
-
53
- def configuration(source, args)
54
- {
55
- element_type: element_type(source, args),
56
- graph: graph(source, args),
57
- extensions: extensions(source, args),
58
- wrapper: wrapper(source, args),
59
- function: function_modules(source, args).first
60
- }
61
- end
62
-
63
- def arguments(source, args)
64
- args.reject do |key, val|
65
- Set[:element_type, :wrapper, :extensions, :modules, :graph, :back, :filter, :side_effect, :transform, :visitor].include? key
66
- end
67
- end
68
-
69
- def graph(source, args)
70
- args[:graph] || source_value(source, :graph)
71
- end
72
-
73
- def element_type(source, args)
74
- et = args[:element_type] || source_value(source, :element_type)
75
- if not et
76
- fail ClientError, "No element_type specified or inferred"
77
- end
78
- if not graph(source, args) and (et == :vertex or et == :edge or et == :mixed)
79
- fail ClientError, "Element type #{ et.inspect } specified, but no graph specified."
80
- end
81
- et
82
- end
83
-
84
- def type_modules(source, args)
85
- case element_type source, args
86
- when :vertex
87
- [Pacer::Core::Graph::ElementRoute, Pacer::Core::Graph::VerticesRoute]
88
- when :edge
89
- [Pacer::Core::Graph::ElementRoute, Pacer::Core::Graph::EdgesRoute]
90
- when :mixed
91
- [Pacer::Core::Graph::ElementRoute, Pacer::Core::Graph::MixedRoute]
92
- else
93
- []
94
- end
95
- end
96
-
97
- def other_modules(source, args)
98
- [*args[:modules]]
99
- end
100
-
101
- def type_from_source?(source, args)
102
- element_type(source, args) == source_value(source, :element_type)
103
- end
104
-
105
- def wrapper(source, args)
106
- args.fetch(:wrapper) do
107
- source_value(source, :wrapper) if type_from_source? source, args
108
- end
109
- end
110
-
111
- def extensions(source, args)
112
- exts = args.fetch(:extensions) do
113
- source_value(source, :extensions) if type_from_source? source, args
114
- end
115
- if exts.is_a? Set
116
- exts.to_a
117
- elsif exts.is_a? Module
118
- [exts]
119
- elsif exts.is_a? Array
120
- exts.uniq
121
- else
122
- []
123
- end
124
- end
125
-
126
- def all_extensions(source, args)
127
- w = wrapper source, args
128
- exts = extensions source, args
129
- if w and exts
130
- (w.extensions + exts).uniq
131
- elsif w
132
- w.extensions
133
- elsif exts
134
- exts
135
- else
136
- []
137
- end
138
- end
139
-
140
- def extension_modules(source, args)
141
- all_extensions(source, args).uniq.select do |mod|
142
- mod.respond_to?(:const_defined?) and mod.const_defined? :Route
143
- end.map { |mod| mod::Route }
144
- end
145
-
146
-
147
- def function_modules(source, args)
148
- FunctionResolver.function(args).compact
149
- end
150
- end
151
-
152
-
153
2
  # The base class for almost everything in Pacer. Every route is an
154
3
  # instance of this class with a variety of modules mixed into the
155
4
  # instance at runtime.