pacer 0.9.1.1-java → 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/.autotest +4 -1
  2. data/.gitignore +4 -0
  3. data/.rspec +1 -1
  4. data/Gemfile-dev +33 -0
  5. data/Gemfile-release +4 -0
  6. data/README.md +27 -9
  7. data/Rakefile +26 -8
  8. data/bin/autotest +1 -1
  9. data/lib/pacer/blueprints/multi_graph.rb +7 -19
  10. data/lib/pacer/blueprints/ruby_graph.rb +77 -52
  11. data/lib/pacer/blueprints/tg.rb +6 -93
  12. data/lib/pacer/blueprints.rb +0 -1
  13. data/lib/pacer/core/graph/edges_route.rb +10 -12
  14. data/lib/pacer/core/graph/element_route.rb +14 -21
  15. data/lib/pacer/core/graph/graph_index_route.rb +12 -8
  16. data/lib/pacer/core/graph/graph_route.rb +2 -5
  17. data/lib/pacer/core/graph/mixed_route.rb +3 -5
  18. data/lib/pacer/core/graph/vertices_route.rb +26 -27
  19. data/lib/pacer/core/route.rb +35 -66
  20. data/lib/pacer/exceptions.rb +13 -6
  21. data/lib/pacer/extensions/block_filter_element.rb +0 -5
  22. data/lib/pacer/filter/collection_filter.rb +9 -2
  23. data/lib/pacer/filter/empty_filter.rb +12 -3
  24. data/lib/pacer/filter/future_filter.rb +5 -5
  25. data/lib/pacer/filter/loop_filter.rb +7 -13
  26. data/lib/pacer/filter/object_filter.rb +10 -16
  27. data/lib/pacer/filter/property_filter/filters.rb +134 -93
  28. data/lib/pacer/filter/property_filter.rb +22 -19
  29. data/lib/pacer/filter/where_filter/node_visitor.rb +47 -26
  30. data/lib/pacer/filter/where_filter.rb +24 -3
  31. data/lib/pacer/function_resolver.rb +7 -2
  32. data/lib/pacer/graph/graph_ml.rb +39 -0
  33. data/lib/pacer/graph/graph_transactions_mixin.rb +107 -175
  34. data/lib/pacer/graph/pacer_graph.rb +438 -0
  35. data/lib/pacer/graph/simple_encoder.rb +20 -0
  36. data/lib/pacer/graph/yaml_encoder.rb +81 -0
  37. data/lib/pacer/graph.rb +8 -10
  38. data/lib/pacer/pipe/blackbox_pipeline.rb +11 -4
  39. data/lib/pacer/pipe/block_filter_pipe.rb +5 -22
  40. data/lib/pacer/pipe/cross_product_transform_pipe.rb +5 -7
  41. data/lib/pacer/pipe/edges_pipe.rb +22 -0
  42. data/lib/pacer/pipe/enumerable_pipe.rb +3 -9
  43. data/lib/pacer/pipe/expandable_pipe.rb +2 -14
  44. data/lib/pacer/pipe/id_collection_filter_pipe.rb +2 -8
  45. data/lib/pacer/pipe/is_empty_pipe.rb +5 -12
  46. data/lib/pacer/pipe/is_unique_pipe.rb +3 -13
  47. data/lib/pacer/pipe/label_collection_filter_pipe.rb +1 -7
  48. data/lib/pacer/pipe/label_prefix_pipe.rb +0 -6
  49. data/lib/pacer/pipe/loop_pipe.rb +27 -25
  50. data/lib/pacer/pipe/never_pipe.rb +1 -1
  51. data/lib/pacer/pipe/path_wrapping_pipe.rb +40 -0
  52. data/lib/pacer/pipe/process_pipe.rb +2 -20
  53. data/lib/pacer/pipe/property_comparison_pipe.rb +0 -6
  54. data/lib/pacer/pipe/ruby_pipe.rb +10 -3
  55. data/lib/pacer/pipe/simple_visitor_pipe.rb +12 -11
  56. data/lib/pacer/pipe/stream_sort_pipe.rb +1 -7
  57. data/lib/pacer/pipe/stream_uniq_pipe.rb +0 -6
  58. data/lib/pacer/pipe/type_filter_pipe.rb +1 -7
  59. data/lib/pacer/pipe/unary_transform_pipe.rb +6 -8
  60. data/lib/pacer/pipe/unwrapping_pipe.rb +13 -0
  61. data/lib/pacer/pipe/vertices_pipe.rb +22 -0
  62. data/lib/pacer/pipe/visitor_pipe.rb +3 -7
  63. data/lib/pacer/pipe/wrapping_pipe.rb +37 -0
  64. data/lib/pacer/pipes.rb +17 -12
  65. data/lib/pacer/route/mixin/bulk_operations.rb +8 -9
  66. data/lib/pacer/route/mixin/route_operations.rb +17 -11
  67. data/lib/pacer/route/mixins.rb +0 -1
  68. data/lib/pacer/route.rb +198 -121
  69. data/lib/pacer/side_effect/aggregate.rb +22 -2
  70. data/lib/pacer/side_effect/as.rb +73 -0
  71. data/lib/pacer/side_effect/group_count.rb +0 -3
  72. data/lib/pacer/side_effect/is_unique.rb +7 -6
  73. data/lib/pacer/side_effect.rb +1 -1
  74. data/lib/pacer/support/enumerable.rb +14 -12
  75. data/lib/pacer/support/nil_class.rb +5 -0
  76. data/lib/pacer/support/proc.rb +2 -2
  77. data/lib/pacer/support.rb +1 -1
  78. data/lib/pacer/transform/cap.rb +1 -1
  79. data/lib/pacer/transform/has_count_cap.rb +1 -1
  80. data/lib/pacer/transform/join.rb +20 -16
  81. data/lib/pacer/transform/map.rb +6 -2
  82. data/lib/pacer/transform/path.rb +44 -20
  83. data/lib/pacer/transform/sort_section.rb +58 -51
  84. data/lib/pacer/utils/tsort.rb +7 -2
  85. data/lib/pacer/utils.rb +0 -1
  86. data/lib/pacer/version.rb +4 -3
  87. data/lib/pacer/visitors/section.rb +42 -0
  88. data/lib/pacer/visitors/visits_section.rb +32 -0
  89. data/lib/pacer/visitors.rb +7 -0
  90. data/lib/pacer/wrappers/edge_wrapper.rb +164 -11
  91. data/lib/pacer/wrappers/element_wrapper.rb +133 -8
  92. data/lib/pacer/wrappers/index_wrapper.rb +47 -0
  93. data/lib/pacer/wrappers/vertex_wrapper.rb +175 -12
  94. data/lib/pacer/wrappers/wrapper_selector.rb +40 -0
  95. data/lib/pacer/wrappers/wrapping_pipe_function.rb +90 -0
  96. data/lib/pacer/wrappers.rb +3 -1
  97. data/lib/pacer-1.0.0-standalone.jar +0 -0
  98. data/lib/pacer.rb +13 -47
  99. data/pacer.gemspec +0 -8
  100. data/pom.xml +10 -3
  101. data/spec/pacer/blueprints/dex_spec.rb +12 -26
  102. data/spec/pacer/blueprints/neo4j_spec.rb +14 -28
  103. data/spec/pacer/blueprints/tg_spec.rb +6 -54
  104. data/spec/pacer/core/graph/edges_route_spec.rb +1 -1
  105. data/spec/pacer/core/graph/element_route_spec.rb +2 -2
  106. data/spec/pacer/core/graph/graph_route_spec.rb +2 -2
  107. data/spec/pacer/core/graph/vertices_route_spec.rb +10 -3
  108. data/spec/pacer/core/route_spec.rb +35 -58
  109. data/spec/pacer/filter/empty_filter_spec.rb +5 -6
  110. data/spec/pacer/filter/future_filter_spec.rb +8 -8
  111. data/spec/pacer/filter/loop_filter_spec.rb +120 -6
  112. data/spec/pacer/filter/object_filter_spec.rb +15 -0
  113. data/spec/pacer/filter/property_filter/filters_spec.rb +169 -0
  114. data/spec/pacer/filter/property_filter_spec.rb +15 -12
  115. data/spec/pacer/filter/uniq_filter_spec.rb +1 -1
  116. data/spec/pacer/filter/where_filter_spec.rb +55 -7
  117. data/spec/pacer/graph/{graph_mixin_spec.rb → pacer_graph_spec.rb} +114 -185
  118. data/spec/pacer/route/mixin/base_spec.rb +36 -35
  119. data/spec/pacer/route/mixin/route_operations_spec.rb +4 -46
  120. data/spec/pacer/side_effect/as_spec.rb +34 -0
  121. data/spec/pacer/support/enumerable_spec.rb +6 -6
  122. data/spec/pacer/transform/join_spec.rb +7 -5
  123. data/spec/pacer/transform/map_spec.rb +55 -0
  124. data/spec/pacer/transform/path_spec.rb +30 -15
  125. data/spec/pacer/transform/process_spec.rb +42 -0
  126. data/spec/pacer/transform/sort_section_spec.rb +82 -0
  127. data/spec/pacer/wrapper/edge_wrapper_spec.rb +122 -2
  128. data/spec/pacer/wrapper/element_wrapper_spec.rb +289 -3
  129. data/spec/pacer/wrapper/vertex_wrapper_spec.rb +289 -2
  130. data/spec/spec_helper.rb +16 -7
  131. data/spec/support/graph_runner.rb +80 -29
  132. data/tags +1165 -0
  133. metadata +46 -107
  134. data/.rvmrc +0 -0
  135. data/lib/pacer/blueprints/extensions.rb +0 -77
  136. data/lib/pacer/graph/edge_mixin.rb +0 -127
  137. data/lib/pacer/graph/element_mixin.rb +0 -202
  138. data/lib/pacer/graph/graph_indices_mixin.rb +0 -93
  139. data/lib/pacer/graph/graph_mixin.rb +0 -361
  140. data/lib/pacer/graph/index_mixin.rb +0 -30
  141. data/lib/pacer/graph/vertex_mixin.rb +0 -119
  142. data/lib/pacer/pipe/map_pipe.rb +0 -36
  143. data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +0 -26
  144. data/lib/pacer/route/mixin/variable_route_module.rb +0 -26
  145. data/lib/pacer/side_effect/section.rb +0 -25
  146. data/lib/pacer/support/iterator_mixins.rb +0 -110
  147. data/lib/pacer/wrappers/new_element.rb +0 -106
  148. data/lib/pacer-0.9.1.1-standalone.jar +0 -0
  149. data/spec/pacer/graph/edge_mixin_spec.rb +0 -116
  150. data/spec/pacer/graph/element_mixin_spec.rb +0 -297
  151. data/spec/pacer/graph/index_mixin_spec.rb +0 -0
  152. data/spec/pacer/graph/vertex_mixin_spec.rb +0 -192
