pacer 1.2.0-java → 1.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 873067a94942616e42ecb659e821bdf1f13c6bd4
4
+ data.tar.gz: 91c4e71707fa23b969e6205d650a981464d2b4a5
5
+ SHA512:
6
+ metadata.gz: bacb0e4e165bd10005d090cc7e1cd1fae2954b88901725078729c2fdd62e202c7f42237ed1d62b2d08aa5b1864b061eceb6638bc3900dbf9ccfbedfef32179fa
7
+ data.tar.gz: 687bc677f5ca3682ef2b012ed278731d2a2963f85f399ef4829b55a4dc35d6e82d504d4470e50a60c6dc5d19f8d2b19e93411801ef6ac60815b0ed22d84ed167
data/README.md CHANGED
@@ -203,3 +203,17 @@ I'm aiming for 100% test coverage in Pacer and am currently nearly there in the
203
203
  ## Style Guide
204
204
 
205
205
  Please follow Github's [Ruby style guide](https://github.com/styleguide/ruby) when contributing to make your patches more likely to be accepted!
206
+
207
+ ## YourKit Profiler
208
+
209
+ One of the advantages of building Pacer on JRuby is that we can leverage
210
+ the incredible tools that exist in the JVM ecosystem. YourKit is a tool
211
+ that I found through glowing recommendation, and has been greatly useful
212
+ in profiling the performance of Pacer.
213
+
214
+ YourKit is kindly supporting the Pacer open source project with its full-featured Java Profiler.
215
+ YourKit, LLC is the creator of innovative and intelligent tools for profiling
216
+ Java and .NET applications. Take a look at YourKit's leading software products:
217
+
218
+ <a href="http://www.yourkit.com/java/profiler/index.jsp">YourKit Java Profiler</a> and
219
+ <a href="http://www.yourkit.com/.net/profiler/index.jsp">YourKit .NET Profiler</a>.
@@ -23,7 +23,6 @@ module Pacer
23
23
 
24
24
  features.ignoresSuppliedIds = false
25
25
  features.isPersistent = false
26
- features.isRDFModel = false
27
26
  features.isWrapper = false
28
27
 
29
28
  features.supportsIndices = false
@@ -6,7 +6,7 @@ module Pacer::Core::Graph
6
6
  # Returns a new route to all graph vertices. Standard filter options.
7
7
  def v(*args, &block)
8
8
  filters = Pacer::Route.filters(args)
9
- if features.supportsIndices
9
+ if features.supportsKeyIndices or (search_manual_indices and features.supportsIndices)
10
10
  route = indexed_route(:vertex, filters, block)
11
11
  end
12
12
  if route
@@ -19,7 +19,7 @@ module Pacer::Core::Graph
19
19
  # Returns a new route to all graph edges. Standard filter options.
20
20
  def e(*args, &block)
21
21
  filters = Pacer::Route.edge_filters(args)
22
- if features.supportsIndices
22
+ if features.supportsKeyIndices or (search_manual_indices and features.supportsIndices)
23
23
  route = indexed_route(:edge, filters, block)
24
24
  end
25
25
  if route
@@ -55,11 +55,17 @@ HELP
55
55
 
56
56
  def payloads
57
57
  map element_type: :path, route_name: 'payloads' do |path|
58
- path.map do |e|
59
- if e.is_a? Pacer::Payload::Element
60
- e.payload
61
- elsif e.is_a? Pacer::Wrappers::ElementWrapper
62
- e.element_payload
58
+ path.flat_map do |e|
59
+ e = e.element if e.is_a? Pacer::Wrappers::ElementWrapper
60
+ r = []
61
+ while e.is_a? Pacer::Payload::Element
62
+ r.unshift e.payload
63
+ e = e.element
64
+ end
65
+ if r == []
66
+ [nil]
67
+ else
68
+ r
63
69
  end
64
70
  end
65
71
  end
@@ -34,6 +34,8 @@ module Pacer
34
34
 
35
35
  module PropertyFilter
36
36
  class Filters
37
+ NodeVisitor = Pacer::Filter::WhereFilter::NodeVisitor
38
+
37
39
  attr_reader :properties, :extensions, :route_modules, :best_index_value
38
40
  attr_accessor :wrapper, :blocks
39
41
 
@@ -112,11 +114,20 @@ module Pacer
112
114
  pipe = e
113
115
  end
114
116
  encoded_properties.each do |key, value|
115
- new_pipe = PropertyFilterPipe.new(key, value, Pacer::Pipes::EQUAL)
116
- new_pipe.set_starts pipe if pipe
117
- Pacer.debug_pipes << { :name => key, :start => pipe, :end => new_pipe } if Pacer.debug_pipes
118
- pipe = new_pipe
119
- start_pipe ||= pipe
117
+ case value
118
+ when NodeVisitor::Pipe
119
+ new_pipe = value.build
120
+ when NodeVisitor::Value
121
+ # no op
122
+ else
123
+ new_pipe = PropertyFilterPipe.new(key, value, Pacer::Pipes::EQUAL)
124
+ end
125
+ if new_pipe
126
+ new_pipe.set_starts pipe if pipe
127
+ Pacer.debug_pipes << { :name => key, :start => pipe, :end => new_pipe } if Pacer.debug_pipes
128
+ pipe = new_pipe
129
+ start_pipe ||= pipe
130
+ end
120
131
  end
