pacer 0.9.1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. data/.autotest +8 -0
  2. data/.document +5 -0
  3. data/.gitignore +26 -0
  4. data/.rspec +1 -0
  5. data/.rvmrc +0 -0
  6. data/CONTRIBUTORS +5 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +24 -0
  9. data/README.md +187 -0
  10. data/Rakefile +49 -0
  11. data/autotest/discover.rb +1 -0
  12. data/bin/autospec +16 -0
  13. data/bin/autotest +16 -0
  14. data/bin/rake +16 -0
  15. data/bin/rcov +16 -0
  16. data/bin/rspec +16 -0
  17. data/bin/yard +16 -0
  18. data/bin/yardoc +16 -0
  19. data/lib/pacer/blueprints/extensions.rb +77 -0
  20. data/lib/pacer/blueprints/multi_graph.rb +121 -0
  21. data/lib/pacer/blueprints/ruby_graph.rb +199 -0
  22. data/lib/pacer/blueprints/tg.rb +100 -0
  23. data/lib/pacer/blueprints.rb +4 -0
  24. data/lib/pacer/core/graph/edges_route.rb +92 -0
  25. data/lib/pacer/core/graph/element_route.rb +171 -0
  26. data/lib/pacer/core/graph/graph_index_route.rb +48 -0
  27. data/lib/pacer/core/graph/graph_route.rb +55 -0
  28. data/lib/pacer/core/graph/mixed_route.rb +96 -0
  29. data/lib/pacer/core/graph/vertices_route.rb +220 -0
  30. data/lib/pacer/core/graph.rb +13 -0
  31. data/lib/pacer/core/route.rb +502 -0
  32. data/lib/pacer/core/side_effect.rb +11 -0
  33. data/lib/pacer/core.rb +8 -0
  34. data/lib/pacer/exceptions.rb +11 -0
  35. data/lib/pacer/extensions/block_filter_element.rb +22 -0
  36. data/lib/pacer/extensions.rb +6 -0
  37. data/lib/pacer/filter/block_filter.rb +31 -0
  38. data/lib/pacer/filter/collection_filter.rb +109 -0
  39. data/lib/pacer/filter/empty_filter.rb +70 -0
  40. data/lib/pacer/filter/future_filter.rb +68 -0
  41. data/lib/pacer/filter/index_filter.rb +30 -0
  42. data/lib/pacer/filter/loop_filter.rb +95 -0
  43. data/lib/pacer/filter/object_filter.rb +55 -0
  44. data/lib/pacer/filter/property_filter/edge_filters.rb +93 -0
  45. data/lib/pacer/filter/property_filter/filters.rb +269 -0
  46. data/lib/pacer/filter/property_filter.rb +111 -0
  47. data/lib/pacer/filter/random_filter.rb +13 -0
  48. data/lib/pacer/filter/range_filter.rb +104 -0
  49. data/lib/pacer/filter/uniq_filter.rb +12 -0
  50. data/lib/pacer/filter/where_filter/node_visitor.rb +280 -0
  51. data/lib/pacer/filter/where_filter.rb +47 -0
  52. data/lib/pacer/filter.rb +17 -0
  53. data/lib/pacer/function_resolver.rb +43 -0
  54. data/lib/pacer/graph/edge_mixin.rb +127 -0
  55. data/lib/pacer/graph/element_mixin.rb +202 -0
  56. data/lib/pacer/graph/graph_indices_mixin.rb +93 -0
  57. data/lib/pacer/graph/graph_mixin.rb +361 -0
  58. data/lib/pacer/graph/graph_transactions_mixin.rb +207 -0
  59. data/lib/pacer/graph/index_mixin.rb +30 -0
  60. data/lib/pacer/graph/vertex_mixin.rb +119 -0
  61. data/lib/pacer/graph.rb +14 -0
  62. data/lib/pacer/pipe/blackbox_pipeline.rb +48 -0
  63. data/lib/pacer/pipe/block_filter_pipe.rb +38 -0
  64. data/lib/pacer/pipe/collection_filter_pipe.rb +10 -0
  65. data/lib/pacer/pipe/cross_product_transform_pipe.rb +48 -0
  66. data/lib/pacer/pipe/enumerable_pipe.rb +30 -0
  67. data/lib/pacer/pipe/expandable_pipe.rb +63 -0
  68. data/lib/pacer/pipe/id_collection_filter_pipe.rb +33 -0
  69. data/lib/pacer/pipe/is_empty_pipe.rb +30 -0
  70. data/lib/pacer/pipe/is_unique_pipe.rb +61 -0
  71. data/lib/pacer/pipe/label_collection_filter_pipe.rb +21 -0
  72. data/lib/pacer/pipe/label_prefix_pipe.rb +21 -0
  73. data/lib/pacer/pipe/loop_pipe.rb +86 -0
  74. data/lib/pacer/pipe/map_pipe.rb +36 -0
  75. data/lib/pacer/pipe/never_pipe.rb +9 -0
  76. data/lib/pacer/pipe/process_pipe.rb +37 -0
  77. data/lib/pacer/pipe/property_comparison_pipe.rb +40 -0
  78. data/lib/pacer/pipe/ruby_pipe.rb +25 -0
  79. data/lib/pacer/pipe/simple_visitor_pipe.rb +43 -0
  80. data/lib/pacer/pipe/stream_sort_pipe.rb +84 -0
  81. data/lib/pacer/pipe/stream_uniq_pipe.rb +33 -0
  82. data/lib/pacer/pipe/type_filter_pipe.rb +22 -0
  83. data/lib/pacer/pipe/unary_transform_pipe.rb +59 -0
  84. data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +26 -0
  85. data/lib/pacer/pipe/visitor_pipe.rb +67 -0
  86. data/lib/pacer/pipes.rb +61 -0
  87. data/lib/pacer/route/mixin/bulk_operations.rb +52 -0
  88. data/lib/pacer/route/mixin/route_operations.rb +107 -0
  89. data/lib/pacer/route/mixin/variable_route_module.rb +26 -0
  90. data/lib/pacer/route/mixins.rb +3 -0
  91. data/lib/pacer/route.rb +228 -0
  92. data/lib/pacer/routes.rb +6 -0
  93. data/lib/pacer/side_effect/aggregate.rb +31 -0
  94. data/lib/pacer/side_effect/counted.rb +30 -0
  95. data/lib/pacer/side_effect/group_count.rb +44 -0
  96. data/lib/pacer/side_effect/is_unique.rb +32 -0
  97. data/lib/pacer/side_effect/section.rb +25 -0
  98. data/lib/pacer/side_effect/visitor.rb +37 -0
  99. data/lib/pacer/side_effect.rb +11 -0
  100. data/lib/pacer/support/array_list.rb +28 -0
  101. data/lib/pacer/support/enumerable.rb +100 -0
  102. data/lib/pacer/support/hash.rb +9 -0
  103. data/lib/pacer/support/iterator_mixins.rb +110 -0
  104. data/lib/pacer/support/native_exception.rb +22 -0
  105. data/lib/pacer/support/proc.rb +16 -0
  106. data/lib/pacer/support.rb +10 -0
  107. data/lib/pacer/transform/cap.rb +50 -0
  108. data/lib/pacer/transform/gather.rb +9 -0
  109. data/lib/pacer/transform/has_count_cap.rb +41 -0
  110. data/lib/pacer/transform/join.rb +181 -0
  111. data/lib/pacer/transform/map.rb +23 -0
  112. data/lib/pacer/transform/path.rb +50 -0
  113. data/lib/pacer/transform/process.rb +23 -0
  114. data/lib/pacer/transform/scatter.rb +23 -0
  115. data/lib/pacer/transform/sort_section.rb +103 -0
  116. data/lib/pacer/transform/stream_sort.rb +21 -0
  117. data/lib/pacer/transform/stream_uniq.rb +21 -0
  118. data/lib/pacer/transform.rb +16 -0
  119. data/lib/pacer/utils/graph_analysis.rb +112 -0
  120. data/lib/pacer/utils/trie.rb +93 -0
  121. data/lib/pacer/utils/tsort.rb +65 -0
  122. data/lib/pacer/utils/y_files.rb +127 -0
  123. data/lib/pacer/utils.rb +10 -0
  124. data/lib/pacer/version.rb +13 -0
  125. data/lib/pacer/wrappers/edge_wrapper.rb +51 -0
  126. data/lib/pacer/wrappers/element_wrapper.rb +78 -0
  127. data/lib/pacer/wrappers/new_element.rb +106 -0
  128. data/lib/pacer/wrappers/vertex_wrapper.rb +51 -0
  129. data/lib/pacer/wrappers.rb +19 -0
  130. data/lib/pacer-0.9.1.1-standalone.jar +0 -0
  131. data/lib/pacer.rb +290 -0
  132. data/pacer.gemspec +30 -0
  133. data/pom/standalone.xml +22 -0
  134. data/pom.xml +124 -0
  135. data/samples/grateful-dead.xml +26380 -0
  136. data/samples/grateful_dead.rb +63 -0
  137. data/samples/profile.rb +15 -0
  138. data/spec/data/grateful-dead.xml +26380 -0
  139. data/spec/data/pacer.graphml +319 -0
  140. data/spec/pacer/blueprints/dex_spec.rb +172 -0
  141. data/spec/pacer/blueprints/neo4j_spec.rb +177 -0
  142. data/spec/pacer/blueprints/tg_spec.rb +128 -0
  143. data/spec/pacer/core/graph/edges_route_spec.rb +52 -0
  144. data/spec/pacer/core/graph/element_route_spec.rb +46 -0
  145. data/spec/pacer/core/graph/graph_route_spec.rb +94 -0
  146. data/spec/pacer/core/graph/vertices_route_spec.rb +169 -0
  147. data/spec/pacer/core/route_spec.rb +197 -0
  148. data/spec/pacer/filter/collection_filter_spec.rb +19 -0
  149. data/spec/pacer/filter/empty_filter_spec.rb +29 -0
  150. data/spec/pacer/filter/future_filter_spec.rb +97 -0
  151. data/spec/pacer/filter/loop_filter_spec.rb +31 -0
  152. data/spec/pacer/filter/property_filter_spec.rb +111 -0
  153. data/spec/pacer/filter/random_filter_spec.rb +17 -0
  154. data/spec/pacer/filter/uniq_filter_spec.rb +18 -0
  155. data/spec/pacer/filter/where_filter_spec.rb +93 -0
  156. data/spec/pacer/graph/edge_mixin_spec.rb +116 -0
  157. data/spec/pacer/graph/element_mixin_spec.rb +297 -0
  158. data/spec/pacer/graph/graph_mixin_spec.rb +538 -0
  159. data/spec/pacer/graph/index_mixin_spec.rb +0 -0
  160. data/spec/pacer/graph/vertex_mixin_spec.rb +192 -0
  161. data/spec/pacer/pipe/block_filter_pipe_spec.rb +0 -0
  162. data/spec/pacer/pipe/labels_filter_pipe_spec.rb +0 -0
  163. data/spec/pacer/pipe/ruby_pipe_spec.rb +0 -0
  164. data/spec/pacer/pipe/type_filter_pipe_spec.rb +0 -0
  165. data/spec/pacer/route/mixin/base_spec.rb +419 -0
  166. data/spec/pacer/route/mixin/bulk_operations_spec.rb +30 -0
  167. data/spec/pacer/route/mixin/route_operations_spec.rb +127 -0
  168. data/spec/pacer/support/array_list_spec.rb +0 -0
  169. data/spec/pacer/support/enumerable_spec.rb +115 -0
  170. data/spec/pacer/transform/join_spec.rb +138 -0
  171. data/spec/pacer/transform/path_spec.rb +54 -0
  172. data/spec/pacer/utils/tsort_spec.rb +89 -0
  173. data/spec/pacer/wrapper/edge_wrapper_spec.rb +33 -0
  174. data/spec/pacer/wrapper/element_wrapper_spec.rb +169 -0
  175. data/spec/pacer/wrapper/vertex_wrapper_spec.rb +33 -0
  176. data/spec/pacer_spec.rb +0 -0
  177. data/spec/spec_helper.rb +91 -0
  178. data/spec/support/contexts.rb +14 -0
  179. data/spec/support/graph_runner.rb +142 -0
  180. data/spec/support/matchers.rb +19 -0
  181. data/spec/support/use_transactions.rb +31 -0
  182. data/spec/tackle/simple_mixin.rb +21 -0
  183. data/spec/tackle/tinkerpop_graph_mixins.rb +60 -0
  184. metadata +364 -0