@@ -2,19 +2,20 @@ module Pacer::Wrappers
2
2
  class EdgeWrapper < ElementWrapper
3
3
  include Pacer::Edge
4
4
  include Pacer::Core::Graph::EdgesRoute
5
- include Pacer::ElementMixin
6
- include Pacer::EdgeMixin
7
5
 
8
6
  def_delegators :@element,
9
7
  :getId, :getLabel, :getPropertyKeys, :getProperty, :setProperty, :removeProperty,
10
- :getInVertex, :getOutVertex,
11
- :getRawEdge,
12
- :graph, :graph=, :<=>, :==
8
+ :getVertex,
9
+ :getRawEdge
13
10
 
14
11
  class << self
15
12
  def wrapper_for(exts)
16
13
  @wrappers = {} unless defined? @wrappers
17
- @wrappers[exts.to_set] ||= build_edge_wrapper(exts)
14
+ if exts
15
+ @wrappers[exts.to_set] ||= build_edge_wrapper(exts)
16
+ else
17
+ fail Pacer::LogicError, "Extensions should not be nil"
18
+ end
18
19
  end
19
20
 
20
21
  def clear_cache
@@ -30,22 +31,174 @@ module Pacer::Wrappers
30
31
 
31
32
  # This method must be defined here rather than in the superclass in order