121
132
  blocks.each do |block|
122
133
  block_pipe = Pacer::Pipes::BlockFilterPipe.new(route, block)
@@ -140,7 +151,13 @@ module Pacer
140
151
  strings = []
141
152
  strings << [wrapper.name] if wrapper
142
153
  strings.concat extensions.map { |e| e.name }
143
- strings.concat((non_ext_props - [@best_index_value]).map { |k, v| "#{ k }==#{ v.inspect }" })
154
+ strings.concat((non_ext_props - [@best_index_value]).map { |k, v|
155
+ if v.is_a? Set
156
+ "#{ k } IN (#{ v.sort.map { |s| s.inspect }.join ', ' })"
157
+ else
158
+ "#{ k }==#{ v.inspect }"
159
+ end
160
+ })
144
161
  strings.concat blocks.map { '&block' }
145
162
  strings.concat route_modules.map { |mod| mod.name }
146
163
  strings.join ', '
@@ -164,6 +181,7 @@ module Pacer
164
181
  when Hash
165
182
  reset_properties
166
183
  filter.each do |k, v|
184
+ v = v.first if v.is_a? Set and v.length == 1
167
185
  self.non_ext_props << [k.to_s, v] unless extension
168
186
  self.properties << [k.to_s, v]
169
187
  end
@@ -209,14 +227,22 @@ module Pacer
209
227
  end
210
228
  end
211
229
 
212
- def encode_value(value)
213
- value = graph.encode_property(value)
214
- if value.respond_to? :to_java
215
- jvalue = value.to_java
216
- elsif value.respond_to? :to_java_string
217
- jvalue = value.to_java_string
230
+ def encode_value(key, value)
231
+ if value.is_a? Set
232
+ encoded = value.map.with_index { |v, i| graph.encode_property(v) }
233
+ str = encoded.map { |v| "`#{ key.to_s }` == #{ v.inspect }" }.join " or "
234
+ parsed = JRuby.parse str
235
+ visitor = NodeVisitor.new(nil, {})
236
+ parsed.accept visitor
218
237
  else
219
- jvalue = value
238
+ value = graph.encode_property(value)
239
+ if value.respond_to? :to_java
240
+ value.to_java
241
+ elsif value.respond_to? :to_java_string
242
+ value.to_java_string
243
+ else
244
+ value
245
+ end
220
246
  end
221
247
  end
222
248
 
@@ -259,9 +285,13 @@ module Pacer
259
285
  end
260
286
 
261
287
  def check_index(index_options, idxs, k, v, index_value)
262
- if choose_best_index
288
+ if v.is_a? Set
289
+ # By default we assume that indices can't do OR type operations, so Set values are ruled out. If
290
+ # the index can do that (i.e. Neo4j's lucene engine), the adapter needs to do its own index selection.
291
+ false
292
+ elsif choose_best_index
263
293
  idxs.each do |idx|
264
- index_options << [idx.count(k, encode_value(v)), [idx, k, v], index_value]
294
+ index_options << [idx.count(k, encode_value(k, v)), [idx, k, v], index_value]
265
295
  end
266
296
  false
267
297
  else
@@ -284,7 +314,7 @@ module Pacer
284
314
 
285
315
  def encoded_properties
286
316
  @encoded_properties ||= properties.map do |k, v|
287
- [k, encode_value(v)]
317
+ [k, encode_value(k, v)]
288
318
  end
289
319
  end
290
320
 
@@ -1,6 +1,8 @@
1
1
  module Pacer
2
2
  module Filter
3
3
  module WhereFilter
4
+ # NOTE: the property filter also uses this to build { key: Set[v1, v2] }
5
+ # filters as or statements.
4
6
  class NodeVisitor
5
7
  import com.tinkerpop.pipes.filter.OrFilterPipe
6
8
  import com.tinkerpop.pipes.filter.FilterPipe
@@ -82,6 +82,13 @@ module Pacer
82
82
  blueprints_graph.stopTransaction TransactionalGraph::Conclusion::SUCCESS
83
83
  end
84
84
 
85
+ attr_reader :on_commit_block
86
+
87
+ def on_commit(&block)
88
+ return unless block
89
+ @on_commit_block = block
90
+ end
91
+
85
92
  private
86
93
 
87
94
  def threadlocal_graph_info
@@ -128,6 +135,7 @@ module Pacer
128
135
  end
129
136
  puts "transaction committed" if Pacer.verbose == :very
