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,361 @@
1
+ module Pacer
2
+ # Methods to be mixed into Blueprints Graph objects from any
3
+ # implementation.
4
+ #
5
+ # Adds more convenient/rubyish methods and adds support for extensions
6
+ # to some methods where needed.
7
+ module GraphMixin
8
+ def self.included(target)
9
+ target.class_eval do
10
+ protected :addVertex, :addEdge
11
+ protected :add_vertex, :add_edge rescue nil
12
+ protected :getVertex, :getEdge
13
+ protected :get_vertex, :get_edge rescue nil
14
+ end
15
+ end
16
+
17
+ attr_accessor :in_bulk_job
18
+
19
+ def graph_id
20
+ @graph_id = Pacer.next_graph_id unless defined? @graph_id
21
+ @graph_id
22
+ end
23
+
24
+ # Get a vertex by id.
25
+ #
26
+ # @overload vertex(id)
27
+ # @param [element id] id
28
+ # @overload vertex(id, *modules)
29
+ # @param [element id] id
30
+ # @param [Module, Class] *modules extensions to add to the returned
31
+ # vertex.
32
+ def vertex(id, *modules)
33
+ v = getVertex(id) rescue nil
34
+ if v
35
+ wrapper = modules.detect { |obj| obj.ancestors.include? Pacer::Wrappers::VertexWrapper }
36
+ if wrapper
37
+ v = wrapper.new v
38
+ modules.delete wrapper
39
+ end
40
+ v.graph = self
41
+ v.add_extensions modules
42
+ else
43
+ v
44
+ end
45
+ end
46
+
47
+ # Get an edge by id.
48
+ #
49
+ # @overload edge(id)
50
+ # @param [element id] id
51
+ # @overload edge(id, *modules)
52
+ # @param [element id] id
53
+ # @param [Module, Class] *modules extensions to add to the returned
54
+ # edge.
55
+ def edge(id, *modules)
56
+ v = getEdge(id) rescue nil
57
+ if v
58
+ wrapper = modules.detect { |obj| obj.ancestors.include? Pacer::Wrappers::EdgeWrapper }
59
+ if wrapper
60
+ v = wrapper.new v
61
+ modules.delete wrapper
62
+ end
63
+ v.graph = self
64
+ v.add_extensions modules
65
+ end
66
+ end
67
+
68
+ # Create a vertex in the graph.
69
+ #
70
+ # @overload create_vertex(*args)
71
+ # @param [extension, Hash] *args extension (Module/Class) arguments will be
72
+ # added to the current vertex. A Hash will be
73
+ # treated as element properties.
74
+ # @overload create_vertex(id, *args)
75
+ # @param [element id] id the desired element id. Some graphs
76
+ # ignore this.
77
+ # @param [extension, Hash] *args extension (Module/Class) arguments will be
78
+ # added to the current vertex. A Hash will be
79
+ # treated as element properties.
80
+ def create_vertex(*args)
81
+ id, wrapper, modules, props = id_modules_properties(args)
82
+ vertex = creating_elements { addVertex(id) }
83
+ vertex = wrapper.new vertex if wrapper
84
+ vertex.graph = self
85
+ props.each { |k, v| vertex[k.to_s] = v } if props
86
+ if modules.any?
87
+ vertex.add_extensions modules
88
+ else
89
+ vertex
90
+ end
91
+ end
92
+
93
+ # Create an edge in the graph.
94
+ #
95
+ # @param [element id] id some graphs allow you to specify your own edge id.
96
+ # @param [Pacer::VertexMixin] from_v the new edge's out_vertex
97
+ # @param [Pacer::VertexMixin] to_v the new edge's in_vertex
98
+ # @param [#to_s] label the edge label
99
+ # @param [extension, Hash] *args extension (Module/Class) arguments will be
100
+ # added to the returned edge. A Hash will be
101
+ # treated as element properties.
102
+ #
103
+ # @todo make id param optional
104
+ def create_edge(id, from_v, to_v, label, *args)
105
+ _, wrapper, modules, props = id_modules_properties(args)
106
+ edge = creating_elements { addEdge(id, from_v.element, to_v.element, label) }
107
+ edge = wrapper.new edge if wrapper
108
+ edge.graph = self
109
+ props.each { |k, v| edge[k.to_s] = v } if props
110
+ if modules.any?
111
+ edge.add_extensions modules
112
+ else
113
+ edge
114
+ end
115
+ end
116
+
117
+ # Import the data in a GraphML file.
118
+ #
119
+ # Will fail if the data already exsts in the current graph.
120
+ #
121
+ # @param [String] path
122
+ def import(path)
123
+ path = File.expand_path path
124
+ begin
125
+ stream = java.net.URL.new(path).open_stream
126
+ rescue java.net.MalformedURLException
127
+ stream = java.io.FileInputStream.new path
128
+ end
129
+ creating_elements do
130
+ com.tinkerpop.blueprints.pgm.util.graphml.GraphMLReader.input_graph self, stream
131
+ end
132
+ true
133
+ ensure
134
+ stream.close if stream
135
+ end
136
+
137
+ # Export the graph to GraphML
138
+ #
139
+ # @param [String] path will be replaced if it exists
140
+ def export(path)
141
+ path = File.expand_path path
142
+ stream = java.io.FileOutputStream.new path
143
+ com.tinkerpop.blueprints.pgm.util.graphml.GraphMLWriter.outputGraph self, stream
144
+ ensure
145
+ stream.close if stream
146
+ end
147
+
148
+ # Set how many elements should go into each transaction in a bulk
149
+ # job.
150
+ #
151
+ # @param [Fixnum] size number of elements
152
+ def bulk_job_size=(size)
153
+ @bulk_job_size = size
154
+ end
155
+
156
+ # The currently configured bulk job size.
157
+ def bulk_job_size
158
+ if defined? @bulk_job_size
159
+ @bulk_job_size
160
+ else
161
+ 5000
162
+ end
163
+ end
164
+
165
+ # Are we currently in the midst of a bulk job?
166
+ def in_bulk_job?
167
+ @in_bulk_job if defined? @in_bulk_job
168
+ end
169
+
170
+ # Directly loads an array of vertices by id.
171
+ #
172
+ # @param [[vertex ids]] ids
173
+ # @return [[Pacer::VertexMixin]]
174
+ def load_vertices(ids)
175
+ ids.map do |id|
176
+ vertex id
177
+ end.compact
178
+ end
179
+
180
+ # Directly loads an array of edges by id.
181
+ #
182
+ # @param [[edge ids]] ids
183
+ # @return [[Pacer::EdgeMixin]]
184
+ def load_edges(ids)
185
+ ids.map do |id|
186
+ edge id
187
+ end.compact
188
+ end
189
+
190
+ # The current graph
191
+ #
192
+ # @return [Graph] returns self
193
+ def graph
194
+ self
195
+ end
196
+
197
+ def equals(other)
198
+ self == other
199
+ end
200
+
201
+ # The proc used to name vertices.
202
+ #
203
+ # @return [Proc]
204
+ def vertex_name
205
+ @vertex_name if defined? @vertex_name
206
+ end
207
+
208
+ # Set the proc used to name vertices.
209
+ #
210
+ # @param [Proc(vertex)] a_proc returns a string given a vertex
211
+ def vertex_name=(a_proc)
212
+ @vertex_name = a_proc
213
+ end
214
+
215
+ # The proc used to name edges.
216
+ #
217
+ # @return [Proc]
218
+ def edge_name
219
+ @edge_name if defined? @edge_name
220
+ end
221
+
222
+ # Set the proc used to name edges.
223
+ #
224
+ # @param [Proc(edge)] a_proc returns a string given an edge
225
+ def edge_name=(a_proc)
226
+ @edge_name = a_proc
227
+ end
228
+
229
+ # Is the element type given supported by this graph?
230
+ #
231
+ # @param [:edge, :vertex, :mixed, element_type, Object] et the
232
+ # object we're testing
233
+ def element_type?(et)
234
+ if [element_type(:vertex), element_type(:edge), element_type(:mixed)].include? element_type(et)
235
+ true
236
+ else
237
+ false
238
+ end
239
+ end
240
+
241
+ # Does this graph support edges where the in_vertex and the
242
+ # out_vertex are the same?
243
+ #
244
+ # Specific graphs may override this method to return false.
245
+ def supports_circular_edges?
246
+ true
247
+ end
248
+
249
+ # When creating an element, does this graph allow me to specify the
250
+ # element_id?
251
+ #
252
+ # Specific graphs may override this method to return false.
253
+ def supports_custom_element_ids?
254
+ true
255
+ end
256
+
257
+ # Does this graph allow me to create or modify automatic indices?
258
+ #
259
+ # Specific graphs may override this method to return false.
260
+ def supports_automatic_indices?
261
+ false
262
+ end
263
+
264
+ # Does this graph allow me to create or modify manual indices?
265
+ #
266
+ # Specific graphs may override this method to return false.
267
+ def supports_manual_indices?
268
+ false
269
+ end
270
+
271
+ # Does this graph support indices on edges?
272
+ #
273
+ # Specific graphs may override this method to return false.
274
+ def supports_edge_indices?
275
+ false
276
+ end
277
+
278
+ def element_type(et = nil)
279
+ return nil unless et
280
+ result = if et == vertex_class or et == edge_class or et == element_class
281
+ et
282
+ else
283
+ case et
284
+ when :vertex, Pacer::Vertex, VertexMixin
285
+ vertex_class
286
+ when :edge, Pacer::Edge, EdgeMixin
287
+ edge_class
288
+ when :mixed, Pacer::Element, ElementMixin
289
+ element_class
290
+ when :object
291
+ Object
292
+ else
293
+ if et == Object
294
+ Object
295
+ elsif vertex_class.respond_to? :java_class
296
+ if et == vertex_class.java_class.to_java
297
+ vertex_class
298
+ elsif et == edge_class.java_class.to_java
299
+ edge_class
300
+ elsif et == Pacer::Vertex.java_class.to_java
301
+ vertex_class
302
+ elsif et == Pacer::Edge.java_class.to_java
303
+ edge_class
304
+ end
305
+ end
306
+ end
307
+ end
308
+ if result
309
+ result
310
+ else
311
+ raise ArgumentError, 'Element type may be one of :vertex, :edge, :mixed or :object'
312
+ end
313
+ end
314
+
315
+ def sanitize_properties(props)
316
+ props
317
+ end
318
+
319
+ def encode_property(value)
320
+ if value.is_a? String
321
+ value = value.strip
322
+ value unless value == ''
323
+ else
324
+ value
325
+ end
326
+ end
327
+
328
+ def decode_property(value)
329
+ value
330
+ end
331
+
332
+ def edges
333
+ getEdges
334
+ end
335
+
336
+ protected
337
+
338
+ # Helper method to wrap element creation in exception handling.
339
+ def creating_elements
340
+ begin
341
+ yield
342
+ rescue NativeException => e
343
+ if e.message =~ /already exists/
344
+ raise ElementExists, e.message
345
+ else
346
+ raise
347
+ end
348
+ end
349
+ end
350
+
351
+ def id_modules_properties(args)
352
+ props = args.last if args.last.is_a? Hash
353
+ modules = args.select { |obj| obj.is_a? Module or obj.is_a? Class }
354
+ wrapper = modules.detect { |obj| obj.is_a? Class and obj.ancestors.include? Pacer::Wrappers::ElementWrapper }
355
+ modules.delete wrapper
356
+ id = args.first
357
+ id = nil if id == props or modules.include? id or id == wrapper
358
+ [id, wrapper, modules, props]
359
+ end
360
+ end
361
+ end
@@ -0,0 +1,207 @@
1
+ module Pacer
2
+ import com.tinkerpop.blueprints.pgm.TransactionalGraph
3
+
4
+ # Collect a global set of graphs that are currently in a transaction.
5
+ #
6
+ # @return [Set] graphs with an open transaction
7
+ def self.graphs_in_transaction
8
+ @graphs = Set[] unless defined? @graphs
9
+ @graphs
10
+ end
11
+
12
+ # Methods used internally to do 'managed transactions' which I define
13
+ # as transactions that are started and committed automatically
14
+ # internally, typically on operations that potentially touch a large
15
+ # number of elements.
16
+ #
17
+ # The reason for keeping track of these separately is to prevent them
18
+ # from being confused with manual transactions. Although when this was
19
+ # written, I had made manual transactions nestable. That has been
20
+ # since explicitly disallowed by Blueprints. I am not sure if this
21
+ # code is actually needed anymore (if it was refactored out).
22
+ #
23
+ # TODO: the method names in this module need to be cleaned up.
24
+ # TODO: some methods may be able to be eliminated.
25
+ module ManagedTransactionsMixin
26
+ def manage_transactions=(v)
27
+ @manage_transactions = v
28
+ end
29
+
30
+ def manage_transactions?
31
+ @manage_transactions = true unless defined? @manage_transactions
32
+ @manage_transactions
33
+ end
34
+ alias manage_transactions manage_transactions?
35
+
36
+ def unmanaged_transactions
37
+ old_value = manage_transactions
38
+ @manage_transactions = false
39
+ yield
40
+ ensure
41
+ @manage_transactions = old_value
42
+ end
43
+
44
+ def managed_transactions
45
+ if manage_transactions?
46
+ manual_transactions { yield }
47
+ else
48
+ yield
49
+ end
50
+ end
51
+
52
+ def managed_manual_transaction
53
+ if manage_transactions?
54
+ manual_transaction { yield }
55
+ else
56
+ yield
57
+ end
58
+ end
59
+
60
+ def managed_transaction
61
+ if manage_transactions?
62
+ transaction { yield }
63
+ else
64
+ yield
65
+ end
66
+ end
67
+
68
+ def managed_start_transaction
69
+ begin_transaction if manage_transactions?
70
+ end
71
+
72
+ def managed_commit_transaction
73
+ commit_transaction if manage_transactions?
74
+ end
75
+
76
+ def managed_checkpoint
77
+ checkpoint if manage_transactions?
78
+ end
79
+ end
80
+
81
+ # This is included into graphs that don't support transactions so that
82
+ # their interface is the same as for graphs that do support them.
83
+ #
84
+ # All methods in this module do nothing but yield or return values
85
+ # that match those in {GraphTransactionsMixin}
86
+ module GraphTransactionsStub
87
+ def in_transaction?
88
+ false
89
+ end
90
+
91
+ def manual_transaction
92
+ yield
93
+ end
94
+
95
+ def manual_transactions
96
+ yield
97
+ end
98
+
99
+ def transaction
100
+ yield
101
+ end
102
+
103
+ def begin_transaction
104
+ end
105
+
106
+ def commit_transaction
107
+ end
108
+
109
+ def rollback_transaction
110
+ end
111
+
112
+ def checkpoint
113
+ end
114
+ end
115
+
116
+ # Add features to transactions to allow them to be more rubyish and
117
+ # more convenient to use.
118
+ #
119
+ # TODO: the method names in this module need to be cleaned up.
120
+ # TODO: some methods may be able to be eliminated.
121
+ module GraphTransactionsMixin
122
+ def self.included(target)
123
+ target.send :protected, :startTransaction, :start_transaction
124
+ end
125
+
126
+ def in_transaction?
127
+ Pacer.graphs_in_transaction.include? self
128
+ end
129
+
130
+ def manual_transaction
131
+ manual_transactions do
132
+ transaction do
133
+ yield
134
+ end
135
+ end
136
+ end
137
+
138
+ def manual_transactions
139
+ original_buffer_size = getMaxBufferSize
140
+ if original_buffer_size != 0
141
+ begin
142
+ puts "transaction buffer size reset to 0 (MANUAL)" if Pacer.verbose == :very
143
+ setMaxBufferSize 0
144
+ yield
145
+ rescue Exception
146
+ rollback_transaction if in_transaction?
147
+ raise
148
+ ensure
149
+ puts "transaction buffer size reset to #{ original_buffer_size }" if Pacer.verbose == :very
150
+ setMaxBufferSize original_buffer_size
151
+ end
152
+ else
153
+ yield
154
+ end
155
+ end
156
+
157
+ def transaction
158
+ begin_transaction
159
+ conclusion = TransactionalGraph::Conclusion::FAILURE
160
+ begin
161
+ catch :transaction_failed do
162
+ yield
163
+ conclusion = TransactionalGraph::Conclusion::SUCCESS
164
+ end
165
+ rescue Exception
166
+ puts "transaction aborted" if Pacer.verbose == :very
167
+ raise
168
+ ensure
169
+ puts "transaction finished #{ conclusion }" if Pacer.verbose == :very
170
+ stop_transaction conclusion
171
+ Pacer.graphs_in_transaction.delete self
172
+ end
173
+ end
174
+
175
+ def begin_transaction
176
+ r = startTransaction
177
+ Pacer.graphs_in_transaction << self
178
+ puts "transaction started" if Pacer.verbose == :very
179
+ r
180
+ end
181
+
182
+ def commit_transaction
183
+ r = stop_transaction TransactionalGraph::Conclusion::SUCCESS
184
+ Pacer.graphs_in_transaction.delete self
185
+ puts "transaction committed" if Pacer.verbose == :very
186
+ r
187
+ end
188
+
189
+ def rollback_transaction
190
+ r = stop_transaction TransactionalGraph::Conclusion::FAILURE
191
+ Pacer.graphs_in_transaction.delete self
192
+ puts "transaction rolled back" if Pacer.verbose == :very
193
+ r
194
+ end
195
+
196
+ def checkpoint(success = true)
197
+ if success
198
+ commit_transaction
199
+ else
200
+ rollback_transaction
201
+ end
202
+ begin_transaction
203
+ Pacer.graphs_in_transaction << self
204
+ end
205
+
206
+ end
207
+ end
@@ -0,0 +1,30 @@
1
+ module Pacer
2
+ module IndexMixin
3
+ def graph=(graph)
4
+ @graph = graph
5
+ end
6
+
7
+ def graph
8
+ @graph if defined? @graph
9
+ end
10
+
11
+ def first(key, value, extensions = nil)
12
+ e = get(key, value).first
13
+ if e and (graph or extensions)
14
+ e.graph = graph
15
+ e.add_extensions extensions
16
+ end
17
+ e
18
+ end
19
+
20
+ def all(key, value, extensions = nil)
21
+ iter = get(key, value)
22
+ if graph or extensions
23
+ iter.extend Pacer::Core::Route::IteratorExtensionsMixin
24
+ iter.graph = graph
25
+ iter.extensions = extensions
26
+ end
27
+ iter
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,119 @@
1
+ module Pacer
2
+ # This module is mixed into the raw Blueprints Vertex class from any
3
+ # graph implementation.
4
+ #
5
+ # Adds more convenient/rubyish methods and adds support for extensions
6
+ # to some methods where needed.
7
+ module VertexMixin
8
+ # Add extensions to this vertex.
9
+ #
10
+ # If any extension has a Vertex module within it, this vertex will
11
+ # be extended with the extension's Vertex module.
12
+ #
13
+ # @see Core::Route#add_extension
14
+ #
15
+ # @param [[extensions]] exts the extensions to add
16
+ # @return [Pacer::EdgeWrapper] this vertex wrapped up and including
17
+ # the extensions
18
+ def add_extensions(exts)
19
+ if exts.any?
20
+ Wrappers::VertexWrapper.wrap(self, exts)
21
+ else
22
+ self
23
+ end
24
+ end
25
+
26
+ # Returns a human-readable representation of the vertex using the
27
+ # standard ruby console representation of an instantiated object.
28
+ # @return [String]
29
+ def inspect
30
+ "#<#{ ["V[#{element_id}]", display_name].compact.join(' ') }>"
31
+ end
32
+
33
+ # Returns the display name of the vertex.
34
+ # @return [String]
35
+ def display_name
36
+ graph.vertex_name.call self if graph and graph.vertex_name
37
+ end
38
+
39
+ # Deletes the vertex from its graph along with all related edges.
40
+ def delete!
41
+ graph.removeVertex element
42
+ end
43
+
44
+ # Copies including the vertex id unless a vertex with that id
45
+ # already exists.
46
+ # @param [Pacer::GraphMixin] target_graph
47
+ # @param opts for compatibility with {Pacer::EdgeMixin#clone_into}
48
+ # @yield [v] Optional block yields the vertex after it has been created.
49
+ # @return [Pacer::VertexMixin] the new vertex
50
+ def clone_into(target_graph, opts = nil)
51
+ v_idx = target_graph.index_name("tmp:v:#{graph.to_s}", :vertex, :create => true)
52
+ v = target_graph.vertex(element_id) || v_idx.get('id', element_id).first
53
+ unless v
54
+ v = target_graph.create_vertex element_id, properties
55
+ v_idx.put('id', element_id, v)
56
+ yield v if block_given?
57
+ end
58
+ v
59
+ end
60
+
61
+ # Make a new copy of the element with the next available vertex id.
62
+ #
63
+ # @param [Pacer::GraphMixin] target_graph
64
+ # @yield [v] Optional block yields the vertex after it has been created.
65
+ # @return [Pacer::VertexMixin] the new vertex
66
+ def copy_into(target_graph)
67
+ v = target_graph.create_vertex properties
68
+ yield v if block_given?
69
+ v
70
+ end
71
+
72
+ def raw_out_edges(*labels)
73
+ element.getOutEdges *labels
74
+ end
75
+
76
+ def raw_in_edges(*labels)
77
+ element.getInEdges *labels
78
+ end
79
+
80
+ def out_edges(*labels_and_extensions)
81
+ labels, exts = split_labels_and_extensions(labels_and_extensions)
82
+ edge_iterator(raw_out_edges(*labels).iterator, exts)
83
+ end
84
+
85
+ def in_edges(*labels_and_extensions)
86
+ labels, exts = split_labels_and_extensions(labels_and_extensions)
87
+ edge_iterator(raw_in_edges(*labels).iterator, exts)
88
+ end
89
+
90
+ def both_edges(*labels_and_extensions)
91
+ labels, exts = split_labels_and_extensions(labels_and_extensions)
92
+ ins = raw_in_edges(*labels).iterator
93
+ outs = raw_out_edges(*labels).iterator
94
+ edge_iterator(Pacer::Pipes::MultiIterator.new(ins, outs), exts)
95
+ end
96
+
97
+ protected
98
+
99
+ def split_labels_and_extensions(mixed)
100
+ labels = Set[]
101
+ exts = Set[]
102
+ mixed.each do |obj|
103
+ if obj.is_a? Symbol or obj.is_a? String
104
+ labels << obj
105
+ else
106
+ exts << obj
107
+ end
108
+ end
109
+ [labels, exts]
110
+ end
111
+
112
+ def edge_iterator(iter, exts)
113
+ iter.extend Pacer::Core::Route::IteratorExtensionsMixin
114
+ iter.graph = self.graph
115
+ iter.extensions = exts
116
+ iter
117
+ end
118
+ end
119
+ end