32
33
  # to correctly override the method in an included module
33
- def extensions
34
- self.class.extensions
34
+ attr_reader :element
35
+
36
+ def label
37
+ getLabel
38
+ end
39
+
40
+ # The incoming vertex for this edge.
41
+ # @return [Pacer::Wrappers::VertexWrapper]
42
+ def in_vertex(extensions = nil)
43
+ v = element.getVertex Pacer::Pipes::IN
44
+ if extensions.is_a? Enumerable
45
+ v = VertexWrapper.wrapper_for(extensions).new v
46
+ elsif extensions
47
+ v = VertexWrapper.wrapper_for([extensions]).new v
48
+ else
49
+ v = VertexWrapper.new v
50
+ end
51
+ v.graph = graph
52
+ v
53
+ end
54
+
55
+ # The outgoing vertex for this edge.
56
+ # @return [Pacer::Wrappers::VertexWrapper]
57
+ def out_vertex(extensions = nil)
58
+ v = element.getVertex Pacer::Pipes::OUT
59
+ if extensions.is_a? Enumerable
60
+ v = VertexWrapper.wrapper_for(extensions).new v
61
+ elsif extensions
62
+ v = VertexWrapper.wrapper_for([extensions]).new v
63
+ else
64
+ v = VertexWrapper.new v
65
+ end
66
+ v.graph = graph
67
+ v
35
68
  end