130
137
  blueprints_graph.stopTransaction TransactionalGraph::Conclusion::SUCCESS
138
+ on_commit_block.call if on_commit_block
131
139
  end
132
140
  rollback = ->(message = nil) do
133
141
  puts ["transaction rolled back", message].compact.join(': ') if Pacer.verbose == :very
@@ -153,6 +161,7 @@ module Pacer
153
161
  def mock_base_tx_finalizers
154
162
  commit = -> do
155
163
  puts "mock transaction committed" if Pacer.verbose == :very
164
+ on_commit_block.call if on_commit_block
156
165
  end
157
166
  rollback = ->(message = nil) do
158
167
  puts ["mock transaction rolled back", message].compact.join(': ') if Pacer.verbose == :very
@@ -1,4 +1,6 @@
1
1
  module Pacer
2
+ import com.tinkerpop.blueprints.Parameter
3
+
2
4
  class PacerGraph
3
5
  include GraphTransactionsMixin
4
6
 
@@ -6,9 +8,9 @@ module Pacer
6
8
  include Pacer::Core::Graph::GraphRoute
7
9
  include Pacer::Core::Graph::GraphIndexRoute
8
10
 
9
- attr_reader :blueprints_graph, :encoder
11
+ attr_reader :blueprints_graph
10
12
 
11
- attr_accessor :base_vertex_wrapper, :base_edge_wrapper
13
+ attr_accessor :encoder, :base_vertex_wrapper, :base_edge_wrapper
12
14
 
13
15
  def initialize(encoder, open, shutdown = nil, graph_id = nil)
14
16
  self.base_vertex_wrapper = Pacer::Wrappers::VertexWrapper
@@ -52,10 +54,6 @@ module Pacer
52
54
  self
53
55
  end
54
56
 
55
- def copy_object
56
- self.class.new @encoder, @reopen, @shutdown, graph_id
57
- end
58
-
59
57
  def use_wrapper(klass)
60
58
  reopen = proc do
61
59
  klass.new unwrap_graph(@reopen.call)
@@ -88,18 +86,7 @@ module Pacer
88
86
  v = blueprints_graph.getVertex(id)
89
87
  rescue java.lang.RuntimeException
90
88
  end
91
- if v
92
- wrapper = modules.detect { |obj| obj.ancestors.include? Pacer::Wrappers::VertexWrapper }
93
- if wrapper
94
- v = wrapper.new graph, v
95
- modules.delete wrapper
96
- else
97
- v = base_vertex_wrapper.new graph, v
98
- end
99
- v.add_extensions modules
100
- else
101
- v
102
- end
89
+ wrap_element v, base_vertex_wrapper, Pacer::Wrappers::VertexWrapper, modules
103
90
  end
104
91
 
105
92
  # Get an edge by id.
@@ -115,15 +102,23 @@ module Pacer
115
102
  v = blueprints_graph.getEdge(id)
116
103
  rescue Java::JavaLang::RuntimeException
117
104
  end
105
+ wrap_element v, base_edge_wrapper, Pacer::Wrappers::EdgeWrapper, modules
106
+ end
107
+
108
+ def wrap_element(v, base, klass, modules)
118
109
  if v
119
- wrapper = modules.detect { |obj| obj.ancestors.include? Pacer::Wrappers::EdgeWrapper }
120
- if wrapper
121
- v = wrapper.new graph, v
122
- modules.delete wrapper
110
+ if modules
111
+ wrapper = modules.detect { |obj| obj.ancestors.include? klass }
112
+ if wrapper
113
+ v = wrapper.new graph, v
114
+ modules.delete wrapper
115
+ else
116
+ v = base.new graph, v
117
+ end
118
+ v.add_extensions modules
123
119
  else
124
- v = base_edge_wrapper.new graph, v
120
+ base.new graph, v
125
121
  end
126
- v.add_extensions modules
127
122
  end
128
123
  end
129
124
 
@@ -371,10 +366,21 @@ module Pacer
371
366
  include Indices
372
367
 
373
368
  module KeyIndices
374
- def create_key_index(name, type)
369
+ def create_key_index(name, type = :vertex, opts = {})
370
+ params = build_key_index_parameters_from opts
375
371
  if features.supportsKeyIndices
376
372
  if element_type(type) == :vertex and features.supportsVertexKeyIndex
377
- blueprints_graph.createKeyIndex name.to_s, index_class(:vertex)
373
+ blueprints_graph.createKeyIndex name.to_s, index_class(:vertex), *params
374
+ elsif element_type(type) == :edge and features.supportsEdgeKeyIndex
375
+ blueprints_graph.createKeyIndex name.to_s, index_class(:edge), *params
376
+ end
377
+ end
378
+ end
379
+
380
+ def drop_key_index(name, type = :vertex)
381
+ if features.supportsKeyIndices
382
+ if element_type(type) == :vertex and features.supportsVertexKeyIndex
383
+ blueprints_graph.dropKeyIndex name.to_s, index_class(:vertex)
378
384
  elsif element_type(type) == :edge and features.supportsEdgeKeyIndex
