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.
- data/.autotest +8 -0
- data/.document +5 -0
- data/.gitignore +26 -0
- data/.rspec +1 -0
- data/.rvmrc +0 -0
- data/CONTRIBUTORS +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +24 -0
- data/README.md +187 -0
- data/Rakefile +49 -0
- data/autotest/discover.rb +1 -0
- data/bin/autospec +16 -0
- data/bin/autotest +16 -0
- data/bin/rake +16 -0
- data/bin/rcov +16 -0
- data/bin/rspec +16 -0
- data/bin/yard +16 -0
- data/bin/yardoc +16 -0
- data/lib/pacer/blueprints/extensions.rb +77 -0
- data/lib/pacer/blueprints/multi_graph.rb +121 -0
- data/lib/pacer/blueprints/ruby_graph.rb +199 -0
- data/lib/pacer/blueprints/tg.rb +100 -0
- data/lib/pacer/blueprints.rb +4 -0
- data/lib/pacer/core/graph/edges_route.rb +92 -0
- data/lib/pacer/core/graph/element_route.rb +171 -0
- data/lib/pacer/core/graph/graph_index_route.rb +48 -0
- data/lib/pacer/core/graph/graph_route.rb +55 -0
- data/lib/pacer/core/graph/mixed_route.rb +96 -0
- data/lib/pacer/core/graph/vertices_route.rb +220 -0
- data/lib/pacer/core/graph.rb +13 -0
- data/lib/pacer/core/route.rb +502 -0
- data/lib/pacer/core/side_effect.rb +11 -0
- data/lib/pacer/core.rb +8 -0
- data/lib/pacer/exceptions.rb +11 -0
- data/lib/pacer/extensions/block_filter_element.rb +22 -0
- data/lib/pacer/extensions.rb +6 -0
- data/lib/pacer/filter/block_filter.rb +31 -0
- data/lib/pacer/filter/collection_filter.rb +109 -0
- data/lib/pacer/filter/empty_filter.rb +70 -0
- data/lib/pacer/filter/future_filter.rb +68 -0
- data/lib/pacer/filter/index_filter.rb +30 -0
- data/lib/pacer/filter/loop_filter.rb +95 -0
- data/lib/pacer/filter/object_filter.rb +55 -0
- data/lib/pacer/filter/property_filter/edge_filters.rb +93 -0
- data/lib/pacer/filter/property_filter/filters.rb +269 -0
- data/lib/pacer/filter/property_filter.rb +111 -0
- data/lib/pacer/filter/random_filter.rb +13 -0
- data/lib/pacer/filter/range_filter.rb +104 -0
- data/lib/pacer/filter/uniq_filter.rb +12 -0
- data/lib/pacer/filter/where_filter/node_visitor.rb +280 -0
- data/lib/pacer/filter/where_filter.rb +47 -0
- data/lib/pacer/filter.rb +17 -0
- data/lib/pacer/function_resolver.rb +43 -0
- data/lib/pacer/graph/edge_mixin.rb +127 -0
- data/lib/pacer/graph/element_mixin.rb +202 -0
- data/lib/pacer/graph/graph_indices_mixin.rb +93 -0
- data/lib/pacer/graph/graph_mixin.rb +361 -0
- data/lib/pacer/graph/graph_transactions_mixin.rb +207 -0
- data/lib/pacer/graph/index_mixin.rb +30 -0
- data/lib/pacer/graph/vertex_mixin.rb +119 -0
- data/lib/pacer/graph.rb +14 -0
- data/lib/pacer/pipe/blackbox_pipeline.rb +48 -0
- data/lib/pacer/pipe/block_filter_pipe.rb +38 -0
- data/lib/pacer/pipe/collection_filter_pipe.rb +10 -0
- data/lib/pacer/pipe/cross_product_transform_pipe.rb +48 -0
- data/lib/pacer/pipe/enumerable_pipe.rb +30 -0
- data/lib/pacer/pipe/expandable_pipe.rb +63 -0
- data/lib/pacer/pipe/id_collection_filter_pipe.rb +33 -0
- data/lib/pacer/pipe/is_empty_pipe.rb +30 -0
- data/lib/pacer/pipe/is_unique_pipe.rb +61 -0
- data/lib/pacer/pipe/label_collection_filter_pipe.rb +21 -0
- data/lib/pacer/pipe/label_prefix_pipe.rb +21 -0
- data/lib/pacer/pipe/loop_pipe.rb +86 -0
- data/lib/pacer/pipe/map_pipe.rb +36 -0
- data/lib/pacer/pipe/never_pipe.rb +9 -0
- data/lib/pacer/pipe/process_pipe.rb +37 -0
- data/lib/pacer/pipe/property_comparison_pipe.rb +40 -0
- data/lib/pacer/pipe/ruby_pipe.rb +25 -0
- data/lib/pacer/pipe/simple_visitor_pipe.rb +43 -0
- data/lib/pacer/pipe/stream_sort_pipe.rb +84 -0
- data/lib/pacer/pipe/stream_uniq_pipe.rb +33 -0
- data/lib/pacer/pipe/type_filter_pipe.rb +22 -0
- data/lib/pacer/pipe/unary_transform_pipe.rb +59 -0
- data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +26 -0
- data/lib/pacer/pipe/visitor_pipe.rb +67 -0
- data/lib/pacer/pipes.rb +61 -0
- data/lib/pacer/route/mixin/bulk_operations.rb +52 -0
- data/lib/pacer/route/mixin/route_operations.rb +107 -0
- data/lib/pacer/route/mixin/variable_route_module.rb +26 -0
- data/lib/pacer/route/mixins.rb +3 -0
- data/lib/pacer/route.rb +228 -0
- data/lib/pacer/routes.rb +6 -0
- data/lib/pacer/side_effect/aggregate.rb +31 -0
- data/lib/pacer/side_effect/counted.rb +30 -0
- data/lib/pacer/side_effect/group_count.rb +44 -0
- data/lib/pacer/side_effect/is_unique.rb +32 -0
- data/lib/pacer/side_effect/section.rb +25 -0
- data/lib/pacer/side_effect/visitor.rb +37 -0
- data/lib/pacer/side_effect.rb +11 -0
- data/lib/pacer/support/array_list.rb +28 -0
- data/lib/pacer/support/enumerable.rb +100 -0
- data/lib/pacer/support/hash.rb +9 -0
- data/lib/pacer/support/iterator_mixins.rb +110 -0
- data/lib/pacer/support/native_exception.rb +22 -0
- data/lib/pacer/support/proc.rb +16 -0
- data/lib/pacer/support.rb +10 -0
- data/lib/pacer/transform/cap.rb +50 -0
- data/lib/pacer/transform/gather.rb +9 -0
- data/lib/pacer/transform/has_count_cap.rb +41 -0
- data/lib/pacer/transform/join.rb +181 -0
- data/lib/pacer/transform/map.rb +23 -0
- data/lib/pacer/transform/path.rb +50 -0
- data/lib/pacer/transform/process.rb +23 -0
- data/lib/pacer/transform/scatter.rb +23 -0
- data/lib/pacer/transform/sort_section.rb +103 -0
- data/lib/pacer/transform/stream_sort.rb +21 -0
- data/lib/pacer/transform/stream_uniq.rb +21 -0
- data/lib/pacer/transform.rb +16 -0
- data/lib/pacer/utils/graph_analysis.rb +112 -0
- data/lib/pacer/utils/trie.rb +93 -0
- data/lib/pacer/utils/tsort.rb +65 -0
- data/lib/pacer/utils/y_files.rb +127 -0
- data/lib/pacer/utils.rb +10 -0
- data/lib/pacer/version.rb +13 -0
- data/lib/pacer/wrappers/edge_wrapper.rb +51 -0
- data/lib/pacer/wrappers/element_wrapper.rb +78 -0
- data/lib/pacer/wrappers/new_element.rb +106 -0
- data/lib/pacer/wrappers/vertex_wrapper.rb +51 -0
- data/lib/pacer/wrappers.rb +19 -0
- data/lib/pacer-0.9.1.1-standalone.jar +0 -0
- data/lib/pacer.rb +290 -0
- data/pacer.gemspec +30 -0
- data/pom/standalone.xml +22 -0
- data/pom.xml +124 -0
- data/samples/grateful-dead.xml +26380 -0
- data/samples/grateful_dead.rb +63 -0
- data/samples/profile.rb +15 -0
- data/spec/data/grateful-dead.xml +26380 -0
- data/spec/data/pacer.graphml +319 -0
- data/spec/pacer/blueprints/dex_spec.rb +172 -0
- data/spec/pacer/blueprints/neo4j_spec.rb +177 -0
- data/spec/pacer/blueprints/tg_spec.rb +128 -0
- data/spec/pacer/core/graph/edges_route_spec.rb +52 -0
- data/spec/pacer/core/graph/element_route_spec.rb +46 -0
- data/spec/pacer/core/graph/graph_route_spec.rb +94 -0
- data/spec/pacer/core/graph/vertices_route_spec.rb +169 -0
- data/spec/pacer/core/route_spec.rb +197 -0
- data/spec/pacer/filter/collection_filter_spec.rb +19 -0
- data/spec/pacer/filter/empty_filter_spec.rb +29 -0
- data/spec/pacer/filter/future_filter_spec.rb +97 -0
- data/spec/pacer/filter/loop_filter_spec.rb +31 -0
- data/spec/pacer/filter/property_filter_spec.rb +111 -0
- data/spec/pacer/filter/random_filter_spec.rb +17 -0
- data/spec/pacer/filter/uniq_filter_spec.rb +18 -0
- data/spec/pacer/filter/where_filter_spec.rb +93 -0
- data/spec/pacer/graph/edge_mixin_spec.rb +116 -0
- data/spec/pacer/graph/element_mixin_spec.rb +297 -0
- data/spec/pacer/graph/graph_mixin_spec.rb +538 -0
- data/spec/pacer/graph/index_mixin_spec.rb +0 -0
- data/spec/pacer/graph/vertex_mixin_spec.rb +192 -0
- data/spec/pacer/pipe/block_filter_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/labels_filter_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/ruby_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/type_filter_pipe_spec.rb +0 -0
- data/spec/pacer/route/mixin/base_spec.rb +419 -0
- data/spec/pacer/route/mixin/bulk_operations_spec.rb +30 -0
- data/spec/pacer/route/mixin/route_operations_spec.rb +127 -0
- data/spec/pacer/support/array_list_spec.rb +0 -0
- data/spec/pacer/support/enumerable_spec.rb +115 -0
- data/spec/pacer/transform/join_spec.rb +138 -0
- data/spec/pacer/transform/path_spec.rb +54 -0
- data/spec/pacer/utils/tsort_spec.rb +89 -0
- data/spec/pacer/wrapper/edge_wrapper_spec.rb +33 -0
- data/spec/pacer/wrapper/element_wrapper_spec.rb +169 -0
- data/spec/pacer/wrapper/vertex_wrapper_spec.rb +33 -0
- data/spec/pacer_spec.rb +0 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/support/contexts.rb +14 -0
- data/spec/support/graph_runner.rb +142 -0
- data/spec/support/matchers.rb +19 -0
- data/spec/support/use_transactions.rb +31 -0
- data/spec/tackle/simple_mixin.rb +21 -0
- data/spec/tackle/tinkerpop_graph_mixins.rb +60 -0
- metadata +364 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
module Pacer
|
|
3
|
+
module Core
|
|
4
|
+
|
|
5
|
+
# The basic internal logic for routes and core route shared methods are
|
|
6
|
+
# defined here. Many of these methods are designed to be specialized by
|
|
7
|
+
# other modules included after Core::Route is included.
|
|
8
|
+
module Route
|
|
9
|
+
class << self
|
|
10
|
+
protected
|
|
11
|
+
def included(target)
|
|
12
|
+
target.send :include, Enumerable
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Replace the generated class name of this route with a specific
|
|
17
|
+
# one by setting route_name.
|
|
18
|
+
attr_accessor :route_name
|
|
19
|
+
attr_accessor :info
|
|
20
|
+
|
|
21
|
+
# Specify which pipe class will be instantiated when an iterator is created.
|
|
22
|
+
attr_accessor :pipe_class
|
|
23
|
+
|
|
24
|
+
# If true, elements won't be printed to STDOUT when #inspect is
|
|
25
|
+
# called on this route.
|
|
26
|
+
# @return [true, false]
|
|
27
|
+
attr_accessor :hide_elements
|
|
28
|
+
|
|
29
|
+
# Set which graph this route will operate on.
|
|
30
|
+
#
|
|
31
|
+
# @todo move this to graph routes.
|
|
32
|
+
attr_writer :graph
|
|
33
|
+
|
|
34
|
+
# Return which graph this route operates on.
|
|
35
|
+
#
|
|
36
|
+
# @todo move this to graph routes.
|
|
37
|
+
#
|
|
38
|
+
# @return [GraphMixin]
|
|
39
|
+
def graph
|
|
40
|
+
@graph = nil unless defined? @graph
|
|
41
|
+
@graph ||= (@back || @source).graph rescue nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns true if the given graph is the one this route operates on.
|
|
45
|
+
def from_graph?(g)
|
|
46
|
+
graph.equals g
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The arguments passed to the pipe constructor.
|
|
50
|
+
#
|
|
51
|
+
# @overload pipe_args
|
|
52
|
+
# @overload pipe_args=(args)
|
|
53
|
+
# @param [Object] args
|
|
54
|
+
# @overload pipe_args=(args)
|
|
55
|
+
# @param [[Object]] args
|
|
56
|
+
#
|
|
57
|
+
# @return [[Object]] array of arguments
|
|
58
|
+
attr_reader :pipe_args
|
|
59
|
+
|
|
60
|
+
def pipe_args=(args)
|
|
61
|
+
if args.is_a? Array
|
|
62
|
+
@pipe_args = args
|
|
63
|
+
else
|
|
64
|
+
@pipe_args = [args]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Return true if this route is at the beginning of the route definition.
|
|
69
|
+
def root?
|
|
70
|
+
!@source.nil? or @back.nil?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Prevents the route from being evaluated when it is inspected. Useful
|
|
74
|
+
# for computationally expensive or one-time routes.
|
|
75
|
+
#
|
|
76
|
+
# @todo rename this method
|
|
77
|
+
#
|
|
78
|
+
# @return [self]
|
|
79
|
+
def route
|
|
80
|
+
@hide_elements = true
|
|
81
|
+
self
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns the hash of variables used during the previous evaluation of
|
|
85
|
+
# the route.
|
|
86
|
+
#
|
|
87
|
+
# The contents of vars is expected to be in a state relevant to the
|
|
88
|
+
# latest route being evaluated and is primarily meant for internal use,
|
|
89
|
+
# but YMMV.
|
|
90
|
+
#
|
|
91
|
+
# @todo It would maybe be better if the vars were tied to the
|
|
92
|
+
# thread context or preferably to the actual pipe instance in
|
|
93
|
+
# use. The current implementation of vars is not threadsafe if
|
|
94
|
+
# the same route is being used in multiple threads concurrently.
|
|
95
|
+
#
|
|
96
|
+
# @return [Hash]
|
|
97
|
+
def vars
|
|
98
|
+
if @back
|
|
99
|
+
@back.vars
|
|
100
|
+
else
|
|
101
|
+
@vars ||= {}
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Iterates over each element or object resulting from traversing the
|
|
106
|
+
# route up to this point.
|
|
107
|
+
#
|
|
108
|
+
# @yield [item] if a block is given
|
|
109
|
+
# @return [Enumerator] if no block is given
|
|
110
|
+
def each
|
|
111
|
+
iter = iterator
|
|
112
|
+
configure_iterator(iter)
|
|
113
|
+
if block_given?
|
|
114
|
+
while true
|
|
115
|
+
yield iter.next
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
iter
|
|
119
|
+
end
|
|
120
|
+
rescue java.util.NoSuchElementException
|
|
121
|
+
self
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Returns a single use pipe iterator based on this route.
|
|
125
|
+
#
|
|
126
|
+
# @yield [java.util.Iterator] the pipe. Very useful because this method will catch the pipe's java.util.NoSuchElementException when iteration is finished.
|
|
127
|
+
# @return [java.util.Iterator] the pipe.
|
|
128
|
+
def pipe
|
|
129
|
+
iterator = each
|
|
130
|
+
yield iterator if block_given?
|
|
131
|
+
iterator
|
|
132
|
+
rescue java.util.NoSuchElementException
|
|
133
|
+
iterator
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Returns a string representation of the route definition. If there are
|
|
137
|
+
# less than Graph#inspect_limit matches, it will also output all matching
|
|
138
|
+
# elements formatted in columns up to a maximum character width of
|
|
139
|
+
# Graph#columns. If this output behaviour is undesired, it may be turned
|
|
140
|
+
# off by calling #route on the current route.
|
|
141
|
+
#
|
|
142
|
+
# @return [String]
|
|
143
|
+
def inspect(limit = nil)
|
|
144
|
+
if Pacer.hide_route_elements or hide_elements or source_iterator.nil?
|
|
145
|
+
"#<#{inspect_strings.join(' -> ')}>"
|
|
146
|
+
else
|
|
147
|
+
Pacer.hide_route_elements do
|
|
148
|
+
count = 0
|
|
149
|
+
limit ||= Pacer.inspect_limit
|
|
150
|
+
results = collect do |v|
|
|
151
|
+
count += 1
|
|
152
|
+
return route.inspect if count > limit
|
|
153
|
+
v.inspect
|
|
154
|
+
end
|
|
155
|
+
if count > 0
|
|
156
|
+
lens = results.collect { |r| r.length }
|
|
157
|
+
max = lens.max
|
|
158
|
+
cols = (Pacer.columns / (max + 1).to_f).floor
|
|
159
|
+
cols = 1 if cols < 1
|
|
160
|
+
if cols == 1
|
|
161
|
+
template_part = ['%s']
|
|
162
|
+
else
|
|
163
|
+
template_part = ["%-#{max}s"]
|
|
164
|
+
end
|
|
165
|
+
template = (template_part * cols).join(' ')
|
|
166
|
+
results.each_slice(cols) do |row|
|
|
167
|
+
template = (template_part * row.count).join(' ') if row.count < cols
|
|
168
|
+
puts template % row
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
puts "Total: #{ count }"
|
|
172
|
+
"#<#{inspect_strings.join(' -> ')}>"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Returns true if the other route is defined the same as the current route.
|
|
178
|
+
#
|
|
179
|
+
# Note that block filters will prevent matches even with identically
|
|
180
|
+
# defined routes unless the routes are actually the same object.
|
|
181
|
+
# @return [true, false]
|
|
182
|
+
def ==(other)
|
|
183
|
+
other.class == self.class and
|
|
184
|
+
other.function == function and
|
|
185
|
+
other.element_type == element_type and
|
|
186
|
+
other.back == back and
|
|
187
|
+
other.source == source
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Returns true if this route currently has no elements.
|
|
191
|
+
def empty?
|
|
192
|
+
none?
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Add an extension to the route.
|
|
196
|
+
#
|
|
197
|
+
# If the extension has a Route module inside it, this route will
|
|
198
|
+
# be extended with the extension's Route module.
|
|
199
|
+
#
|
|
200
|
+
# If the extension has a Vertex or Edge module inside it, any vertices
|
|
201
|
+
# or edges emitted from this route will be extended with with the
|
|
202
|
+
# extension as well.
|
|
203
|
+
#
|
|
204
|
+
# @see VertexMixin#add_extensions
|
|
205
|
+
# @see EdgeMixin#add_extensions
|
|
206
|
+
#
|
|
207
|
+
# @return [self]
|
|
208
|
+
def add_extension(mod, add_to_list = true)
|
|
209
|
+
return self unless mod.respond_to?(:const_defined?)
|
|
210
|
+
is_extension = false
|
|
211
|
+
if mod.const_defined? :Route
|
|
212
|
+
is_extension = true
|
|
213
|
+
extend mod::Route
|
|
214
|
+
end
|
|
215
|
+
if add_to_list and (is_extension or mod.const_defined? :Vertex or mod.const_defined? :Edge)
|
|
216
|
+
@extensions << mod
|
|
217
|
+
end
|
|
218
|
+
self
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def set_wrapper(wrapper)
|
|
222
|
+
if wrapper.respond_to? :extensions
|
|
223
|
+
wrapper.extensions.each do |ext|
|
|
224
|
+
add_extension ext, false
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
@wrapper = wrapper
|
|
228
|
+
self
|
|
229
|
+
end
|
|
230
|
+
alias wrapper= set_wrapper
|
|
231
|
+
|
|
232
|
+
def wrapper
|
|
233
|
+
@wrapper
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Add extensions to this route.
|
|
237
|
+
#
|
|
238
|
+
# @see #add_extension
|
|
239
|
+
def extensions=(exts)
|
|
240
|
+
add_extensions Set[*exts]
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Get the set of extensions currently on this route.
|
|
244
|
+
#
|
|
245
|
+
# The order of extensions for custom defined wrappers are
|
|
246
|
+
# guaranteed. If a wrapper is iterated with additional extensions,
|
|
247
|
+
# a new wrapper will be created dynamically with the original
|
|
248
|
+
# extensions in order followed by any additional extensions in
|
|
249
|
+
# undefined order.
|
|
250
|
+
#
|
|
251
|
+
# If a wrapper is present, returns an Array. Otherwise a Set.
|
|
252
|
+
#
|
|
253
|
+
# @return [Enumerable[extension]]
|
|
254
|
+
def extensions
|
|
255
|
+
if wrapper
|
|
256
|
+
wrapper.extensions + @extensions.to_a
|
|
257
|
+
else
|
|
258
|
+
@extensions
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# If any objects in the given array are modules that contain a Route
|
|
263
|
+
# submodule, extend this route with the Route module.
|
|
264
|
+
# @see #add_extension
|
|
265
|
+
# @return [self]
|
|
266
|
+
def add_extensions(exts)
|
|
267
|
+
modules = exts.select { |obj| obj.is_a? Module or obj.is_a? Class }
|
|
268
|
+
modules.each do |mod|
|
|
269
|
+
add_extension(mod)
|
|
270
|
+
end
|
|
271
|
+
self
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def no_extensions
|
|
275
|
+
chain_route(:extensions => nil, :wrapper => nil)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Change the source of this route.
|
|
279
|
+
#
|
|
280
|
+
# @note all routes derived from any route in the chain will be
|
|
281
|
+
# affected so use with caution.
|
|
282
|
+
#
|
|
283
|
+
# @param [Enumerable, Enumerator] src the data source.
|
|
284
|
+
def set_pipe_source(src)
|
|
285
|
+
if @back
|
|
286
|
+
@back.set_pipe_source src
|
|
287
|
+
else
|
|
288
|
+
self.source = src
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
protected
|
|
293
|
+
|
|
294
|
+
# Set the previous route in the chain.
|
|
295
|
+
def back=(back)
|
|
296
|
+
if back.is_a? Route and not back.is_a? GraphMixin
|
|
297
|
+
@back = back
|
|
298
|
+
else
|
|
299
|
+
@source = back
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Return the route which is attached to the given route.
|
|
304
|
+
def route_after(route)
|
|
305
|
+
if route == self
|
|
306
|
+
nil
|
|
307
|
+
elsif @back
|
|
308
|
+
if @back == route
|
|
309
|
+
self
|
|
310
|
+
elsif @back.is_a? Route
|
|
311
|
+
@back.route_after(route)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Overridden to extend the iterator to apply mixins
|
|
317
|
+
# or wrap elements
|
|
318
|
+
def configure_iterator(iter)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def get_section_route(name)
|
|
322
|
+
if respond_to? :section_name and section_name == name
|
|
323
|
+
self
|
|
324
|
+
elsif @back
|
|
325
|
+
@back.get_section_route(name)
|
|
326
|
+
else
|
|
327
|
+
raise ArgumentError, "Section #{ name } not found"
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Returns a HashSet of element ids from the collection, but
|
|
332
|
+
# only if all elements in the collection have an element_id.
|
|
333
|
+
|
|
334
|
+
# This should not normally need to be set. It can be used to inject a route
|
|
335
|
+
# into another route during iterator generation.
|
|
336
|
+
def source=(source)
|
|
337
|
+
@back = nil
|
|
338
|
+
@source = source
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Get the actual source of data for this route.
|
|
342
|
+
#
|
|
343
|
+
# @return [java.util.Iterator]
|
|
344
|
+
def source_iterator
|
|
345
|
+
if @source
|
|
346
|
+
iterator_from_source(@source)
|
|
347
|
+
elsif @back
|
|
348
|
+
@back.send(:source_iterator)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Get the first and last pipes in the pipeline before the current
|
|
353
|
+
# route's pipes are added.
|
|
354
|
+
# @see #build_pipeline
|
|
355
|
+
# @return [[com.tinkerpop.pipes.Pipe, com.tinkerpop.pipes.Pipe], nil]
|
|
356
|
+
def pipe_source
|
|
357
|
+
if @source
|
|
358
|
+
nil
|
|
359
|
+
elsif @back
|
|
360
|
+
@back.send(:build_pipeline)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Return an iterator for a variety of source object types.
|
|
365
|
+
def iterator_from_source(src)
|
|
366
|
+
if src.is_a? Pacer::GraphMixin
|
|
367
|
+
al = java.util.ArrayList.new
|
|
368
|
+
al << src
|
|
369
|
+
al.iterator
|
|
370
|
+
elsif src.is_a? Pacer::Wrappers::ElementWrapper
|
|
371
|
+
Pacer::Pipes::EnumerablePipe.new src.element
|
|
372
|
+
elsif src.is_a? Proc
|
|
373
|
+
iterator_from_source(src.call)
|
|
374
|
+
elsif src.is_a? Iterator
|
|
375
|
+
src
|
|
376
|
+
elsif src
|
|
377
|
+
Pacer::Pipes::EnumerablePipe.new src
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Return an iterator for this route loading data from all previous routes
|
|
382
|
+
# in the chain.
|
|
383
|
+
def iterator
|
|
384
|
+
start, end_pipe = build_pipeline
|
|
385
|
+
if start
|
|
386
|
+
src = source_iterator
|
|
387
|
+
Pacer.debug_source = src if Pacer.debug_pipes
|
|
388
|
+
start.setStarts src
|
|
389
|
+
end_pipe
|
|
390
|
+
elsif end_pipe
|
|
391
|
+
raise "End pipe without start pipe"
|
|
392
|
+
else
|
|
393
|
+
pipe = Pacer::Pipes::IdentityPipe.new
|
|
394
|
+
pipe.setStarts source_iterator
|
|
395
|
+
pipe
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# This is the default implementation of the method used to create
|
|
400
|
+
# the specialized pipe for each route instance. It is overridden
|
|
401
|
+
# in most function modules to produce the pipe needed to perform
|
|
402
|
+
# that function.
|
|
403
|
+
#
|
|
404
|
+
# @see Filter modules in this namespace override this method
|
|
405
|
+
# @see Transform modules in this namespace override this method
|
|
406
|
+
# @see SideEffect modules in this namespace override this method
|
|
407
|
+
#
|
|
408
|
+
# @param [com.tinkerpop.pipes.Pipe] the pipe emitting the source
|
|
409
|
+
# data for this pipe
|
|
410
|
+
# @return [com.tinkerpop.pipes.Pipe] the pipe that emits the
|
|
411
|
+
# resulting data from this step
|
|
412
|
+
def attach_pipe(end_pipe)
|
|
413
|
+
if pipe_class
|
|
414
|
+
if pipe_args
|
|
415
|
+
begin
|
|
416
|
+
pipe = pipe_class.new(*pipe_args)
|
|
417
|
+
rescue ArgumentError
|
|
418
|
+
raise ArgumentError, "Invalid args for pipe: #{ pipe_class.inspect }.new(*#{pipe_args.inspect})"
|
|
419
|
+
end
|
|
420
|
+
else
|
|
421
|
+
begin
|
|
422
|
+
pipe = pipe_class.new
|
|
423
|
+
rescue ArgumentError
|
|
424
|
+
raise ArgumentError, "Invalid args for pipe: #{ pipe_class.inspect }.new()"
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
pipe.setStarts end_pipe if end_pipe
|
|
428
|
+
pipe
|
|
429
|
+
else
|
|
430
|
+
end_pipe
|
|
431
|
+
end
|
|
432
|
+
rescue NativeException => e
|
|
433
|
+
if e.cause.name == 'java.lang.InstantiationException'
|
|
434
|
+
raise Exception, "Unable to instantiate abstract class #{ pipe_class }"
|
|
435
|
+
else
|
|
436
|
+
raise
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# Walks back along the chain of routes to build the series of Pipe
|
|
441
|
+
# objects that represent this route.
|
|
442
|
+
#
|
|
443
|
+
# @return [[com.tinkerpop.pipes.Pipe, com.tinkerpop.pipes.Pipe]]
|
|
444
|
+
# start and end pipe in the pipeline. The start pipe gets the
|
|
445
|
+
# source applied to it, the end pipe produces the result when its
|
|
446
|
+
# next method is called.
|
|
447
|
+
def build_pipeline
|
|
448
|
+
start, end_pipe = pipe_source
|
|
449
|
+
pipe = attach_pipe(end_pipe)
|
|
450
|
+
Pacer.debug_pipes << { :name => inspect_class_name, :start => start, :end => pipe } if Pacer.debug_pipes
|
|
451
|
+
[start || pipe, pipe]
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
# Returns an array of strings representing each route object in the
|
|
455
|
+
# chain.
|
|
456
|
+
# @return [[String]]
|
|
457
|
+
def inspect_strings
|
|
458
|
+
ins = []
|
|
459
|
+
ins += @back.inspect_strings unless root?
|
|
460
|
+
|
|
461
|
+
ins << inspect_string
|
|
462
|
+
ins
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# Returns the string representing just this route instance.
|
|
466
|
+
# @return [String]
|
|
467
|
+
def inspect_string
|
|
468
|
+
return route_name if route_name
|
|
469
|
+
if pipe_class
|
|
470
|
+
ps = pipe_class.name
|
|
471
|
+
if ps =~ /FilterPipe$/
|
|
472
|
+
ps = ps.split('::').last.sub(/FilterPipe/, '')
|
|
473
|
+
if pipe_args
|
|
474
|
+
pipeargs = pipe_args.collect do |arg|
|
|
475
|
+
if arg.is_a? Enumerable and arg.count > 10
|
|
476
|
+
"[...#{ arg.count } items...]"
|
|
477
|
+
else
|
|
478
|
+
arg.to_s
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
ps = "#{ps}(#{pipeargs.join(', ')})" if pipeargs.any?
|
|
482
|
+
end
|
|
483
|
+
elsif pipe_args
|
|
484
|
+
ps = pipe_args.join(', ')
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
s = inspect_class_name
|
|
488
|
+
s = "#{s}(#{ ps })" if ps and ps != ''
|
|
489
|
+
s
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
# Return the class name of the current route.
|
|
493
|
+
# @return [String]
|
|
494
|
+
def inspect_class_name
|
|
495
|
+
s = "#{self.class.name.split('::').last.sub(/Route$/, '')}"
|
|
496
|
+
s = "#{s} #{ info }" if info
|
|
497
|
+
s
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
data/lib/pacer/core.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Pacer
|
|
2
|
+
module Extensions
|
|
3
|
+
module BlockFilterElement
|
|
4
|
+
module Route
|
|
5
|
+
def back=(back)
|
|
6
|
+
@back = back
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# The previous route element.
|
|
10
|
+
def back
|
|
11
|
+
@back
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# The vars hash contains variables that were set earlier in the processing
|
|
15
|
+
# of the route. Vars may also be set within the block.
|
|
16
|
+
def vars
|
|
17
|
+
@back.vars
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Pacer
|
|
2
|
+
module Routes
|
|
3
|
+
module RouteOperations
|
|
4
|
+
def select(&block)
|
|
5
|
+
chain_route :filter => :block, :block => block, :route_name => 'Select'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def reject(&block)
|
|
9
|
+
chain_route :filter => :block, :block => block, :invert => true, :route_name => 'Reject'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Filter
|
|
15
|
+
module BlockFilter
|
|
16
|
+
attr_accessor :block, :invert
|
|
17
|
+
|
|
18
|
+
def ==(other)
|
|
19
|
+
super and invert == other.invert and block == other.block
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
protected
|
|
23
|
+
|
|
24
|
+
def attach_pipe(end_pipe)
|
|
25
|
+
pipe = Pacer::Pipes::BlockFilterPipe.new(self, block, invert)
|
|
26
|
+
pipe.set_starts end_pipe if end_pipe
|
|
27
|
+
pipe
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
module Pacer
|
|
2
|
+
module Core
|
|
3
|
+
module Route
|
|
4
|
+
def except(excluded)
|
|
5
|
+
if excluded.is_a? Symbol
|
|
6
|
+
chain_route :filter => :collection, :except_var => excluded
|
|
7
|
+
else
|
|
8
|
+
chain_route :filter => :collection, :except => excluded
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def -(other)
|
|
13
|
+
chain_route :filter => :collection, :except => other
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def only(included)
|
|
17
|
+
if included.is_a? Symbol
|
|
18
|
+
chain_route :filter => :collection, :only_var => included
|
|
19
|
+
else
|
|
20
|
+
chain_route :filter => :collection, :only => included
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Filter
|
|
27
|
+
module CollectionFilter
|
|
28
|
+
import java.util.HashSet
|
|
29
|
+
|
|
30
|
+
attr_reader :var, :comparison, :ids, :objects
|
|
31
|
+
|
|
32
|
+
def except=(collection)
|
|
33
|
+
self.collection = collection
|
|
34
|
+
@comparison = Pacer::Pipes::NOT_EQUAL
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def except_var=(var)
|
|
38
|
+
@var = var
|
|
39
|
+
@comparison = Pacer::Pipes::NOT_EQUAL
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def only=(collection)
|
|
43
|
+
self.collection = collection
|
|
44
|
+
@comparison = Pacer::Pipes::EQUAL
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def only_var=(var)
|
|
48
|
+
@var = var
|
|
49
|
+
@comparison = Pacer::Pipes::EQUAL
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
protected
|
|
53
|
+
|
|
54
|
+
def collection=(collection)
|
|
55
|
+
collection = [collection] unless collection.is_a? Enumerable
|
|
56
|
+
@ids = nil
|
|
57
|
+
if collection.is_a? HashSet
|
|
58
|
+
@objects = collection
|
|
59
|
+
elsif element_type != Object
|
|
60
|
+
@ids = element_id_hashset(collection)
|
|
61
|
+
@objects = collection.to_hashset unless ids
|
|
62
|
+
else
|
|
63
|
+
@objects = collection.to_hashset
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def element_id_hashset(collection)
|
|
68
|
+
if collection.is_a? Pacer::Core::Graph::ElementRoute
|
|
69
|
+
collection.element_ids.to_hashset
|
|
70
|
+
else
|
|
71
|
+
collection.to_hashset(:element_id) rescue nil
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def attach_pipe(end_pipe)
|
|
76
|
+
if var
|
|
77
|
+
pipe = Pacer::Pipes::CollectionFilterPipe.new(vars[var], comparison)
|
|
78
|
+
elsif ids
|
|
79
|
+
pipe = Pacer::Pipes::IdCollectionFilterPipe.new(ids, comparison)
|
|
80
|
+
else
|
|
81
|
+
pipe = Pacer::Pipes::CollectionFilterPipe.new(objects, comparison)
|
|
82
|
+
end
|
|
83
|
+
pipe.set_starts(end_pipe) if end_pipe
|
|
84
|
+
pipe
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def collection_count
|
|
88
|
+
@collection.count
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def inspect_class_name
|
|
92
|
+
if @comparison == Pacer::Pipes::NOT_EQUAL
|
|
93
|
+
'Except'
|
|
94
|
+
else
|
|
95
|
+
'Only'
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def inspect_string
|
|
100
|
+
if var
|
|
101
|
+
"#{ inspect_class_name }(#{ var.inspect })"
|
|
102
|
+
else
|
|
103
|
+
c = (ids || objects)
|
|
104
|
+
"#{ inspect_class_name }(#{c.count} elements)"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|