36
69
 
37
70
  # This method must be defined here rather than in the superclass in order
38
71
  # to correctly override the method in an included module
39
- def element
40
- @element
72
+ def extensions
73
+ self.class.extensions
41
74
  end
42
75
 
76
+ # Add extensions to this edge.
77
+ #
78
+ # If any extension has a Edge module within it, this edge will
79
+ # be extended with the extension's Edge module.
80
+ #
81
+ # @param [[extensions]] exts the extensions to add
82
+ # @return [Pacer::Wrappers::EdgeWrapper] this edge wrapped up and including
83
+ # the extensions
43
84
  def add_extensions(exts)
44
85
  if exts.any?
45
- self.class.wrap(element, extensions + exts.to_a)
86
+ e = self.class.wrap(element, extensions + exts.to_a)
87
+ e.graph = graph
88
+ e
46
89
  else
47
90
  self
48
91
  end
49
92
  end
93
+
94
+ # Returns the element with a new simple wrapper.
95
+ # @return [EdgeWrapper]
96
+ def no_extensions
97
+ EdgeWrapper.new element
98
+ end
99
+
100
+ # Returns a human-readable representation of the edge using the
101
+ # standard ruby console representation of an instantiated object.
102
+ # @return [String]
103
+ def inspect
104
+ "#<E[#{element_id}]:#{display_name}>"
105
+ end
106
+
107
+ # Returns the display name of the edge.
108
+ # @return [String]
109
+ def display_name
110
+ if graph and graph.edge_name
111
+ graph.edge_name.call self
112
+ else
113
+ "#{ out_vertex.element_id }-#{ getLabel }-#{ in_vertex.element_id }"
114
+ end
115
+ end
116
+
117
+ # Deletes the edge from its graph.
118
+ def delete!
119
+ graph.remove_edge element
120
+ end
121
+
122
+ # Clones this edge into the target graph.
123
+ #
124
+ # This differs from the {#copy_into} in that it tries to set
125
+ # the new element_id the same as the original element_id.
126
+ #
127
+ # @param [PacerGraph] target_graph
128
+ # @param [Hash] opts
129
+ # @option opts :create_vertices [true] Create the vertices
130
+ # associated to this edge if they don't already exist.
131
+ # @yield [e] Optional block yields the edge after it has been created.
132
+ # @return [Pacer::Wrappers::EdgeWrapper] the new edge
133
+ #
134
+ # @raise [StandardError] If this the associated vertices don't exist and :create_vertices is not set
135
+ def clone_into(target_graph, opts = {})
136
+ e_idx = target_graph.index("tmp-e-#{graph.graph_id}", :edge, :create => true)
137
+ e = target_graph.edge(element_id)
138
+ unless e
139
+ e = e_idx.first('id', element_id)
140
+ if e
141
+ e = EdgeWrapper.new(e)
142
+ e.graph = target_graph
143
+ end
144
+ end
145
+ unless e
146
+ v_idx = target_graph.index("tmp-v-#{graph.graph_id}", :vertex, :create => true)
147
+ iv = target_graph.vertex(in_vertex.element_id) || v_idx.first('id', in_vertex.element_id)
148
+ ov = target_graph.vertex(out_vertex.element_id) || v_idx.first('id', out_vertex.element_id)
149
+ if opts[:create_vertices]
150
+ iv ||= in_vertex.clone_into target_graph
151
+ ov ||= out_vertex.clone_into target_graph
152
+ end
153
+ if not iv or not ov
154
+ message = "Vertex not found for #{ self.inspect }: #{ iv.inspect } -> #{ ov.inspect }"
155
+ puts message if opts[:show_missing_vertices]
156
+ raise message unless opts[:ignore_missing_vertices]
157
+ return nil
158
+ end
159
+ e = target_graph.create_edge(element_id, iv, ov, label, properties)
160
+ e_idx.put('id', element_id, e)
161
+ yield e if block_given?
162
+ end
163
+ e
164
+ end
165
+
166
+ # Copies this edge into the target graph with the next available
167
+ # edge id.
168
+ #
169
+ # @param [PacerGraph] target_graph
170
+ # @yield [e] Optional block yields the edge after it has been created.
171
+ # @return [Pacer::Wrappers::EdgeWrapper] the new edge
172
+ #
173
+ # @raise [StandardError] If this the associated vertices don't exist
174
+ def copy_into(target_graph)
175
+ v_idx = target_graph.index("tmp-v-#{graph.graph_id}", :vertex, :create => true)
176
+ iv = v_idx.first('id', in_vertex.element_id) || target_graph.vertex(in_vertex.element_id)
177
+ ov = v_idx.first('id', out_vertex.element_id) || target_graph.vertex(out_vertex.element_id)
178
+
179
+ raise 'vertices not found' if not iv or not ov
180
+ e = target_graph.create_edge nil, iv, ov, label, properties
181
+ yield e if block_given?
182
+ e
183
+ end
184
+
185
+ # Test equality to another object.
186
+ #
187
+ # Elements are equal if they are the same element type and have the same id
188
+ # and the same graph, regardless of extensions/wrappers.
189
+ #
190
+ # If the graphdb instantiates multiple copies of the same element
191
+ # this method will return true when comparing them.
192
+ #
193
+ # If the other instance is an unwrapped edge, this will always return
194
+ # false because otherwise the == method would not be symetrical.
195
+ #
196
+ # @see #eql?
197
+ # @param other
198
+ def ==(other)
199
+ other.is_a? EdgeWrapper and
200
+ element_id == other.element_id and
201
+ graph == other.graph
202
+ end
50
203
  end
