pacer 0.9.1.1-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 (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