379
385
  blueprints_graph.createKeyIndex name.to_s, index_class(:edge)
380
386
  end
@@ -413,7 +419,14 @@ module Pacer
413
419
  fail ClientError, "The key #{ key } is not indexed"
414
420
  end
415
421
  end
422
+
423
+ def build_key_index_parameters_from(option_hash)
424
+ option_hash.each_with_object([]) do |(key, value), params|
425
+ params << Pacer::Parameter.new(key, value)
426
+ end
427
+ end
416
428
  end
429
+
417
430
  include KeyIndices
418
431
 
419
432
  module ElementType
@@ -1,6 +1,7 @@
1
1
  module Pacer
2
2
  class SimpleEncoder
3
3
  JBoolean = java.lang.Boolean
4
+ JDate = java.util.Date
4
5
  JFalse = false.to_java
5
6
 
6
7
  def self.encode_property(value)
@@ -17,6 +18,8 @@ module Pacer
17
18
  def self.decode_property(value)
18
19
  if value.is_a? JBoolean and value == JFalse
19
20
  false
21
+ elsif value.is_a? JDate
22
+ Time.at value.getTime() / 1000.0
20
23
  else
21
24
  value
22
25
  end
@@ -70,6 +70,7 @@ require 'pacer/visitors/section'
70
70
  require 'pacer/filter/collection_filter'
71
71
  require 'pacer/filter/empty_filter'
72
72
  require 'pacer/filter/future_filter'
73
+ require 'pacer/filter/where_filter'
73
74
  require 'pacer/filter/property_filter'
74
75
  require 'pacer/filter/range_filter'
75
76
  require 'pacer/filter/uniq_filter'
@@ -77,7 +78,6 @@ require 'pacer/filter/index_filter'
77
78
  require 'pacer/filter/loop_filter'
78
79
  require 'pacer/filter/block_filter'
79
80
  require 'pacer/filter/object_filter'
80
- require 'pacer/filter/where_filter'
81
81
  require 'pacer/filter/random_filter'
82
82
 
83
83
  require 'pacer/transform/cap'
@@ -3,7 +3,7 @@ module Pacer
3
3
  module Pipes
4
4
  # TODO: move pipe imports to the modules that actually use them.
5
5
  import com.tinkerpop.pipes.AbstractPipe
6
- import com.tinkerpop.pipes.transform.IdentityPipe
6
+ import com.tinkerpop.pipes.IdentityPipe
7
7
  import com.tinkerpop.pipes.util.Pipeline
8
8
  import com.tinkerpop.pipes.util.PipeHelper
9
9
 
@@ -2,7 +2,11 @@ module Pacer
2
2
  module Routes
3
3
  module RouteOperations
4
4
  def sort_section(section = nil, &block)
5
- chain_route transform: :sort_section, block: block, section: section
5
+ chain_route transform: :sort_section, sort_by_block: block, section: section
6
+ end
7
+
8
+ def custom_sort_section(section = nil, &block)
9
+ chain_route transform: :sort_section, custom_sort_block: block, section: section
6
10
  end
7
11
  end
8
12
  end
@@ -15,26 +19,32 @@ module Pacer
15
19
  # section_visitor
16
20
  include Pacer::Visitors::VisitsSection
17
21
 
18
- attr_accessor :block
22
+ attr_accessor :sort_by_block
23
+ attr_accessor :custom_sort_block
19
24
 
20
25
  protected
21
26
 
22
27
  def attach_pipe(end_pipe)
23
- pf = Pacer::Wrappers::WrappingPipeFunction.new self, block if block
24
- pipe = SortSectionPipe.new(self, section_visitor, pf)
28
+ if custom_sort_block
29
+ wrapper = Pacer::Wrappers::WrapperSelector.build graph, element_type, extensions
30
+ pipe = CustomSortPipe.new(self, section_visitor, custom_sort_block, graph, wrapper)
31
+ else # sort_by_block
32
+ pf = Pacer::Wrappers::WrappingPipeFunction.new self, sort_by_block if sort_by_block
33
+ pipe = SortBySectionPipe.new(self, section_visitor, pf)
34
+ end
25
35
  pipe.setStarts end_pipe if end_pipe
26
36
  pipe
27
37
  end
28
38
 
29
-
30
- class SortSectionPipe < Pacer::Pipes::RubyPipe
31
- attr_reader :pf_1, :pf_2, :to_sort, :to_emit, :section
39
+ class SortBySectionPipe < Pacer::Pipes::RubyPipe
40
+ attr_reader :pf_1, :pf_2, :to_sort, :to_emit, :section, :route
32
41
  attr_reader :getPathToHere
33
42
 
34
43
  def initialize(route, section, pipe_function)