51
204
  end
@@ -3,16 +3,26 @@ module Pacer::Wrappers
3
3
  include Pacer::Element
4
4
  extend Forwardable
5
5
  include Comparable
6
+ include Pacer::Routes::RouteOperations
7
+ include Pacer::Core::Graph::ElementRoute
6
8
 
7
9
  class << self
8
10
  def wrap(element, exts)
9
- wrapper_for(exts).new(element.element)
11
+ if element.respond_to? :element
12
+ wrapper_for(exts).new(element.element)
13
+ else
14
+ wrapper_for(exts).new(element)
15
+ end
10
16
  end
11
17
 
12
18
  def extensions
13
19
  @extensions ||= []
14
20
  end
15
21
 
22
+ def add_extensions(exts)
23
+ wrapper_for(extensions + exts.to_a)
24
+ end
25
+
16
26
  def clear_cache
17
27
  Pacer.send :remove_const, :Wrap if Pacer.const_defined? :Wrap
18
28
  VertexWrapper.clear_cache
@@ -37,8 +47,19 @@ module Pacer::Wrappers
37
47
  sc_name = superclass.to_s.split(/::/).last
38
48
  exts = exts.uniq unless exts.is_a? Set
39
49
  classname = "#{sc_name}#{exts.map { |m| m.to_s }.join('')}".gsub(/::/, '_').gsub(/\W/, '')
40
- eval "module ::Pacer; module Wrap; class #{classname.to_s} < #{sc_name}; end; end; end"
41
- wrapper = Pacer::Wrap.const_get classname
50
+ begin
51
+ wrapper = Pacer::Wrap.const_get classname
52
+ rescue NameError
53
+ eval %{
54
+ module ::Pacer
55
+ module Wrap
56
+ class #{classname.to_s} < #{sc_name}
57
+ end
58
+ end
59
+ end
60
+ }
61
+ wrapper = Pacer::Wrap.const_get classname
62
+ end
42
63
  exts.each do |obj|
43
64
  if obj.is_a? Module or obj.is_a? Class
44
65
  mod_names.each do |mod_name|
@@ -53,21 +74,125 @@ module Pacer::Wrappers
53
74
  end
54
75
  end
55
76
 
77
+ # For internal use only.
78
+ #
79
+ # The graph the element belongs to.
80
+ #
81
+ # Used to help prevent objects from different graphs from being
82
+ # accidentally associated, as well as to get graph-specific data for
83
+ # the element.
84
+ #
85
+ # @return [PacerGraph]
86
+ attr_accessor :graph
87
+ attr_reader :element
88
+
56
89
  def initialize(element)
57
- @element = element
90
+ if element.is_a? ElementWrapper
91
+ @element = element.element
92
+ else
93
+ @element = element
94
+ end
58
95
  after_initialize
59
96
  end
60
97
 
