pacer 0.9.1.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/pacer/route.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
[Pacer::Core::Route, Pacer::ElementMixin, Pacer::Wrappers::EdgeWrapper, Pacer::Wrappers::VertexWrapper].each do |klass|
|
2
|
+
klass.class_eval %{
|
3
|
+
def chain_route(args_hash)
|
4
|
+
Pacer::Route.new({ :back => self }.merge(args_hash))
|
5
|
+
end
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
module Pacer
|
10
|
+
# The base class for almost everything in Pacer. Every route is an
|
11
|
+
# instance of this class with a variety of modules mixed into the
|
12
|
+
# instance at runtime.
|
13
|
+
#
|
14
|
+
# The class definition only contains methods directly related to the
|
15
|
+
# construction of new Routes. For methods more likely to be used, see
|
16
|
+
# the {Core::Route} module which is always mixed into this class.
|
17
|
+
#
|
18
|
+
# @see Core::Route
|
19
|
+
class Route
|
20
|
+
class << self
|
21
|
+
# A pipeline is sometimes required if a pipe needs to be passed
|
22
|
+
# into a method that will change the starts on the same object
|
23
|
+
# that it requests the next result from.
|
24
|
+
#
|
25
|
+
# @param [Route] route the route to create a pipeline based on
|
26
|
+
# @return [Pacer::Pipes::BlackboxPipeline] an instantiated pipeline
|
27
|
+
def pipeline(route)
|
28
|
+
s, e = route.send(:build_pipeline)
|
29
|
+
if s.equal?(e)
|
30
|
+
s
|
31
|
+
else
|
32
|
+
Pacer::Pipes::BlackboxPipeline.new s, e
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
include Pacer::Core::Route
|
38
|
+
include Pacer::Routes::RouteOperations
|
39
|
+
|
40
|
+
# The function mixed into this instance
|
41
|
+
attr_reader :function
|
42
|
+
|
43
|
+
# The type of object that this route emits.
|
44
|
+
attr_reader :element_type
|
45
|
+
|
46
|
+
# Additional info to include after the class name when generating a
|
47
|
+
# name for this route.
|
48
|
+
attr_accessor :info
|
49
|
+
|
50
|
+
# The previous route in the chain
|
51
|
+
attr_reader :back
|
52
|
+
|
53
|
+
# The soure of data for the entire chain. Routes that have a source
|
54
|
+
# generally should not have a {#back}
|
55
|
+
attr_reader :source
|
56
|
+
|
57
|
+
# Create a new route. It should be very rare that you would need to
|
58
|
+
# directly create a Route object.
|
59
|
+
#
|
60
|
+
# See {Core::Graph::GraphRoute} and {GraphMixin} for methods
|
61
|
+
# to build routes based on a graph.
|
62
|
+
#
|
63
|
+
# See {ElementMixin}, {VertexMixin} and
|
64
|
+
# {EdgeMixin} for methods to build routes based on an
|
65
|
+
# individual graph element.
|
66
|
+
#
|
67
|
+
# @see Core::Graph::GraphRoute
|
68
|
+
# @see GraphMixin
|
69
|
+
# @see ElementMixin
|
70
|
+
# @see VertexMixin
|
71
|
+
# @see EdgeMixin
|
72
|
+
#
|
73
|
+
# See Pacer's {Enumerable#to_route} method to create a route based
|
74
|
+
# on an Array, a Set or any other Enumerable type.
|
75
|
+
#
|
76
|
+
# @param [Hash] args
|
77
|
+
# @option args [Graph] :graph the graph this route is based on
|
78
|
+
# @option args [Route] :bace the previous route in the chain
|
79
|
+
# @option args [element type] :element_type
|
80
|
+
# @option args [Module] :modules additional modules to mix in
|
81
|
+
# @option args [Symbol, Module] :filter the filter to use as this
|
82
|
+
# route's function
|
83
|
+
# @option args [Symbol, Module] :side_effect the side effect to use
|
84
|
+
# as this route's function (Also triggers the {Core::SideEffect}
|
85
|
+
# mixin)
|
86
|
+
# @option args [Symbol, Module] :transform the transform module to
|
87
|
+
# use as this route's function
|
88
|
+
# @option args [[Module]] :extensions extensions for this route
|
89
|
+
#
|
90
|
+
# All other keys sent to the args method will be converted into
|
91
|
+
# setter method calls and called against the instantiated route to
|
92
|
+
# allow modules to define their own setup however they need.
|
93
|
+
#
|
94
|
+
# @example If a route is constructed with the a custom key:
|
95
|
+
# route = Route.new(:filter => :block, :block => proc { |element| element.element_id.even? })
|
96
|
+
#
|
97
|
+
# # is theoretically the same as
|
98
|
+
#
|
99
|
+
# route = Route.new
|
100
|
+
# route.extend Pacer::Filter::BlockFilter
|
101
|
+
# route.block = proc { |element| element.element_id.even? }
|
102
|
+
# route
|
103
|
+
#
|
104
|
+
# When the route object is fully initialized, the
|
105
|
+
# {#after_initialize} method is called to allow mixins to do any
|
106
|
+
# additional setup.
|
107
|
+
def initialize(args = {})
|
108
|
+
@@graph = @back = @source = nil
|
109
|
+
@wrapper = nil
|
110
|
+
@extensions = Set[]
|
111
|
+
self.graph = args[:graph]
|
112
|
+
self.back = args[:back]
|
113
|
+
include_function args
|
114
|
+
set_element_type args
|
115
|
+
include_other_modules args
|
116
|
+
keys = args.keys - [:element_type, :modules, :graph, :back, :filter, :side_effect, :transform]
|
117
|
+
keys.each do |key|
|
118
|
+
send("#{key}=", args[key])
|
119
|
+
end
|
120
|
+
include_extensions args
|
121
|
+
after_initialize
|
122
|
+
rescue Exception => e
|
123
|
+
puts "Exception creating Route with #{ args.inspect }" if Pacer.verbose?
|
124
|
+
raise
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
|
129
|
+
# Set the element type of this route and include the apropriate
|
130
|
+
# mixin to support the element type.
|
131
|
+
#
|
132
|
+
# @param [:vertex, :edge, :mixed, element type, Object] et the
|
133
|
+
# element type to use
|
134
|
+
def element_type=(et)
|
135
|
+
if graph
|
136
|
+
@element_type = graph.element_type(et)
|
137
|
+
if @element_type == graph.element_type(:vertex)
|
138
|
+
extend Pacer::Core::Graph::VerticesRoute
|
139
|
+
elsif @element_type == graph.element_type(:edge)
|
140
|
+
extend Pacer::Core::Graph::EdgesRoute
|
141
|
+
elsif @element_type == graph.element_type(:mixed)
|
142
|
+
extend Pacer::Core::Graph::MixedRoute
|
143
|
+
end
|
144
|
+
elsif et == :object or et == Object
|
145
|
+
@element_type = Object
|
146
|
+
else
|
147
|
+
raise "Element type #{ et.inspect } specified, but no graph specified."
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# This callback may be overridden. Be sure to call super() though.
|
152
|
+
# @return ignored
|
153
|
+
def after_initialize
|
154
|
+
end
|
155
|
+
|
156
|
+
# Find the module for the function to include based on the :filter,
|
157
|
+
# :side_effect or :transform argument given to {#initialize} and
|
158
|
+
# extend this instance with it.
|
159
|
+
def include_function(args)
|
160
|
+
@function, extension = FunctionResolver.function(args)
|
161
|
+
self.extend extension if extension
|
162
|
+
self.extend function if function
|
163
|
+
end
|
164
|
+
|
165
|
+
# @return [Route, nil] the previous route in the chain
|
166
|
+
def back_object(args)
|
167
|
+
back || args[:back]
|
168
|
+
end
|
169
|
+
|
170
|
+
# Get element type from the previous route in the chain.
|
171
|
+
# @return [element type, nil]
|
172
|
+
def back_element_type(args)
|
173
|
+
b = back_object(args)
|
174
|
+
if b.respond_to? :element_type
|
175
|
+
b.element_type
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# If no element type has been specified, try to find one from
|
180
|
+
# the previous route in the chain.
|
181
|
+
# @raise [StandardError] if no element type can be found
|
182
|
+
def set_element_type(args)
|
183
|
+
if args[:element_type]
|
184
|
+
self.element_type = args[:element_type]
|
185
|
+
else
|
186
|
+
if bet = back_element_type(args)
|
187
|
+
self.element_type = bet
|
188
|
+
else
|
189
|
+
raise "No element_type specified or inferred"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# extends this class with any modules passed to {#initialize} in the
|
195
|
+
# :modules key.
|
196
|
+
def include_other_modules(args)
|
197
|
+
if mods = args[:modules]
|
198
|
+
@modules = [*mods]
|
199
|
+
@modules.each do |mod|
|
200
|
+
extend mod
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Copy extensions from the previous route in the chain if the
|
206
|
+
# previous route's element type is the same as the current route's
|
207
|
+
# element type and no extensions were explicitly set on this route.
|
208
|
+
def include_extensions(args)
|
209
|
+
if back_element_type(args) == self.element_type and not args.key? :extensions and not args.key? :wrapper
|
210
|
+
back_obj = back_object(args)
|
211
|
+
if not wrapper and extensions.none?
|
212
|
+
self.wrapper = back_obj.wrapper if back_obj.respond_to? :wrapper
|
213
|
+
self.extensions = back_obj.extensions if back_obj.respond_to? :extensions
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Creates a terse, human-friendly name for the class based on its
|
219
|
+
# element type, function and info.
|
220
|
+
# @return [String]
|
221
|
+
def inspect_class_name
|
222
|
+
s = "#{element_type.to_s.scan(/Elem|Obj|V|E/).last}"
|
223
|
+
s = "#{s}-#{function.name.split('::').last.sub(/Filter|Route$/, '')}" if function
|
224
|
+
s = "#{s} #{ @info }" if @info
|
225
|
+
s
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
data/lib/pacer/routes.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes::RouteOperations
|
3
|
+
def aggregate(into = nil)
|
4
|
+
chain_route :side_effect => :aggregate, :into => into
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module SideEffect
|
9
|
+
module Aggregate
|
10
|
+
import com.tinkerpop.pipes.sideeffect.AggregatePipe
|
11
|
+
import java.util.HashSet
|
12
|
+
|
13
|
+
attr_accessor :into
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def attach_pipe(end_pipe)
|
18
|
+
if into.is_a? Symbol
|
19
|
+
hs = vars[into] = HashSet.new
|
20
|
+
pipe = AggregatePipe.new hs
|
21
|
+
elsif into
|
22
|
+
pipe = AggregatePipe.new into
|
23
|
+
else
|
24
|
+
pipe = AggregatePipe.new HashSet.new
|
25
|
+
end
|
26
|
+
pipe.setStarts end_pipe if end_pipe
|
27
|
+
pipe
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def counted
|
5
|
+
chain_route :side_effect => :counted
|
6
|
+
end
|
7
|
+
|
8
|
+
def count
|
9
|
+
counted.count
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
module SideEffect
|
16
|
+
module Counted
|
17
|
+
def count
|
18
|
+
cap.first
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def attach_pipe(end_pipe)
|
24
|
+
@pipe = com.tinkerpop.pipes.sideeffect.CountPipe.new
|
25
|
+
@pipe.setStarts(end_pipe) if end_pipe
|
26
|
+
@pipe
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes::RouteOperations
|
3
|
+
def fast_group_count(hash_map = nil)
|
4
|
+
chain_route :side_effect => :group_count, :hash_map => hash_map
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module SideEffect
|
9
|
+
module GroupCount
|
10
|
+
def hash_map=(hash_map)
|
11
|
+
@hash_map = hash_map
|
12
|
+
end
|
13
|
+
|
14
|
+
def at_least(n)
|
15
|
+
@min = n
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
c = 0
|
21
|
+
each { c = c + 1 }
|
22
|
+
puts c
|
23
|
+
h = {}
|
24
|
+
min = @min || 0
|
25
|
+
side_effect.each do |k,v|
|
26
|
+
h[k] = v if v >= min
|
27
|
+
end
|
28
|
+
h
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def attach_pipe(end_pipe)
|
34
|
+
if @hash_map
|
35
|
+
@pipe = com.tinkerpop.pipes.sideeffect.GroupCountPipe.new @hash_map
|
36
|
+
else
|
37
|
+
@pipe = com.tinkerpop.pipes.sideeffect.GroupCountPipe.new
|
38
|
+
end
|
39
|
+
@pipe.set_starts(end_pipe) if end_pipe
|
40
|
+
@pipe
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def is_unique
|
5
|
+
chain_route :side_effect => :is_unique
|
6
|
+
end
|
7
|
+
|
8
|
+
def unique?
|
9
|
+
is_unique.unique?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
module SideEffect
|
16
|
+
module IsUnique
|
17
|
+
def unique?
|
18
|
+
pipe do |pipe|
|
19
|
+
pipe.next while pipe.unique?
|
20
|
+
end.unique?
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def attach_pipe(end_pipe)
|
26
|
+
@pipe = Pacer::Pipes::IsUniquePipe.new
|
27
|
+
@pipe.setStarts(end_pipe) if end_pipe
|
28
|
+
@pipe
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def section(section_name = nil)
|
5
|
+
chain_route side_effect: :section, section_name: section_name
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module SideEffect
|
11
|
+
module Section
|
12
|
+
attr_accessor :section_name
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
attr_reader :section_visitor
|
17
|
+
|
18
|
+
def attach_pipe(end_pipe)
|
19
|
+
@section_visitor = pipe = Pacer::Pipes::SimpleVisitorPipe.new
|
20
|
+
pipe.setStarts end_pipe if end_pipe
|
21
|
+
pipe
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def visitor(visitor)
|
5
|
+
chain_route side_effect: :visitor, visitor: visitor
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module SideEffect
|
11
|
+
module Visitor
|
12
|
+
attr_reader :visitor
|
13
|
+
|
14
|
+
def visitor=(v)
|
15
|
+
@visitor = v
|
16
|
+
@visitor = @visitor.on_route(self) if @visitor.respond_to? :on_route
|
17
|
+
end
|
18
|
+
|
19
|
+
def element_type
|
20
|
+
if @visitor.respond_to? :element_type
|
21
|
+
@visitor.element_type
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def attach_pipe(end_pipe)
|
30
|
+
pipe = @visitor.attach_pipe(end_pipe) if @visitor.respond_to? :attach_pipe
|
31
|
+
pipe ||= Pacer::Pipes::VisitorPipe.new(visitor)
|
32
|
+
pipe.setStarts end_pipe if end_pipe
|
33
|
+
pipe
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Pacer
|
2
|
+
module SideEffect
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'pacer/side_effect/aggregate'
|
7
|
+
require 'pacer/side_effect/group_count'
|
8
|
+
require 'pacer/side_effect/is_unique'
|
9
|
+
require 'pacer/side_effect/counted'
|
10
|
+
require 'pacer/side_effect/section'
|
11
|
+
require 'pacer/side_effect/visitor'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
java.util.ArrayList
|
2
|
+
class Java::JavaUtil::ArrayList
|
3
|
+
def inspect
|
4
|
+
to_a.inspect
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
java.util.LinkedList
|
9
|
+
class Java::JavaUtil::LinkedList
|
10
|
+
def inspect
|
11
|
+
to_a.inspect
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'set'
|
16
|
+
java.util.HashSet
|
17
|
+
class Java::JavaUtil::HashSet
|
18
|
+
def inspect
|
19
|
+
to_set.inspect.sub(/Set/, 'HashSet')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
java.util.HashMap
|
24
|
+
class Java::JavaUtil::HashMap
|
25
|
+
def to_hash_map
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Extend the built-in Enumerable module:
|
2
|
+
module Enumerable
|
3
|
+
|
4
|
+
def one?
|
5
|
+
counter = 0
|
6
|
+
each do
|
7
|
+
return false if counter == 1
|
8
|
+
counter += 1
|
9
|
+
end
|
10
|
+
counter == 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def many?
|
14
|
+
counter = 0
|
15
|
+
any? { if counter == 1; true; else; counter += 1; false; end }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Transform the enumerable into a java HashSet.
|
19
|
+
def to_hashset(method = nil, *args)
|
20
|
+
return self if self.is_a? java.util.HashSet and not method
|
21
|
+
hs = java.util.HashSet.new
|
22
|
+
iter = self.each rescue nil
|
23
|
+
if not iter and respond_to? :iterator
|
24
|
+
iter = self.iterator
|
25
|
+
end
|
26
|
+
e = iter.next
|
27
|
+
if method
|
28
|
+
while true
|
29
|
+
hs.add e.send(method, *args)
|
30
|
+
e = iter.next
|
31
|
+
end
|
32
|
+
else
|
33
|
+
while true
|
34
|
+
hs.add e
|
35
|
+
e = iter.next
|
36
|
+
end
|
37
|
+
end
|
38
|
+
rescue StopIteration
|
39
|
+
hs
|
40
|
+
rescue NativeException => e
|
41
|
+
if (e.cause.kind_of?(java.util.NoSuchElementException))
|
42
|
+
hs
|
43
|
+
else
|
44
|
+
raise
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# NOTE: if this is a collection of wrapped vertices or edges, Java pipes
|
49
|
+
# may crash with something like:
|
50
|
+
#
|
51
|
+
# NativeException: java.lang.ClassCastException: org.jruby.RubyObject cannot be cast to com.tinkerpop.blueprints.pgm.Element
|
52
|
+
#
|
53
|
+
# You can work around that by passing the option :unwrap => true or
|
54
|
+
# setting the :based_on parameter to a route that has extensions.
|
55
|
+
def to_route(opts = {})
|
56
|
+
if self.is_a? Pacer::Core::Route
|
57
|
+
self
|
58
|
+
else
|
59
|
+
based_on = opts[:based_on]
|
60
|
+
if opts[:unwrap] or based_on and (based_on.wrapper or based_on.extensions.any?) and based_on.is_a? Pacer::Core::Graph::ElementRoute
|
61
|
+
source = Pacer::Route.new(:source => self, :element_type => :object).map { |e| e.element }
|
62
|
+
else
|
63
|
+
source = self
|
64
|
+
end
|
65
|
+
if based_on
|
66
|
+
Pacer::Route.new(:source => source, :element_type => opts.fetch(:element_type, based_on.element_type), :graph => based_on.graph, :wrapper => based_on.wrapper, :extensions => based_on.extensions, :info => based_on.info)
|
67
|
+
else
|
68
|
+
graph = opts[:graph] if opts[:graph]
|
69
|
+
Pacer::Route.new(:source => source, :element_type => opts.fetch(:element_type, :object), :graph => graph, :wrapper => opts[:wrapper], :extensions => opts[:extensions], :info => opts[:info])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def id_to_element_route(args = {})
|
75
|
+
based_on = args[:based_on]
|
76
|
+
raise 'Must supply :based_on option' unless based_on
|
77
|
+
raise 'Graph routes do not contain element ids to look up' if self.is_a? Pacer::Core::Route and graph
|
78
|
+
raise 'Based on route must be a graph route' unless based_on.graph
|
79
|
+
r = to_route(:info => "#{ count } ids")
|
80
|
+
r.chain_route(:graph => based_on.graph,
|
81
|
+
:element_type => based_on.element_type,
|
82
|
+
:pipe_class => based_on.send(:id_pipe_class),
|
83
|
+
:pipe_args => [based_on.graph],
|
84
|
+
:route_name => 'lookup',
|
85
|
+
:extensions => based_on.extensions,
|
86
|
+
:wrapper => based_on.wrapper,
|
87
|
+
:info => [args[:name], based_on.info].compact.join(':')).is_not(nil)
|
88
|
+
end
|
89
|
+
|
90
|
+
def group_count
|
91
|
+
result = Hash.new(0)
|
92
|
+
if block_given?
|
93
|
+
each { |e| result[yield(e)] += 1 }
|
94
|
+
else
|
95
|
+
each { |e| result[e] += 1 }
|
96
|
+
end
|
97
|
+
result
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Pacer::Core::Route
|
2
|
+
# This mixin allows an iterator to be returned from methods that perform a
|
3
|
+
# transformation on the elements in their collection. Set the block property
|
4
|
+
# to the proc that does the transformation.
|
5
|
+
module IteratorBlockMixin
|
6
|
+
attr_accessor :graph
|
7
|
+
|
8
|
+
# Set the block that does the transformation.
|
9
|
+
def block=(block)
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def next
|
14
|
+
item = super
|
15
|
+
item.graph ||= @graph
|
16
|
+
@block.call(item)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module IteratorPathMixin
|
21
|
+
attr_accessor :graph
|
22
|
+
|
23
|
+
def next
|
24
|
+
super.collect do |e|
|
25
|
+
e.graph ||= @graph if e.respond_to? :graph=
|
26
|
+
e
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module IteratorExtensionsMixin
|
32
|
+
attr_accessor :graph, :extensions
|
33
|
+
|
34
|
+
def next
|
35
|
+
item = super
|
36
|
+
# TODO: optimize this (and other) check:
|
37
|
+
# - exception?
|
38
|
+
# - type check?
|
39
|
+
# - method check?
|
40
|
+
# - ...?
|
41
|
+
if item.respond_to? :graph=
|
42
|
+
item = item.add_extensions @extensions
|
43
|
+
item.graph ||= @graph
|
44
|
+
end
|
45
|
+
item
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module IteratorWrapperMixin
|
50
|
+
attr_reader :graph, :extensions, :wrapper
|
51
|
+
|
52
|
+
def wrapper=(w)
|
53
|
+
@base_wrapper = w
|
54
|
+
@wrapper = build_wrapper?
|
55
|
+
@set_graph = set_graph?
|
56
|
+
end
|
57
|
+
|
58
|
+
def graph=(g)
|
59
|
+
@graph = g
|
60
|
+
@wrapper = build_wrapper?
|
61
|
+
@set_graph = set_graph?
|
62
|
+
end
|
63
|
+
|
64
|
+
def extensions=(exts)
|
65
|
+
@extensions = exts
|
66
|
+
@wrapper = build_wrapper?
|
67
|
+
@set_graph = set_graph?
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_wrapper?
|
71
|
+
@base_wrapper = nil unless defined? @base_wrapper
|
72
|
+
@extensions = nil unless defined? @extensions
|
73
|
+
if @base_wrapper and @extensions
|
74
|
+
@wrapper = @base_wrapper.wrapper_for(@base_wrapper.extensions + @extensions.to_a)
|
75
|
+
elsif @base_wrapper
|
76
|
+
@wrapper = @base_wrapper
|
77
|
+
elsif @extensions
|
78
|
+
# We don't know what type of wrapper to create
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if RUBY_VERSION =~ /^1\.8\./
|
83
|
+
def set_graph?
|
84
|
+
graph and wrapper and wrapper.instance_methods.include?('graph=')
|
85
|
+
end
|
86
|
+
else
|
87
|
+
def set_graph?
|
88
|
+
graph and wrapper and wrapper.instance_methods.include?(:graph=)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def next
|
93
|
+
item = wrapper.new(super)
|
94
|
+
item.graph ||= graph if @set_graph
|
95
|
+
item
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
module IteratorMixin
|
100
|
+
attr_accessor :graph
|
101
|
+
|
102
|
+
def next
|
103
|
+
item = super
|
104
|
+
if item.respond_to? :graph=
|
105
|
+
item.graph ||= @graph
|
106
|
+
end
|
107
|
+
item
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|