35
44
  super()
36
45
  @to_emit = []
37
46
  @section = section
47
+ @route = route
38
48
  @to_sort = []
39
49
  @paths = []
40
50
  if section
@@ -105,6 +115,30 @@ module Pacer
105
115
  end
106
116
  end
107
117
  end
118
+
119
+ class CustomSortPipe < SortBySectionPipe
120
+ attr_reader :sort_block
121
+
122
+ def initialize(route, section, sort_block, graph, wrapper)
123
+ super route, section, nil
124
+ @sort_block = sort_block
125
+ @graph = graph
126
+ @wrapper = wrapper
127
+ end
128
+
129
+ def after_element
130
+ if to_sort.any?
131
+ to_sort.map! { |e| [ @wrapper.new(@graph, e.first), e.last ] }
132
+ sorted = to_sort.sort { |a, b| @sort_block.call a.first, b.first }
133
+ if route.element_type == :vertex || route.element_type == :edge
134
+ to_emit.concat sorted.map { |e| [ e.first.element, e.last ] }
135
+ else
136
+ to_emit.concat sorted
137
+ end
138
+ @to_sort.clear
139
+ end
140
+ end
141
+ end
108
142
  end
109
143
  end
110
144
  end
@@ -1,14 +1,14 @@
1
1
  module Pacer
2
2
  unless const_defined? :VERSION
3
- VERSION = "1.2.0"
3
+ VERSION = "1.3.1"
4
4
 
5
5
  JAR = "pacer-#{ VERSION }-standalone.jar"
6
6
  JAR_PATH = "lib/#{ JAR }"
7
7
 
8
8
  START_TIME = Time.now
9
9
 
10
- BLUEPRINTS_VERSION = "2.2.0"
11
- PIPES_VERSION = "2.2.0"
12
- GREMLIN_VERSION = "2.2.0"
10
+ BLUEPRINTS_VERSION = "2.3.0"
11
+ PIPES_VERSION = "2.3.0"
12
+ GREMLIN_VERSION = "2.3.0"
13
13
  end
14
14
  end
@@ -119,6 +119,19 @@ module Pacer::Wrappers
119
119
  graph.remove_edge element
120
120
  end
121
121
 
122
+ # Creates a new edge between the same elements with the same
123
+ # properties, but in the opposite direction and optionally with a
124
+ # new label. Attempts to reuse the edge id.
125
+ def reverse!(opts = {})
126
+ iv = out_vertex
127
+ ov = in_vertex
128
+ id = element_id if opts[:reuse_id]
129
+ new_label = opts.fetch(:label, label)
130
+ props = properties
131
+ delete!
132
+ graph.create_edge id, ov, iv, new_label, props
133
+ end
134
+
122
135
  # Clones this edge into the target graph.
123
136
  #
124
137
  # This differs from the {#copy_into} in that it tries to set
@@ -113,12 +113,12 @@ module Pacer::Wrappers
113
113
  value = graph.encode_property(value)
114
114
  key = key.to_s
115
115
  if value
116
- if value != element.getProperty(key)
117
- element.setProperty(key, value)
118
- end
116
+ element.setProperty(key, value)
119
117
  else
120
- element.removeProperty(key) if element.getPropertyKeys.include? key
118
+ element.removeProperty(key)
121
119
  end
120
+ rescue Exception => e
121
+ throw Pacer::ClientError.new "Unable to serialize #{ key }: #{ value.class }"
122
122
  end
123
123
 
124
124
  # Specialize result to return self for elements.
@@ -40,7 +40,16 @@ module Pacer::Wrappers
40
40
  if element.is_a? ElementWrapper
41
41
  element = element.element
42
42
  end
43
+
43
44
  index.put key.to_s, value, element
44
45
  end
46
+
47
+ def remove(key, value, element)
48
+ if element.is_a? ElementWrapper
49
+ element = element.element
50
+ end
51
+
52
+ index.remove key.to_s, value, element
53
+ end
45
54
  end
46
55
  end
data/pom.xml CHANGED
@@ -7,10 +7,10 @@
7
7
  <artifactId>pacer</artifactId>
8
8
  <!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
9
9
  <properties>
10
- <blueprints.version>2.2.0</blueprints.version>
11
- <gem.version>1.2.0</gem.version>
12
- <pipes.version>2.2.0</pipes.version>
13
- <gremlin.version>2.2.0</gremlin.version>
10
+ <blueprints.version>2.3.0</blueprints.version>
11
+ <gem.version>1.3.1</gem.version>
12
+ <pipes.version>2.3.0</pipes.version>
13
+ <gremlin.version>2.3.0</gremlin.version>
14
14
  </properties>
15
15
  <!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
16
16
  <version>${gem.version}</version>
@@ -39,7 +39,7 @@ module NeoSpec
39
39
 
40
40
  # sanity checks
41
41
  it { should be_a Pacer::Filter::LuceneFilter }