98
+ def hash
99
+ element.hash
100
+ end
101
+
102
+ # Convenience method to retrieve a property by name.
103
+ #
104
+ # @param [#to_s] key the property name
105
+ # @return [Object]
106
+ def [](key)
107
+ if key.is_a? Array
108
+ key.map { |k| self[k] }
109
+ else
110
+ value = element.getProperty(key.to_s)
111
+ graph.decode_property(value)
112
+ end
113
+ end
114
+
115
+ # Convenience method to set a property by name to the given value.
116
+ # @param [#to_s] key the property name
117
+ # @param [Object] value the value to set the property to
118
+ def []=(key, value)
119
+ value = graph.encode_property(value)
120
+ key = key.to_s
121
+ if value
122
+ if value != element.getProperty(key)
123
+ element.setProperty(key, value)
124
+ end
125
+ else
126
+ element.removeProperty(key) if element.getPropertyKeys.include? key
127
+ end
128
+ end
129
+
130
+ # Specialize result to return self for elements.
131
+ # @return [ElementWrapper] self
132
+ def result(name = nil)
133
+ self
134
+ end
135
+
136
+ # Query whether the current node belongs to the given graph.
137
+ #
138
+ # @param [Object] g the object to compare to {#graph}
139
+ def from_graph?(g)
140
+ g.blueprints_graph.equal? graph.blueprints_graph
141
+ end
142
+
143
+ # Returns a hash of property values by name.
144
+ #
145
+ # @return [Hash]
146
+ def properties
147
+ element.getPropertyKeys.inject({}) { |h, name| h[name] = element.getProperty(name); h }
148
+ end
149
+
150
+ # Replace the element's properties with the given hash
151
+ #
152
+ # @param [Hash] props the element's new properties
153
+ def properties=(props)
154
+ (element.getPropertyKeys - props.keys.collect { |k| k.to_s }).each do |key|
155
+ element.removeProperty key
156
+ end
157
+ props.each do |key, value|
158
+ self[key] = value
159
+ end
160
+ end
161
+
162
+ def property_keys
163
+ getPropertyKeys
164
+ end
165
+
166
+ # The id of the current element
167
+ # @return [Object] element id (type varies by graph implementation.
61
168
  def element_id
62
- @element.get_id
169
+ element.getId
63
170
  end
64
171
 
65
- def hash
66
- @element.hash
172
+ # Sort objects semi arbitrarily based on {#display_name}.
173
+ # @param other
174
+ #
175
+ # @return [Fixnum]
176
+ def <=>(other)
177
+ display_name.to_s <=> other.display_name.to_s
67
178
  end
68
179
 
180
+ # Test object equality of the element instance.
181
+ #
182
+ # Wrappers/extensions (if any) are ignored, the underlying element
183
+ # only is compared
184
+ #
185
+ # If the graphdb instantiates multiple copies of the same element
186
+ # this method will return false when comparing them.
187
+ #
188
+ # @see #==
189
+ # @param other
69
190
  def eql?(other)
70
- @element.eql?(other)
191
+ if other.respond_to? :element_id
192
+ other.graph == graph and other.element_id == element_id
193
+ else
194
+ element.equals other
195
+ end
71
196
  end
72
197
 
73
198
  protected
@@ -0,0 +1,47 @@
1
+ module Pacer::Wrappers
2
+ class IndexWrapper
3
+ attr_reader :index, :graph, :element_type
4
+
5
+ def initialize(graph, index, element_type)
6
+ @index = index
7
+ @graph = graph
8
+ @element_type = element_type
9
+ end
10
+
11
+ def name
12
+ index.index_name
13
+ end
14
+
15
+ def wrapper
16
+ WrapperSelector.build element_type
17
+ end
18
+
19
+ def first(key, value, extensions = nil)
20
+ e = index.get(key, value).first
21
+ if e
22
+ e = wrapper.new e
23
+ e = e.add_extensions extensions if extensions
24
+ e.graph = graph
25
+ end
26
+ e
27
+ end
28
+
29
+ def all(key, value, extensions = nil)
30
+ iter = index.get(key, value)
31
+ if graph or extensions
32
+ pipe = Pacer::Pipes::WrappingPipe.new graph, element_type, extensions
33
+ pipe.setStarts iter.iterator
34
+ pipe
35
+ else
36
+ iter
37
+ end
38
+ end
39
+
40
+ def put(key, value, element)
41
+ if element.is_a? ElementWrapper
42
+ element = element.element
43
+ end
44
+ index.put key, value, element
45
+ end
46
+ end
47
+ end
@@ -2,19 +2,20 @@ module Pacer::Wrappers
2
2
  class VertexWrapper < ElementWrapper
3
3
  include Pacer::Vertex
4
4
  include Pacer::Core::Graph::VerticesRoute
5
- include Pacer::ElementMixin
6
- include Pacer::VertexMixin
7
5
 
8
6
  def_delegators :@element,