@@ -0,0 +1,111 @@
1
+ require 'pacer/filter/property_filter/filters'
2
+ require 'pacer/filter/property_filter/edge_filters'
3
+
4
+ module Pacer
5
+ class Route
6
+ class << self
7
+ def filters(filters)
8
+ if filters? filters
9
+ filters
10
+ elsif filters? filters.first
11
+ filters.first
12
+ else
13
+ Pacer::Filter::PropertyFilter::Filters.new(filters)
14
+ end
15
+ end
16
+
17
+ def edge_filters(filters)
18
+ if filters? filters
19
+ filters
20
+ elsif filters? filters.first
21
+ filters.first
22
+ else
23
+ Pacer::Filter::PropertyFilter::EdgeFilters.new(filters)
24
+ end
25
+ end
26
+
27
+ def filters?(filters)
28
+ filters.is_a? Pacer::Filter::PropertyFilter::Filters
29
+ end
30
+
31
+ def property_filter_before(base, filters, block)
32
+ filters = Pacer::Route.edge_filters(filters)
33
+ filters.blocks = [block] if block
34
+ if filters.extensions_only? and base.is_a? Route
35
+ base.wrapper ||= filters.wrapper if filters.wrapper
36
+ base.add_extensions(filters.extensions)
37
+ yield base
38
+ elsif filters and filters.any?
39
+ yield new(:back => base, :filter => :property, :filters => filters)
40
+ else
41
+ yield base
42
+ end
43
+ end
44
+
45
+ def property_filter(base, filters, block)
46
+ filters = Pacer::Route.edge_filters(filters)
47
+ filters.blocks = [block] if block
48
+ if filters.extensions_only? and base.is_a? Route
49
+ base.wrapper ||= filters.wrapper if filters.wrapper
50
+ base.add_extensions(filters.extensions)
51
+ elsif filters and filters.any?
52
+ new(:back => base, :filter => :property, :filters => filters)
53
+ elsif Pacer.vertex? base
54
+ new(:back => base, :pipe_class => Pacer::Pipes::IdentityPipe)
55
+ elsif Pacer.edge? base
56
+ new(:back => base, :pipe_class => Pacer::Pipes::IdentityPipe)
57
+ else
58
+ base
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ module Filter
65
+ module PropertyFilter
66
+ #import com.tinkerpop.pipes.filter.LabelCollectionFilterPipe
67
+ import com.tinkerpop.pipes.filter.PropertyFilterPipe
68
+
69
+ def filters=(f)
70
+ if f.is_a? Filters
71
+ @filters = f
72
+ else
73
+ @filters = EdgeFilters.new(f)
74
+ end
75
+ self.wrapper ||= f.wrapper if f.wrapper
76
+ add_extensions f.extensions
77
+ end
78
+
79
+ # Return an array of filter options for the current route.
80
+ def filters
81
+ @filters ||= EdgeFilters.new(nil)
82
+ end
83
+
84
+ def block=(block)
85
+ if block
86
+ filters.blocks = [block]
87
+ else
88
+ filters.blocks = []
89
+ end
90
+ end
91
+
92
+ def block
93
+ filters.blocks.first
94
+ end
95
+
96
+ protected
97
+
98
+ def build_pipeline
99
+ filters.build_pipeline(self, *pipe_source)
100
+ end
101
+
102
+ def inspect_string
103
+ if filters.any?
104
+ "#{inspect_class_name}(#{filters})"
105
+ else
106
+ inspect_class_name
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,13 @@
1
+ module Pacer
2
+ module Core
3
+ module Route
4
+ # Return elements based on a bias:1 chance.
5
+ #
6
+ # If given an integer (n) > 0, bias is calcualated at 1 / n.
7
+ def random(bias = 0.5)
8
+ bias = 1 / bias.to_f if bias.is_a? Fixnum and bias > 0
9
+ chain_route :pipe_class => Pacer::Pipes::RandomFilterPipe, :pipe_args => bias
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,104 @@
1
+ module Pacer
2
+ module Routes
3
+ module RouteOperations
4
+ def range(from, to)
5
+ args = { :filter => :range }
6
+ args[:begin] = from if from
7
+ args[:end] = to if to
8
+ chain_route args
9
+ end
10
+
11
+ def limit(max)
12
+ chain_route :filter => :range, :limit => max
13
+ end
14
+
15
+ def offset(amount)
16
+ chain_route :filter => :range, :offset => amount
17
+ end
18
+
19
+ def at(pos)
20
+ chain_route :filter => :range, :index => pos
21
+ end
22
+ end
23
+ end
24
+
25
+ module Filter
26
+ module RangeFilter
27
+ def limit(n = nil)
28
+ @limit = n
29
+ if range.begin == -1
30
+ @range = range.begin...n
31
+ else
32
+ @range = range.begin...(range.begin + n)
33
+ end
34
+ self
35
+ end
36
+
37
+ def limit=(n)
38
+ limit n
39
+ n
40
+ end
41
+
42
+ def offset(n = nil)
43
+ s = n
44
+ s += 1 if range.begin == -1
45
+ if range.end == -1
46
+ @range = (range.begin + s)..-1
47
+ elsif range.exclude_end?
48
+ @range = (range.begin + s)...(range.end + n)
49
+ else
50
+ @range = (range.begin + s)..(range.end + n)
51
+ end
52
+ self
53
+ end
54
+
55
+ def offset=(n)
56
+ offset n
57
+ n
58
+ end
59
+
60
+ def range=(range)
61
+ @range = range
62
+ end
63
+
64
+ def begin=(n)
65
+ @range = n..range.end
66
+ end
67
+
68
+ def end=(n)
69
+ @range = range.begin..n
70
+ end
71
+
72
+ def index=(index)
73
+ @range = index..index
74
+ end
75
+
76
+ def range
77
+ @range ||= -1..-1
78
+ end
79
+
80
+ protected
81
+
82
+ def attach_pipe(end_pipe)
83
+ from = @range.begin
84
+ to = @range.end
85
+ if @range.exclude_end?
86
+ if to == 0
87
+ pipe = Pacer::Pipes::NeverPipe.new
88
+ pipe.set_starts end_pipe if end_pipe
89
+ return pipe
90
+ elsif to > 0
91
+ to -= 1
92
+ end
93
+ end
94
+ pipe = Pacer::Pipes::RangeFilterPipe.new from, to
95
+ pipe.set_starts end_pipe if end_pipe
96
+ pipe
97
+ end
98
+
99
+ def inspect_string
100
+ "#{ inspect_class_name }(#{ range.inspect })"
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,12 @@
1
+ module Pacer
2
+ module Routes
3
+ module RouteOperations
4
+ # Do not return duplicate elements.
5
+ def uniq(*filters, &block)
6
+ Pacer::Route.property_filter_before(self, filters, block) do |r|
7
+ chain_route :pipe_class => Pacer::Pipes::DuplicateFilterPipe, :route_name => 'uniq'
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,280 @@
1
+ module Pacer
2
+ module Filter
3
+ module WhereFilter
4
+ class NodeVisitor
5
+ import com.tinkerpop.pipes.filter.OrFilterPipe
6
+ import com.tinkerpop.pipes.filter.FilterPipe
7
+ import com.tinkerpop.pipes.filter.AndFilterPipe
8
+ import com.tinkerpop.pipes.filter.OrFilterPipe
9
+ import com.tinkerpop.pipes.filter.ObjectFilterPipe
10
+ import com.tinkerpop.pipes.transform.PropertyPipe
11
+ import com.tinkerpop.pipes.transform.HasCountPipe
12
+ NeverPipe = Pacer::Pipes::NeverPipe
13
+ IdentityPipe = Pacer::Pipes::IdentityPipe
14
+ PropertyComparisonFilterPipe = Pacer::Pipes::PropertyComparisonFilterPipe
15
+ Pipeline = Pacer::Pipes::Pipeline
16
+ CrossProductTransformPipe = Pacer::Pipes::CrossProductTransformPipe
17
+ UnaryTransformPipe = Pacer::Pipes::UnaryTransformPipe
18
+ BlockFilterPipe = Pacer::Pipes::BlockFilterPipe
19
+
20
+ Filters = {
21
+ '==' => FilterPipe::Filter::EQUAL,
22
+ '=' => FilterPipe::Filter::EQUAL,
23
+ '!=' => FilterPipe::Filter::NOT_EQUAL,
24
+ '>' => FilterPipe::Filter::GREATER_THAN,
25
+ '<' => FilterPipe::Filter::LESS_THAN,
26
+ '>=' => FilterPipe::Filter::GREATER_THAN_EQUAL,
27
+ '<=' => FilterPipe::Filter::LESS_THAN_EQUAL
28
+ }
29
+
30
+ ReverseFilters = Filters.merge(
31
+ '<' => FilterPipe::Filter::GREATER_THAN,
32
+ '>' => FilterPipe::Filter::LESS_THAN,
33
+ '<=' => FilterPipe::Filter::GREATER_THAN_EQUAL,
34
+ '>=' => FilterPipe::Filter::LESS_THAN_EQUAL
35
+ )
36
+
37
+ COMPARITORS = %w[ == != > < >= <= ]
38
+ METHODS = %w[ + - * / % ]
39
+ REGEX_COMPARITORS = %w[ =~ !~ ]
40
+
41
+ VALID_OPERATIONS = COMPARITORS + METHODS # + REGEX_COMPARITORS
42
+
43
+ class Pipe
44
+ def initialize(pipe, *args)
45
+ @pipe = pipe
46
+ @args = args
47
+ end
48
+
49
+ attr_reader :pipe
50
+ attr_reader :args
51
+
52
+ def inspect(depth = 0)
53
+ ([" " * depth + pipe.to_s] + args.map do |arg|
54
+ if arg.is_a? Pipe or arg.is_a? Value
55
+ arg.inspect(depth + 2)
56
+ else
57
+ " " * (depth + 2) + arg.to_s
58
+ end
59
+ end).join "\n"
60
+ end
61
+
62
+ def build
63
+ pipe.new *build_args
64
+ end
65
+
66
+ def build_args
67
+ args.map do |arg|
68
+ if arg.is_a? Pipe
69
+ arg.build
70
+ elsif arg.is_a? Value
71
+ arg.value
72
+ else
73
+ arg
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ class Value
80
+ def initialize(value)
81
+ @value = value
82
+ end
83
+
84
+ def pipe; end
85
+ attr_reader :value
86
+
87
+ def inspect(depth = 0)
88
+ " " * depth + "Value: #{ value.inspect }"
89
+ end
90
+
91
+ def build
92
+ value
93
+ end
94
+
95
+ def values!
96
+ if value.is_a? Array
97
+ value.map do |v|
98
+ if v.is_a? Value
99
+ v.values!
100
+ else
101
+ raise "Arrays may not contain other properties"
102
+ end
103
+ end
104
+ else
105
+ value
106
+ end
107
+ end
108
+ end
109
+
110
+ attr_reader :route, :values
111
+
112
+ def initialize(route, values = {})
113
+ @route = route
114
+ @values = values
115
+ end
116
+
117
+ def build_comparison(a, b, name)
118
+ # TODO: support regex matches
119
+
120
+ raise "Operation not supported: #{ name }" unless VALID_OPERATIONS.include? name
121
+ if COMPARITORS.include? name
122
+ if a.is_a? Value and b.is_a? Value
123
+ if a.value.send name, b.value
124
+ Pipe.new IdentityPipe
125
+ else
126
+ Pipe.new NeverPipe
127
+ end
128
+ elsif a.pipe == PropertyPipe and b.pipe == PropertyPipe
129
+ Pipe.new PropertyComparisonFilterPipe, a, b, Filters[name]
130
+ elsif b.pipe == PropertyPipe and a.is_a? Value
131
+ Pipe.new Pipeline, b, Pipe.new(ObjectFilterPipe, a, ReverseFilters[name])
132
+ else
133
+ Pipe.new Pipeline, a, Pipe.new(ObjectFilterPipe, b, Filters[name])
134
+ end
135
+ elsif METHODS.include? name
136
+ if a.is_a? Value and b.is_a? Value
137
+ Value.new a.value.send(name, b.value)
138
+ else
139
+ Pipe.new CrossProductTransformPipe, name, a, b
140
+ end
141
+ end
142
+ end
143
+
144
+ def visitAndNode(node)
145
+ a = node.first_node.accept(self)
146
+ b = node.second_node.accept(self)
147
+
148
+ if a.pipe == AndFilterPipe and b.pipe == AndFilterPipe
149
+ Pipe.new AndFilterPipe, *a.args, *b.args
150
+ elsif a.pipe == AndFilterPipe
151
+ Pipe.new AndFilterPipe, *a.args, b
152
+ elsif b.pipe == AndFilterPipe
153
+ Pipe.new AndFilterPipe, a, *b.args
154
+ else
155
+ Pipe.new AndFilterPipe, a, b
156
+ end
157
+ end
158
+
159
+ def visitArrayNode(node)
160
+ Value.new Value.new(node.child_nodes.map { |n| n.accept self }).values!
161
+ end
162
+
163
+ def visitBignumNode(node)
164
+ Value.new node.value.to_s
165
+ end
166
+
167
+ def visitCallNode(node)
168
+ a = node.receiver_node.accept(self)
169
+ if node.args_node
170
+ b = node.args_node.child_nodes.first.accept(self)
171
+ build_comparison(a, b, node.name)
172
+ else
173
+ return a if node.name == '+'
174
+ if a.is_a? Value
175
+ Value.new a.value.send(a.name)
176
+ elsif a.pipe == PropertyPipe
177
+ Pipe.new(UnaryTransformPipe, node.name, a)
178
+ else
179
+ case node.name
180
+ when '!'
181
+ # Special case for "a == 1 and not (b == 1)", etc.
182
+ Pipe.new(Pipeline, a, Pipe.new(HasCountPipe, -1, 0), Pipe.new(ObjectFilterPipe, true, Filters['==']))
183
+ else
184
+ raise 'not sure'
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ def visitFalseNode(node)
191
+ Pipe.new NeverPipe
192
+ end
193
+
194
+ def visitFixnumNode(node)
195
+ Value.new node.value
196
+ end
197
+
198
+ def visitFloatNode(node)
199
+ Value.new node.value
200
+ end
201
+
202
+ def visitHashNode(node)
203
+ Value.new Hash[*node.child_nodes.first.accept(self).value.map { |v| v.value }]
204
+ end
205
+
206
+ def visitLocalAsgnNode(node)
207
+ a = Pipe.new PropertyPipe, node.name
208
+ b = node.value_node.accept(self)
209
+ build_comparison(a, b, '==')
210
+ end
211
+
212
+ def visitLocalVarNode(node)
213
+ Pipe.new PropertyPipe, node.name
214
+ end
215
+
216
+ def visitNewlineNode(node)
217
+ node.next_node.accept(self)
218
+ end
219
+
220
+ def visitNilNode(node)
221
+ Value.new nil
222
+ end
223
+
224
+ def visitOrNode(node)
225
+ a = node.first_node.accept(self)
226
+ b = node.second_node.accept(self)
227
+ if a.pipe == OrFilterPipe and b.pipe == OrFilterPipe
228
+ Pipe.new OrFilterPipe, *a.args, *b.args
229
+ elsif a.pipe == OrFilterPipe
230
+ Pipe.new OrFilterPipe, *a.args, b
231
+ elsif b.pipe == OrFilterPipe
232
+ Pipe.new OrFilterPipe, a, *b.args
233
+ else
234
+ Pipe.new OrFilterPipe, a, b
235
+ end
236
+ end
237
+
238
+ def visitRootNode(node)
239
+ pipe = node.body_node.accept self
240
+ if pipe.pipe == AndFilterPipe or pipe.pipe == OrFilterPipe
241
+ pipe
242
+ elsif pipe.is_a? Value
243
+ if pipe.value
244
+ Pipe.new IdentityPipe
245
+ else
246
+ Pipe.new NeverPipe
247
+ end
248
+ else
249
+ Pipe.new AndFilterPipe, pipe
250
+ end
251
+ end
252
+
253
+ def visitStrNode(node)
254
+ Value.new node.value
255
+ end
256
+
257
+ def visitSymbolNode(node)
258
+ Value.new values.fetch(node.name.to_sym, node.name.to_sym)
259
+ end
260
+
261
+ def visitTrueNode(node)
262
+ Pipe.new IdentityPipe
263
+ end
264
+
265
+ def visitVCallNode(node)
266
+ Pipe.new PropertyPipe, node.name
267
+ end
268
+
269
+ def visitYieldNode(node)
270
+ block = node.args_node.child_nodes.first.accept(self)
271
+ Pipe.new BlockFilterPipe, Value.new(route), block
272
+ end
273
+
274
+ def visitZArrayNode(node)
275
+ Value.new []
276
+ end
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,47 @@
1
+ require 'pacer/filter/where_filter/node_visitor'
2
+
3
+ module Pacer
4
+ module Routes
5
+ module RouteOperations
6
+ def where(str, values = {})
7
+ chain_route :filter => :where, :where_statement => str, :values => values
8
+ end
9
+ end
10
+ end
11
+
12
+ module Filter
13
+ module WhereFilter
14
+ attr_reader :where_statement
15
+ attr_accessor :values
16
+
17
+ def where_statement=(str)
18
+ @where_statement = str
19
+ @built = @parsed = @intermediate = nil
20
+ end
21
+
22
+ def parsed
23
+ @parsed ||= JRuby.parse @where_statement
24
+ end
25
+
26
+ def intermediate
27
+ @intermediate ||= parsed.accept(NodeVisitor.new(self, values || {}))
28
+ end
29
+
30
+ def build!
31
+ @built ||= intermediate.build
32
+ end
33
+
34
+ protected
35
+
36
+ def attach_pipe(end_pipe)
37
+ pipe = build!
38
+ pipe.setStarts end_pipe if end_pipe
39
+ pipe
40
+ end
41
+
42
+ def inspect_string
43
+ "where(#@where_statement)"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ module Pacer
2
+ module Filter
3
+ end
4
+ end
5
+
6
+ require 'pacer/filter/collection_filter'
7
+ require 'pacer/filter/empty_filter'
8
+ require 'pacer/filter/future_filter'
9
+ require 'pacer/filter/property_filter'
10
+ require 'pacer/filter/range_filter'
11
+ require 'pacer/filter/uniq_filter'
12
+ require 'pacer/filter/index_filter'
13
+ require 'pacer/filter/loop_filter'
14
+ require 'pacer/filter/block_filter'
15
+ require 'pacer/filter/object_filter'
16
+ require 'pacer/filter/where_filter'
17
+ require 'pacer/filter/random_filter'
@@ -0,0 +1,43 @@
1
+ module Pacer
2
+ module FunctionResolver
3
+ class << self
4
+ def clear_cache
5
+ @lookup_path = nil
6
+ end
7
+
8
+ def function(args)
9
+ lookup_path.each do |key, map, extension|
10
+ if value = args[key]
11
+ function = map.fetch(value, value.is_a?(Module) && value)
12
+ return [function, extension] if function
13
+ end
14
+ end
15
+ nil
16
+ end
17
+
18
+ def lookup_path
19
+ @lookup_path ||= [
20
+ [:filter, filter_map, nil],
21
+ [:transform, transform_map, nil],
22
+ [:side_effect, side_effect_map, Pacer::Core::SideEffect]
23
+ ]
24
+ end
25
+
26
+ def filter_map
27
+ Hash[Pacer::Filter.constants.map { |name| [symbolize_module_name(name), Pacer::Filter.const_get(name)] }]
28
+ end
29
+
30
+ def side_effect_map
31
+ Hash[Pacer::SideEffect.constants.map { |name| [symbolize_module_name(name), Pacer::SideEffect.const_get(name)] }]
32
+ end
33
+
34
+ def transform_map
35
+ Hash[Pacer::Transform.constants.map { |name| [symbolize_module_name(name), Pacer::Transform.const_get(name)] }]
36
+ end
37
+
38
+ def symbolize_module_name(name)
39
+ name.to_s.sub(/(Filter|SideEffect|Transform)$/, '').gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase.to_sym
40
+ end
41
+ end
42
+ end
43
+ end