42
- its(:query) { should == 'type:person' }
42
+ its(:query) { should == 'type:"person"' }
43
43
  its(:count) { should == 2 }
44
44
 
45
45
  its(:wrapper) { should == Person }
@@ -36,6 +36,27 @@ module Pacer::Filter::PropertyFilter
36
36
  its(:properties) { should == [ %w[ name Darrick ], %w[ nickname pangloss ] ] }
37
37
  end
38
38
 
39
+ context 'With a Set of properties' do
40
+ let(:filters) { Pacer::Route.send filter_method, [nickname: Set['pangloss', 'someone']] }
41
+
42
+ before { subject.graph = graph }
43
+
44
+ its(:any?) { should be_true }
45
+ its(:extensions_only?) { should be_false }
46
+ its(:extensions) { should be_empty }
47
+ its(:route_modules) { should be_empty }
48
+ its(:wrapper) { should be_nil }
49
+ its(:blocks) { should be_empty }
50
+ its(:properties) { should == [ ['nickname', Set['pangloss', 'someone'] ] ] }
51
+ its(:to_s) { should == 'nickname IN ("pangloss", "someone")' }
52
+ it 'should encode the Set property as an Or pipe' do
53
+ props = subject.send :encoded_properties
54
+ pipe = props.assoc('nickname').last
55
+ pipe.should be_a Pacer::Filter::WhereFilter::NodeVisitor::Pipe
56
+ pipe.build.should be_a Java::ComTinkerpopPipesFilter::OrFilterPipe
57
+ end
58
+ end
59
+
39
60
  context 'with extensions' do
40
61
  let(:filters) { Pacer::Route.send filter_method, [TP::Person, name: 'Darrick', nickname: 'pangloss'] }
41
62
 
@@ -34,6 +34,20 @@ Run.tg(:read_only) do
34
34
  end
35
35
  end
36
36
 
37
+ context 'v(:type => "person", :name => Set["pangloss", "someone"])' do
38
+ subject { graph.v(:type => 'person', :name => Set['pangloss', 'someone']) }
39
+ its(:to_a) { should == graph.v('type' => 'person', 'name' => 'pangloss').to_a }
40
+ its(:to_a) { should == graph.v.where('type = "person" and (name == "pangloss" or name == "someone")').to_a }
41
+ its(:count) { should == 1 }
42
+ its(:extensions) { should == [] }
43
+ it 'should have the correct type' do
44
+ subject[:type].first.should == 'person'
45
+ end
46
+ it 'should have the correct name' do
47
+ subject[:name].first.should == 'pangloss'
48
+ end
49
+ end
50
+
37
51
  context 'v(TP::Person)' do
38
52
  subject { graph.v(TP::Person) }
39
53
  its(:count) { should == 2 }
@@ -94,6 +94,11 @@ Run.all :read_write do
94
94
  describe '#create_vertex' do
95
95
  let(:use_id) { rand 1000000 }
96
96
 
97
+ before do
98
+ c = example.metadata[:graph_commit]
99
+ c.call if c
100
+ end
101
+
97
102
  context 'existing' do
98
103
  it 'should raise an exception' do
99
104
  unless graph.features.ignoresSuppliedIds
@@ -168,6 +173,11 @@ Run.all :read_write do
168
173
  let(:from) { graph.vertex v0.element_id }
169
174
  let(:to) { graph.vertex v1.element_id }
170
175
 
176
+ before do
177
+ c = example.metadata[:graph_commit]
178
+ c.call if c
179
+ end
180
+
171
181
  context 'existing' do
172
182
  it 'should raise an exception' do
173
183
  if not graph.features.ignoresSuppliedIds
@@ -341,6 +351,8 @@ Run.all :read_write do
341
351
  it 'should not load the data into a graph with conflicting vertex ids' do
342
352
  unless graph.features.ignoresSuppliedIds
343
353
  graph.create_vertex '0' unless graph.vertex '0'
354
+ c = example.metadata[:graph_commit]
355
+ c.call if c
344
356
  expect { Pacer::GraphML.import graph, 'spec/data/pacer.graphml' }.to raise_error(Pacer::ElementExists)
345
357
  end
346
358
  end
@@ -30,7 +30,7 @@ Run.all do
30
30
 
31
31
  its(:inspect) do
32
32
  should be_one_of "#<V-Index(name: \"gremlin\") -> V-Section -> :grem -> inE(:wrote)>",
33
- /#<V-Lucene\(name:gremlin\) ~ \d+ -> V-Section -> :grem -> inE\(:wrote\)>/,
33
+ /#<V-Lucene\(name:"gremlin"\) ~ \d+ -> V-Section -> :grem -> inE\(:wrote\)>/,
34
34
  "#<GraphV -> V-Property(name==\"gremlin\") -> V-Section -> :grem -> inE(:wrote)>"
35
35
  end
36
36
  its(:out_v) { should_not be_nil }