9
7
  :getId, :getPropertyKeys, :getProperty, :setProperty, :removeProperty,
10
- :getOutEdges, :getInEdges,
11
- :getRawVertex,
12
- :graph, :graph=, :<=>, :==
8
+ :getEdges,
9
+ :getRawVertex
13
10
 
14
11
  class << self
15
12
  def wrapper_for(exts)
16
13
  @wrappers = {} unless defined? @wrappers
17
- @wrappers[exts.to_set] ||= build_vertex_wrapper(exts)
14
+ if exts
15
+ @wrappers[exts.to_set] ||= build_vertex_wrapper(exts)
16
+ else
17
+ fail Pacer::LogicError, "Extensions should not be nil"
18
+ end
18
19
  end
19
20
 
20
21
  def clear_cache
@@ -30,22 +31,184 @@ module Pacer::Wrappers
30
31
 
31
32
  # This method must be defined here rather than in the superclass in order
32
33
  # to correctly override the method in an included module
33
- def extensions
34
- self.class.extensions
35
- end
34
+ attr_reader :element
36
35
 
37
36
  # This method must be defined here rather than in the superclass in order
38
37
  # to correctly override the method in an included module
39
- def element
40
- @element
38
+ def extensions
39
+ self.class.extensions
41
40
  end
42
41
 
42
+ # Add extensions to this vertex.
43
+ #
44
+ # If any extension has a Vertex module within it, this vertex will
45
+ # be extended with the extension's Vertex module.
46
+ #
47
+ # @param [[extensions]] exts the extensions to add
48
+ # @return [Pacer::EdgeWrapper] this vertex wrapped up and including
49
+ # the extensions
43
50
  def add_extensions(exts)
44
51
  if exts.any?
45
- self.class.wrap(element, extensions + exts.to_a)
52
+ e = self.class.wrap(element, extensions + exts.to_a)
53
+ e.graph = graph
54
+ e
46
55
  else
47
56
  self
48
57
  end
49
58
  end
