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.
- data/.autotest +4 -1
- data/.gitignore +4 -0
- data/.rspec +1 -1
- data/Gemfile-dev +33 -0
- data/Gemfile-release +4 -0
- data/README.md +27 -9
- data/Rakefile +26 -8
- data/bin/autotest +1 -1
- data/lib/pacer/blueprints/multi_graph.rb +7 -19
- data/lib/pacer/blueprints/ruby_graph.rb +77 -52
- data/lib/pacer/blueprints/tg.rb +6 -93
- data/lib/pacer/blueprints.rb +0 -1
- data/lib/pacer/core/graph/edges_route.rb +10 -12
- data/lib/pacer/core/graph/element_route.rb +14 -21
- data/lib/pacer/core/graph/graph_index_route.rb +12 -8
- data/lib/pacer/core/graph/graph_route.rb +2 -5
- data/lib/pacer/core/graph/mixed_route.rb +3 -5
- data/lib/pacer/core/graph/vertices_route.rb +26 -27
- data/lib/pacer/core/route.rb +35 -66
- data/lib/pacer/exceptions.rb +13 -6
- data/lib/pacer/extensions/block_filter_element.rb +0 -5
- data/lib/pacer/filter/collection_filter.rb +9 -2
- data/lib/pacer/filter/empty_filter.rb +12 -3
- data/lib/pacer/filter/future_filter.rb +5 -5
- data/lib/pacer/filter/loop_filter.rb +7 -13
- data/lib/pacer/filter/object_filter.rb +10 -16
- data/lib/pacer/filter/property_filter/filters.rb +134 -93
- data/lib/pacer/filter/property_filter.rb +22 -19
- data/lib/pacer/filter/where_filter/node_visitor.rb +47 -26
- data/lib/pacer/filter/where_filter.rb +24 -3
- data/lib/pacer/function_resolver.rb +7 -2
- data/lib/pacer/graph/graph_ml.rb +39 -0
- data/lib/pacer/graph/graph_transactions_mixin.rb +107 -175
- data/lib/pacer/graph/pacer_graph.rb +438 -0
- data/lib/pacer/graph/simple_encoder.rb +20 -0
- data/lib/pacer/graph/yaml_encoder.rb +81 -0
- data/lib/pacer/graph.rb +8 -10
- data/lib/pacer/pipe/blackbox_pipeline.rb +11 -4
- data/lib/pacer/pipe/block_filter_pipe.rb +5 -22
- data/lib/pacer/pipe/cross_product_transform_pipe.rb +5 -7
- data/lib/pacer/pipe/edges_pipe.rb +22 -0
- data/lib/pacer/pipe/enumerable_pipe.rb +3 -9
- data/lib/pacer/pipe/expandable_pipe.rb +2 -14
- data/lib/pacer/pipe/id_collection_filter_pipe.rb +2 -8
- data/lib/pacer/pipe/is_empty_pipe.rb +5 -12
- data/lib/pacer/pipe/is_unique_pipe.rb +3 -13
- data/lib/pacer/pipe/label_collection_filter_pipe.rb +1 -7
- data/lib/pacer/pipe/label_prefix_pipe.rb +0 -6
- data/lib/pacer/pipe/loop_pipe.rb +27 -25
- data/lib/pacer/pipe/never_pipe.rb +1 -1
- data/lib/pacer/pipe/path_wrapping_pipe.rb +40 -0
- data/lib/pacer/pipe/process_pipe.rb +2 -20
- data/lib/pacer/pipe/property_comparison_pipe.rb +0 -6
- data/lib/pacer/pipe/ruby_pipe.rb +10 -3
- data/lib/pacer/pipe/simple_visitor_pipe.rb +12 -11
- data/lib/pacer/pipe/stream_sort_pipe.rb +1 -7
- data/lib/pacer/pipe/stream_uniq_pipe.rb +0 -6
- data/lib/pacer/pipe/type_filter_pipe.rb +1 -7
- data/lib/pacer/pipe/unary_transform_pipe.rb +6 -8
- data/lib/pacer/pipe/unwrapping_pipe.rb +13 -0
- data/lib/pacer/pipe/vertices_pipe.rb +22 -0
- data/lib/pacer/pipe/visitor_pipe.rb +3 -7
- data/lib/pacer/pipe/wrapping_pipe.rb +37 -0
- data/lib/pacer/pipes.rb +17 -12
- data/lib/pacer/route/mixin/bulk_operations.rb +8 -9
- data/lib/pacer/route/mixin/route_operations.rb +17 -11
- data/lib/pacer/route/mixins.rb +0 -1
- data/lib/pacer/route.rb +198 -121
- data/lib/pacer/side_effect/aggregate.rb +22 -2
- data/lib/pacer/side_effect/as.rb +73 -0
- data/lib/pacer/side_effect/group_count.rb +0 -3
- data/lib/pacer/side_effect/is_unique.rb +7 -6
- data/lib/pacer/side_effect.rb +1 -1
- data/lib/pacer/support/enumerable.rb +14 -12
- data/lib/pacer/support/nil_class.rb +5 -0
- data/lib/pacer/support/proc.rb +2 -2
- data/lib/pacer/support.rb +1 -1
- data/lib/pacer/transform/cap.rb +1 -1
- data/lib/pacer/transform/has_count_cap.rb +1 -1
- data/lib/pacer/transform/join.rb +20 -16
- data/lib/pacer/transform/map.rb +6 -2
- data/lib/pacer/transform/path.rb +44 -20
- data/lib/pacer/transform/sort_section.rb +58 -51
- data/lib/pacer/utils/tsort.rb +7 -2
- data/lib/pacer/utils.rb +0 -1
- data/lib/pacer/version.rb +4 -3
- data/lib/pacer/visitors/section.rb +42 -0
- data/lib/pacer/visitors/visits_section.rb +32 -0
- data/lib/pacer/visitors.rb +7 -0
- data/lib/pacer/wrappers/edge_wrapper.rb +164 -11
- data/lib/pacer/wrappers/element_wrapper.rb +133 -8
- data/lib/pacer/wrappers/index_wrapper.rb +47 -0
- data/lib/pacer/wrappers/vertex_wrapper.rb +175 -12
- data/lib/pacer/wrappers/wrapper_selector.rb +40 -0
- data/lib/pacer/wrappers/wrapping_pipe_function.rb +90 -0
- data/lib/pacer/wrappers.rb +3 -1
- data/lib/pacer-1.0.0-standalone.jar +0 -0
- data/lib/pacer.rb +13 -47
- data/pacer.gemspec +0 -8
- data/pom.xml +10 -3
- data/spec/pacer/blueprints/dex_spec.rb +12 -26
- data/spec/pacer/blueprints/neo4j_spec.rb +14 -28
- data/spec/pacer/blueprints/tg_spec.rb +6 -54
- data/spec/pacer/core/graph/edges_route_spec.rb +1 -1
- data/spec/pacer/core/graph/element_route_spec.rb +2 -2
- data/spec/pacer/core/graph/graph_route_spec.rb +2 -2
- data/spec/pacer/core/graph/vertices_route_spec.rb +10 -3
- data/spec/pacer/core/route_spec.rb +35 -58
- data/spec/pacer/filter/empty_filter_spec.rb +5 -6
- data/spec/pacer/filter/future_filter_spec.rb +8 -8
- data/spec/pacer/filter/loop_filter_spec.rb +120 -6
- data/spec/pacer/filter/object_filter_spec.rb +15 -0
- data/spec/pacer/filter/property_filter/filters_spec.rb +169 -0
- data/spec/pacer/filter/property_filter_spec.rb +15 -12
- data/spec/pacer/filter/uniq_filter_spec.rb +1 -1
- data/spec/pacer/filter/where_filter_spec.rb +55 -7
- data/spec/pacer/graph/{graph_mixin_spec.rb → pacer_graph_spec.rb} +114 -185
- data/spec/pacer/route/mixin/base_spec.rb +36 -35
- data/spec/pacer/route/mixin/route_operations_spec.rb +4 -46
- data/spec/pacer/side_effect/as_spec.rb +34 -0
- data/spec/pacer/support/enumerable_spec.rb +6 -6
- data/spec/pacer/transform/join_spec.rb +7 -5
- data/spec/pacer/transform/map_spec.rb +55 -0
- data/spec/pacer/transform/path_spec.rb +30 -15
- data/spec/pacer/transform/process_spec.rb +42 -0
- data/spec/pacer/transform/sort_section_spec.rb +82 -0
- data/spec/pacer/wrapper/edge_wrapper_spec.rb +122 -2
- data/spec/pacer/wrapper/element_wrapper_spec.rb +289 -3
- data/spec/pacer/wrapper/vertex_wrapper_spec.rb +289 -2
- data/spec/spec_helper.rb +16 -7
- data/spec/support/graph_runner.rb +80 -29
- data/tags +1165 -0
- metadata +46 -107
- data/.rvmrc +0 -0
- data/lib/pacer/blueprints/extensions.rb +0 -77
- data/lib/pacer/graph/edge_mixin.rb +0 -127
- data/lib/pacer/graph/element_mixin.rb +0 -202
- data/lib/pacer/graph/graph_indices_mixin.rb +0 -93
- data/lib/pacer/graph/graph_mixin.rb +0 -361
- data/lib/pacer/graph/index_mixin.rb +0 -30
- data/lib/pacer/graph/vertex_mixin.rb +0 -119
- data/lib/pacer/pipe/map_pipe.rb +0 -36
- data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +0 -26
- data/lib/pacer/route/mixin/variable_route_module.rb +0 -26
- data/lib/pacer/side_effect/section.rb +0 -25
- data/lib/pacer/support/iterator_mixins.rb +0 -110
- data/lib/pacer/wrappers/new_element.rb +0 -106
- data/lib/pacer-0.9.1.1-standalone.jar +0 -0
- data/spec/pacer/graph/edge_mixin_spec.rb +0 -116
- data/spec/pacer/graph/element_mixin_spec.rb +0 -297
- data/spec/pacer/graph/index_mixin_spec.rb +0 -0
- 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
|
-
:
|
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
|
-
|
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
|
-
|
34
|
-
|
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
|
40
|
-
|
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
|
-
|
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
|
-
|
41
|
-
|
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
|
-
|
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
|
-
|
169
|
+
element.getId
|
63
170
|
end
|
64
171
|
|
65
|
-
|
66
|
-
|
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
|
-
|
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
|
-
:
|
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
|
-
|
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
|
-
|
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
|
40
|
-
|
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
|