@@ -87,7 +87,7 @@ Run.all do
87
87
  use_simple_graph_data
88
88
  before { setup_data }
89
89
  subject { graph.v.element_ids.to_a }
90
- its(:sort) { should == [v0, v1].to_route(based_on: graph.v).element_ids.to_a.sort }
90
+ its(:to_set) { should == [v0, v1].to_route(based_on: graph.v).element_ids.to_set }
91
91
  end
92
92
  end
93
93
  end
@@ -107,7 +107,7 @@ Run.all(:read_only) do
107
107
  r = r.in_v
108
108
  r = r.is_not(:grem)
109
109
  r.inspect.should be_one_of "#<V-Index(name: \"gremlin\") -> V-Section -> :grem -> inE(:wrote) -> outV -> outE(:wrote) -> E-Property(&block) -> inV -> V-Property(&block)>",
110
- /#<V-Lucene\(name:gremlin\) ~ \d+ -> V-Section -> :grem -> inE\(:wrote\) -> outV -> outE\(:wrote\) -> E-Property\(&block\) -> inV -> V-Property\(&block\)>/,
110
+ /#<V-Lucene\(name:"gremlin"\) ~ \d+ -> V-Section -> :grem -> inE\(:wrote\) -> outV -> outE\(:wrote\) -> E-Property\(&block\) -> inV -> V-Property\(&block\)>/,
111
111
  "#<GraphV -> V-Property(name==\"gremlin\") -> V-Section -> :grem -> inE(:wrote) -> outV -> outE(:wrote) -> E-Property(&block) -> inV -> V-Property(&block)>"
112
112
  end
113
113
  end
@@ -5,6 +5,35 @@ Run.tg :read_only do
5
5
 
6
6
  let(:unsorted) { graph.v.out.out }
7
7
 
8
+ describe 'sort by custom sort' do
9
+ let(:by_custom) do
10
+ graph.v.section(:x).out.out.sort_section(:x) { |a, b| a[:name] <=> b[:name] }
11
+ end
12
+
13
+ it 'should have the same elements' do
14
+ by_custom.group_count.should == unsorted.group_count
15
+ end
16
+
17
+ it 'should have 3 elements in the path' do
18
+ by_custom.paths.each do |path|
19
+ path.length.should == 3
20
+ end
21
+ end
22
+
23
+ it 'should put groups into the correct order' do
24
+ # depends on the order of graph.v(type: 'project') ...
25
+ route = graph.v(type: 'project').section(:proj).out[:name].custom_sort_section(:proj) { |a, b| a <=> b }
26
+ route.to_a.should == %w[
27
+ blueprints
28
+ blueprints
29
+ gremlin
30
+ pipes
31
+ blueprints
32
+ pipes
33
+ ]
34
+ end
35
+ end
36
+
8
37
  describe 'sort by name' do
9
38
  let(:by_name) do
10
39
  graph.v.section(:x).out.out.sort_section(:x) { |v| v[:name] }
@@ -100,6 +100,52 @@ describe Pacer::Wrappers::EdgeWrapper do
100
100
  end
101
101
  end
102
102
 
103
+ describe '#reverse!' do
104
+ it 'should remove the old element' do
105
+ id = e0.element_id
106
+ e0.reverse!
107
+ c = example.metadata[:graph_commit]
108
+ c.call if c
109
+ graph.edge(id).should be_nil
110
+ end
111
+
112
+ it 'should create a new element with the same label' do
113
+ label = e0.label
114
+ new_e = e0.reverse!
115
+ new_e.label.should == label
116
+ end
117
+
118
+ it 'should not have the same element_id' do
119
+ id = e0.element_id
120
+ new_e = e0.reverse!
121
+ new_e.element_id.should_not == id
122
+ end
123
+
124
+ it 'should reverse the direction' do
125
+ iv = e0.in_vertex
126
+ ov = e0.out_vertex
127
+ new_e = e0.reverse!
128
+ new_e.in_vertex.should == ov
129
+ new_e.out_vertex.should == iv
130
+ end
131
+
132
+ it 'should change the label' do
133
+ new_e = e0.reverse! label: 'hello!!'
134
+ new_e.label.should == 'hello!!'
135
+ end
136
+
137
+ it 'should reuse the element id' do
138
+ unless graph.features.ignoresSuppliedIds
139
+ e0
140
+ c = example.metadata[:graph_commit]
141
+ c.call if c
142
+ id = e0.element_id
143
+ new_e = e0.reverse! reuse_id: true
144
+ new_e.element_id.should == id.to_s
145
+ end
146
+ end
147
+ end
148
+
103
149
  contexts(
104
150
  'into new tg' => proc {
105
151
  let(:dest) { Pacer.tg }
@@ -115,7 +161,12 @@ describe Pacer::Wrappers::EdgeWrapper do
115
161
  }) do
116
162
  describe '#clone_into' do