59
+
60
+ # Returns the element with a new simple wrapper.
61
+ # @return [VertexWrapper]
62
+ def no_extensions
63
+ e = VertexWrapper.new element
64
+ e.graph = graph
65
+ e
66
+ end
67
+
68
+ # Checks that the given extensions can be applied to the vertex. If
69
+ # they can then yield the vertex correctly extended or return the extended
70
+ # vertex. If not then do not yield and return nil.
71
+ #
72
+ # @param [extensions] exts extensions to add if possible
73
+ # @yield [v] Optional block yields the vertex with the extensions added.
74
+ # @return nil or the result of the block or the extended vertex
75
+ def as(*exts)
76
+ if as?(*exts)
77
+ exts_to_add = extensions_missing(exts)
78
+ extended = exts_to_add.empty? ? self : add_extensions(exts_to_add)
79
+ if block_given?
80
+ yield extended
81
+ else
82
+ extended
83
+ end
84
+ end
85
+ end
86
+
87
+ def only_as(*exts)
88
+ if as?(*exts)
89
+ extended = exts.empty? ? no_extensions : no_extensions.add_extensions(exts)
90
+ if block_given?
91
+ yield extended
92
+ else
93
+ extended
94
+ end
95
+ end
96
+ end
97
+
98
+ def as?(*exts)
99
+ has_exts = extensions_missing(exts).all? do |ext|
100
+ if ext.respond_to? :route_conditions
101
+ ext.route_conditions.all? do |k, v|
102
+ self[k] == v
103
+ end
104
+ else
105
+ true
106
+ end
107
+ end
108
+ end
109
+
110
+ # Returns a human-readable representation of the vertex using the
111
+ # standard ruby console representation of an instantiated object.
112
+ # @return [String]
113
+ def inspect
114
+ "#<#{ ["V[#{element_id}]", display_name].compact.join(' ') }>"
115
+ end
116
+
117
+ # Returns the display name of the vertex.
118
+ # @return [String]
119
+ def display_name
120
+ graph.vertex_name.call self if graph and graph.vertex_name
121
+ end
122
+
123
+ # Deletes the vertex from its graph along with all related edges.
124
+ def delete!
125
+ graph.remove_vertex element
126
+ end
127
+
128
+ # Copies including the vertex id unless a vertex with that id
129
+ # already exists.
130
+ # @param [PacerGraph] target_graph
131
+ # @param opts for compatibility with {Pacer::Wrappers::EdgeWrapper#clone_into}
132
+ # @yield [v] Optional block yields the vertex after it has been created.
133
+ # @return [Pacer::Wrappers::VertexWrapper] the new vertex
134
+ def clone_into(target_graph, opts = nil)
135
+ v_idx = target_graph.index("tmp-v-#{graph.graph_id}", :vertex, :create => true)
136
+ v = target_graph.vertex(element_id) || v_idx.first('id', element_id)
137
+ unless v
138
+ v = target_graph.create_vertex element_id, properties
139
+ v_idx.put('id', element_id, v.element)
140
+ yield v if block_given?
141
+ end
142
+ v
143
+ end
144
+
145
+ # Make a new copy of the element with the next available vertex id.
146
+ #
147
+ # @param [PacerGraph] target_graph
148
+ # @yield [v] Optional block yields the vertex after it has been created.
149
+ # @return [Pacer::Wrappers::VertexWrapper] the new vertex
150
+ def copy_into(target_graph)
151
+ v = target_graph.create_vertex properties
152
+ yield v if block_given?
153
+ v
154
+ end
155
+
156
+ def out_edges(*labels_and_extensions)
157
+ get_edges_helper Pacer::Pipes::OUT, *labels_and_extensions
158
+ end
159
+
160
+ def in_edges(*labels_and_extensions)
161
+ get_edges_helper Pacer::Pipes::IN, *labels_and_extensions
162
+ end
163
+
164
+ def both_edges(*labels_and_extensions)
165
+ get_edges_helper Pacer::Pipes::BOTH, *labels_and_extensions
166
+ end
167
+
168
+ # Test equality to another object.
169
+ #
170
+ # Elements are equal if they are the same type and have the same id
171
+ # and the same graph, regardless of extensions.
172
+ #
173
+ # If the graphdb instantiates multiple copies of the same element
174
+ # this method will return true when comparing them.
175
+ #
176
+ # If the other instance is an unwrapped vertex, this will always return
177
+ # false because otherwise the == method would not be symetrical.
178
+ #
179
+ # @see #eql?
180
+ # @param other
181
+ def ==(other)
182
+ other.is_a? VertexWrapper and
183
+ element_id == other.element_id and
184
+ graph == other.graph
185
+ end
186
+
187
+ protected
188
+
189
+ def get_edges_helper(direction, *labels_and_extensions)
190
+ labels, exts = split_labels_and_extensions(labels_and_extensions)
191
+ pipe = Pacer::Pipes::WrappingPipe.new graph, :edge, exts
192
+ pipe.setStarts element.getEdges(direction, *labels).iterator
193
+ pipe
194
+ end
195
+
196
+ def split_labels_and_extensions(mixed)
197
+ labels = Set[]
198
+ exts = []
199
+ mixed.each do |obj|
200
+ if obj.is_a? Symbol or obj.is_a? String
201
+ labels << obj
202
+ else
203
+ exts << obj
204
+ end
205
+ end
206
+ [labels, exts.uniq]
207
+ end
208
+
209
+ # Return the extensions this vertex is missing from the given array
210
+ def extensions_missing(exts)
211
+ Set.new(exts.flatten).difference extensions.to_set
212
+ end
50
213
  end
51
214
  end
@@ -0,0 +1,40 @@
1
+ module Pacer::Wrappers
2
+ class WrapperSelector
3
+ import com.tinkerpop.blueprints.Vertex
4
+ import com.tinkerpop.blueprints.Edge
5
+
6
+ def self.build(element_type = nil, extensions = [])
7
+ if element_type == :vertex
8
+ Pacer::Wrappers::VertexWrapper.wrapper_for extensions
9
+ elsif element_type == :edge
10
+ Pacer::Wrappers::EdgeWrapper.wrapper_for extensions
11
+ else
12
+ new extensions
13
+ end
14
+ end
15
+
16
+ attr_reader :extensions
17
+ attr_accessor :vertex_wrapper, :edge_wrapper
18
+
19
+ def initialize(extensions = [])
20
+ @extensions = extensions
21
+ end
22
+
23
+ def wrapper(element)
24
+ if element.is_a? Vertex
25
+ self.vertex_wrapper ||= Pacer::Wrappers::VertexWrapper.wrapper_for extensions
26
+ elsif element.is_a? Edge
27
+ self.edge_wrapper ||= Pacer::Wrappers::EdgeWrapper.wrapper_for extensions
28
+ end
29
+ end
30
+
31
+ def new(element)
32
+ w = wrapper(element)
33
+ if w
34
+ w.new element
35
+ else
36
+ element
37
+ end
38
+ end
39
+ end
40
+ end