pacer 1.2.0-java → 1.3.1-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: