pacer 1.0.2-java → 1.0.3-java

Sign up to get free protection for your applications and to get access to all the features.
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.