117
163
  context 'including vertices' do
118
- subject { e0.clone_into(dest, :create_vertices => true) }
164
+ subject do
165
+ e0
166
+ c = example.metadata[:graph_commit]
167
+ c.call if c
168
+ e0.clone_into(dest, :create_vertices => true)
169
+ end
119
170
 
120
171
  its('element_id.to_s') { should == e0.element_id.to_s unless graph.features.ignoresSuppliedIds }
121
172
  its(:label) { should == 'links' }
@@ -132,6 +183,9 @@ describe Pacer::Wrappers::EdgeWrapper do
132
183
 
133
184
  context 'existing' do
134
185
  before do
186
+ v0; v1; e0
187
+ c = example.metadata[:graph_commit]
188
+ c.call if c
135
189
  v0.clone_into(dest)
136
190
  v1.clone_into(dest)
137
191
  end
@@ -146,7 +200,16 @@ describe Pacer::Wrappers::EdgeWrapper do
146
200
  end
147
201
 
148
202
  describe '#copy_into' do
149
- subject { v0.clone_into(dest); v1.clone_into(dest); e0.copy_into(dest) }
203
+ before do
204
+ v0; v1; e0
205
+ c = example.metadata[:graph_commit]
206
+ c.call if c
207
+ end
208
+ subject do
209
+ v0.clone_into(dest)
210
+ v1.clone_into(dest)
211
+ e0.copy_into(dest)
212
+ end
150
213
  its(:label) { should == 'links' }
151
214
  its(:graph) { should equal(dest) }
152
215
  its('in_vertex.properties') { should == e0.in_vertex.properties }
@@ -195,13 +195,13 @@ shared_examples_for Pacer::Wrappers::VertexWrapper do
195
195
  subject { v0 }
196
196
  its(:graph) { should equal(graph) }
197
197
  its(:display_name) { should be_nil }
198
- its(:inspect) { should =~ /#<[VM]\[#{v0.element_id}\]>/ }
198
+ its(:inspect) { should =~ /#<[VM]\[#{Regexp.quote v0.element_id.to_s }\]>/ }
199
199
  context 'with label proc' do
200
200
  before do
201
201
  graph.vertex_name = proc { |e| "some name" }
202
202
  end
203
203
  its(:display_name) { should == "some name" }
204
- its(:inspect) { should =~ /#<[VM]\[#{ v0.element_id }\] some name>/ }
204
+ its(:inspect) { should =~ /#<[VM]\[#{ Regexp.quote v0.element_id.to_s }\] some name>/ }
205
205
  end
206
206
  it { should_not == v1 }
207
207
  it { should == v0 }
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pacer
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.2.0
4
+ version: 1.3.1
6
5
  platform: java
7
6
  authors:
8
7
  - Darrick Wiebe
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-04 00:00:00.000000000 Z
11
+ date: 2013-07-04 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: Pacer defines routes through a graph and then traverses them very quickly.
15
14
  email: darrick@innatesoftware.com
@@ -218,39 +217,30 @@ files:
218
217
  - spec/support/use_transactions.rb
219
218
  - spec/tackle/simple_mixin.rb
220
219
  - spec/tackle/tinkerpop_graph_mixins.rb
221
- - lib/pacer-1.2.0-standalone.jar
220
+ - lib/pacer-1.3.1-standalone.jar
222
221
  homepage: http://github.com/pangloss/pacer
223
222
  licenses:
224
223
  - MIT
224
+ metadata: {}
225
225
  post_install_message:
226
226
  rdoc_options: []
227
227
  require_paths:
228
228
  - lib
229
229
  required_ruby_version: !ruby/object:Gem::Requirement
230
230
  requirements:
231
- - - ! '>='
231
+ - - '>='
232
232
  - !ruby/object:Gem::Version
233
- segments:
234
- - 0
235
- hash: 2
236
- version: !binary |-
237
- MA==
238
- none: false
233
+ version: '0'
239
234
  required_rubygems_version: !ruby/object:Gem::Requirement
240
235
  requirements:
241
- - - ! '>='
236
+ - - '>='
242
237
  - !ruby/object:Gem::Version
243
- segments:
244
- - 0
245
- hash: 2
246
- version: !binary |-
247
- MA==
248
- none: false
238
+ version: '0'
249
239
  requirements: []
250
240
  rubyforge_project:
251
- rubygems_version: 1.8.24
241
+ rubygems_version: 2.0.3
252
242
  signing_key:
253
- specification_version: 3
243
+ specification_version: 4
254
244
  summary: A very efficient and easy to use graph traversal engine.
255
245
  test_files:
256
246
  - spec/data/grateful-dead.xml
@@ -307,3 +297,4 @@ test_files:
307
297
  - spec/support/use_transactions.rb
308
298
  - spec/tackle/simple_mixin.rb
309
299
  - spec/tackle/tinkerpop_graph_mixins.rb
300
+ has_rdoc: