neo4j 1.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +141 -0
- data/CONTRIBUTORS +15 -0
- data/Gemfile +3 -0
- data/README.rdoc +2015 -0
- data/lib/neo4j.old/batch_inserter.rb +144 -0
- data/lib/neo4j.old/config.rb +138 -0
- data/lib/neo4j.old/event_handler.rb +73 -0
- data/lib/neo4j.old/extensions/activemodel.rb +158 -0
- data/lib/neo4j.old/extensions/aggregate.rb +12 -0
- data/lib/neo4j.old/extensions/aggregate/aggregate_enum.rb +40 -0
- data/lib/neo4j.old/extensions/aggregate/ext/node_mixin.rb +69 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregate.rb +8 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregate_mixin.rb +331 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregator.rb +216 -0
- data/lib/neo4j.old/extensions/aggregate/node_group.rb +43 -0
- data/lib/neo4j.old/extensions/aggregate/prop_group.rb +30 -0
- data/lib/neo4j.old/extensions/aggregate/property_enum.rb +24 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregate.rb +8 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregate_mixin.rb +31 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregator.rb +80 -0
- data/lib/neo4j.old/extensions/find_path.rb +117 -0
- data/lib/neo4j.old/extensions/graph_algo.rb +1 -0
- data/lib/neo4j.old/extensions/graph_algo/all_simple_paths.rb +133 -0
- data/lib/neo4j.old/extensions/graph_algo/neo4j-graph-algo-0.3.jar +0 -0
- data/lib/neo4j.old/extensions/reindexer.rb +104 -0
- data/lib/neo4j.old/extensions/rest.rb +21 -0
- data/lib/neo4j.old/extensions/rest/rest.rb +336 -0
- data/lib/neo4j.old/extensions/rest/rest_mixin.rb +193 -0
- data/lib/neo4j.old/extensions/rest/server.rb +50 -0
- data/lib/neo4j.old/extensions/rest/stubs.rb +141 -0
- data/lib/neo4j.old/extensions/rest_master.rb +34 -0
- data/lib/neo4j.old/extensions/rest_slave.rb +31 -0
- data/lib/neo4j.old/extensions/tx_tracker.rb +392 -0
- data/lib/neo4j.old/indexer.rb +187 -0
- data/lib/neo4j.old/jars.rb +6 -0
- data/lib/neo4j.old/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j.old/jars/neo4j-kernel-1.0.jar +0 -0
- data/lib/neo4j.old/mixins/java_list_mixin.rb +139 -0
- data/lib/neo4j.old/mixins/java_node_mixin.rb +205 -0
- data/lib/neo4j.old/mixins/java_property_mixin.rb +169 -0
- data/lib/neo4j.old/mixins/java_relationship_mixin.rb +60 -0
- data/lib/neo4j.old/mixins/migration_mixin.rb +157 -0
- data/lib/neo4j.old/mixins/node_mixin.rb +249 -0
- data/lib/neo4j.old/mixins/property_class_methods.rb +265 -0
- data/lib/neo4j.old/mixins/rel_class_methods.rb +167 -0
- data/lib/neo4j.old/mixins/relationship_mixin.rb +103 -0
- data/lib/neo4j.old/neo.rb +247 -0
- data/lib/neo4j.old/node.rb +49 -0
- data/lib/neo4j.old/reference_node.rb +15 -0
- data/lib/neo4j.old/relationship.rb +85 -0
- data/lib/neo4j.old/relationships/decl_relationship_dsl.rb +164 -0
- data/lib/neo4j.old/relationships/has_list.rb +101 -0
- data/lib/neo4j.old/relationships/has_n.rb +129 -0
- data/lib/neo4j.old/relationships/node_traverser.rb +138 -0
- data/lib/neo4j.old/relationships/relationship_dsl.rb +149 -0
- data/lib/neo4j.old/relationships/traversal_position.rb +50 -0
- data/lib/neo4j.old/relationships/wrappers.rb +51 -0
- data/lib/neo4j.old/search_result.rb +72 -0
- data/lib/neo4j.old/transaction.rb +254 -0
- data/lib/neo4j.old/version.rb +3 -0
- data/lib/neo4j.rb +50 -0
- data/lib/neo4j/config.rb +137 -0
- data/lib/neo4j/database.rb +43 -0
- data/lib/neo4j/equal.rb +22 -0
- data/lib/neo4j/event_handler.rb +91 -0
- data/lib/neo4j/index.rb +157 -0
- data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/lucene-core-2.9.2.jar +0 -0
- data/lib/neo4j/jars/lucene-core-3.0.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-index-1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-lucene-index-0.1-20100916.085626-67.jar +0 -0
- data/lib/neo4j/mapping/class_methods/index.rb +21 -0
- data/lib/neo4j/mapping/class_methods/property.rb +139 -0
- data/lib/neo4j/mapping/class_methods/relationship.rb +96 -0
- data/lib/neo4j/mapping/class_methods/rule.rb +135 -0
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +151 -0
- data/lib/neo4j/mapping/has_n.rb +117 -0
- data/lib/neo4j/mapping/node_mixin.rb +70 -0
- data/lib/neo4j/neo4j.rb +65 -0
- data/lib/neo4j/node.rb +82 -0
- data/lib/neo4j/node_mixin.rb +4 -0
- data/lib/neo4j/node_relationship.rb +60 -0
- data/lib/neo4j/node_traverser.rb +141 -0
- data/lib/neo4j/property.rb +72 -0
- data/lib/neo4j/rails/lucene_connection_closer.rb +19 -0
- data/lib/neo4j/rails/model.rb +210 -0
- data/lib/neo4j/rails/railtie.rb +16 -0
- data/lib/neo4j/rails/transaction.rb +29 -0
- data/lib/neo4j/rails/value.rb +43 -0
- data/lib/neo4j/relationship.rb +88 -0
- data/lib/neo4j/relationship_traverser.rb +57 -0
- data/lib/neo4j/to_java.rb +17 -0
- data/lib/neo4j/transaction.rb +69 -0
- data/lib/neo4j/version.rb +3 -0
- data/neo4j.gemspec +30 -0
- metadata +243 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
module Relationships
|
4
|
+
|
5
|
+
# Provides appending and traversing nodes that are linked together in a list with
|
6
|
+
# relationships to the next list item.
|
7
|
+
#
|
8
|
+
class HasList
|
9
|
+
include Enumerable
|
10
|
+
attr_reader :relationship_type
|
11
|
+
|
12
|
+
def initialize(node, dsl, &filter)
|
13
|
+
@node = node
|
14
|
+
@relationship_type = "_list_#{dsl.to_type}_#{node.neo_id}"
|
15
|
+
if (dsl.counter?)
|
16
|
+
@counter_id = "_#{dsl.to_type}_size".to_sym
|
17
|
+
end
|
18
|
+
@cascade_delete = dsl.cascade_delete_prop_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def size
|
22
|
+
@node[@counter_id] || 0
|
23
|
+
end
|
24
|
+
|
25
|
+
# called by the event handler
|
26
|
+
def self.on_node_deleted(node) #:nodoc:
|
27
|
+
# check if node is member of one or more lists
|
28
|
+
node.lists{|list_item| list_item.prev.next = list_item.next if list_item.prev; list_item.size -= 1}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Appends one node to the end of the list
|
32
|
+
#
|
33
|
+
# :api: public
|
34
|
+
def <<(other)
|
35
|
+
# does node have a relationship ?
|
36
|
+
new_rel = []
|
37
|
+
if (@node.rel?(@relationship_type))
|
38
|
+
# get that relationship
|
39
|
+
first = @node.rels.outgoing(@relationship_type).first
|
40
|
+
|
41
|
+
# delete this relationship
|
42
|
+
first.del
|
43
|
+
old_first = first.other_node(@node)
|
44
|
+
new_rel << @node.add_rel(@relationship_type, other)
|
45
|
+
new_rel << other.add_rel(@relationship_type, old_first)
|
46
|
+
else
|
47
|
+
# the first node will be set
|
48
|
+
new_rel << @node.add_rel(@relationship_type, other)
|
49
|
+
end
|
50
|
+
|
51
|
+
if @cascade_delete
|
52
|
+
# the @node.neo_id is only used for cascade_delete_incoming since that node will be deleted when all the list items has been deleted.
|
53
|
+
# if cascade_delete_outgoing all nodes will be deleted when the root node is deleted
|
54
|
+
# if cascade_delete_incoming then the root node will be deleted when all root nodes' outgoing nodes are deleted
|
55
|
+
new_rel.each {|rel| rel[@cascade_delete] = @node.neo_id}
|
56
|
+
end
|
57
|
+
if @counter_id
|
58
|
+
@node[@counter_id] ||= 0
|
59
|
+
@node[@counter_id] += 1
|
60
|
+
end
|
61
|
+
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns true if the list is empty s
|
66
|
+
#
|
67
|
+
# :api: public
|
68
|
+
def empty?
|
69
|
+
!iterator.hasNext
|
70
|
+
end
|
71
|
+
|
72
|
+
def first
|
73
|
+
return nil unless @node.rel?(@relationship_type, :outgoing)
|
74
|
+
@node.rel(@relationship_type, :outgoing).end_node
|
75
|
+
end
|
76
|
+
|
77
|
+
def each
|
78
|
+
iter = iterator
|
79
|
+
while (iter.hasNext) do
|
80
|
+
n = iter.next
|
81
|
+
yield Neo4j.load_node(n.get_id)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def iterator
|
86
|
+
stop_evaluator = org.neo4j.graphdb.StopEvaluator::END_OF_GRAPH
|
87
|
+
traverser_order = org.neo4j.graphdb.Traverser::Order::BREADTH_FIRST
|
88
|
+
returnable_evaluator = org.neo4j.graphdb.ReturnableEvaluator::ALL_BUT_START_NODE
|
89
|
+
types_and_dirs = []
|
90
|
+
types_and_dirs << org.neo4j.graphdb.DynamicRelationshipType.withName(@relationship_type.to_s)
|
91
|
+
types_and_dirs << org.neo4j.graphdb.Direction::OUTGOING
|
92
|
+
@node._java_node.traverse(traverser_order, stop_evaluator, returnable_evaluator, types_and_dirs.to_java(:object)).iterator
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Relationships
|
3
|
+
|
4
|
+
# Enables creating and traversal of nodes.
|
5
|
+
# Includes the Enumerable Mixin.
|
6
|
+
#
|
7
|
+
class HasN
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def initialize(node, dsl, &filter) # :nodoc:
|
11
|
+
@node = node
|
12
|
+
@traverser = NodeTraverser.new(node._java_node)
|
13
|
+
@outgoing = dsl.outgoing?
|
14
|
+
# returns the other DSL if it exists otherwise use this DSL for specifing incoming relationships
|
15
|
+
if @outgoing
|
16
|
+
@dsl = dsl
|
17
|
+
else
|
18
|
+
# which class specifies the incoming DSL ?
|
19
|
+
clazz = dsl.to_class || node.class
|
20
|
+
@dsl = clazz.decl_relationships[dsl.to_type]
|
21
|
+
raise "Unspecified outgoing relationship '#{dsl.to_type}' for incoming relationship '#{dsl.rel_id}' on class #{clazz}" if @dsl.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
if @outgoing
|
25
|
+
@traverser.outgoing(@dsl.namespace_type)
|
26
|
+
else
|
27
|
+
@traverser.incoming(@dsl.namespace_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
@traverser.filter(&filter) unless filter.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# Returns the relationships instead of the nodes.
|
35
|
+
#
|
36
|
+
# ==== Example
|
37
|
+
# # return the relationship objects between the folder and file nodes:
|
38
|
+
# folder.files.rels.each {|x| ...}
|
39
|
+
#
|
40
|
+
def rels
|
41
|
+
Neo4j::Relationships::RelationshipDSL.new(@node._java_node, (@outgoing)? :outgoing : :incoming, @dsl.namespace_type)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sets the depth of the traversal.
|
45
|
+
# Default is 1 if not specified.
|
46
|
+
#
|
47
|
+
# ==== Example
|
48
|
+
# morpheus.friends.depth(:all).each { ... }
|
49
|
+
# morpheus.friends.depth(3).each { ... }
|
50
|
+
#
|
51
|
+
# ==== Arguments
|
52
|
+
# d<Fixnum,Symbol>:: the depth or :all if traversing to the end of the network.
|
53
|
+
# ==== Return
|
54
|
+
# self
|
55
|
+
#
|
56
|
+
# :api: public
|
57
|
+
def depth(d)
|
58
|
+
@traverser.depth(d)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Required by the Enumerable mixin.
|
63
|
+
def each(&block)
|
64
|
+
@traverser.each(&block)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# Returns true if there are no node in this type of relationship
|
69
|
+
def empty?
|
70
|
+
@traverser.empty?
|
71
|
+
end
|
72
|
+
|
73
|
+
# Return the first relationship or nil
|
74
|
+
def first
|
75
|
+
@traverser.first
|
76
|
+
end
|
77
|
+
|
78
|
+
# Creates a relationship instance between this and the other node.
|
79
|
+
def new(other)
|
80
|
+
create_rel(@node, other)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Creates a relationship between this and the other node.
|
85
|
+
#
|
86
|
+
# ==== Example
|
87
|
+
#
|
88
|
+
# n1 = Node.new # Node has declared having a friend type of relationship
|
89
|
+
# n2 = Node.new
|
90
|
+
# n3 = Node.new
|
91
|
+
#
|
92
|
+
# n1 << n2 << n3
|
93
|
+
#
|
94
|
+
# This is the same as:
|
95
|
+
#
|
96
|
+
# n1.add_rel(:friends, n2)
|
97
|
+
# n1.add_rel(:friends, n3)
|
98
|
+
#
|
99
|
+
# ==== Returns
|
100
|
+
# self
|
101
|
+
#
|
102
|
+
# :api: public
|
103
|
+
def <<(other)
|
104
|
+
create_rel(@node, other)
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def create_rel(node, other) # :nodoc:
|
110
|
+
# If the are creating an incoming relationship we need to swap incoming and outgoing nodes
|
111
|
+
if @outgoing
|
112
|
+
from, to = node, other
|
113
|
+
else
|
114
|
+
from, to = other, node
|
115
|
+
end
|
116
|
+
|
117
|
+
rel = from.add_rel(@dsl.namespace_type, to, @dsl.relationship_class)
|
118
|
+
|
119
|
+
# the from.neo_id is only used for cascade_delete_incoming since that node will be deleted when all the list items has been deleted.
|
120
|
+
# if cascade_delete_outgoing all nodes will be deleted when the root node is deleted
|
121
|
+
# if cascade_delete_incoming then the root node will be deleted when all root nodes' outgoing nodes are deleted
|
122
|
+
rel[@dsl.cascade_delete_prop_name] = node.neo_id if @dsl.cascade_delete?
|
123
|
+
rel
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Relationships
|
3
|
+
|
4
|
+
class IllegalTraversalArguments < StandardError;
|
5
|
+
end
|
6
|
+
|
7
|
+
# Enables traversing nodes
|
8
|
+
# Contains state about one specific traversal to be performed.
|
9
|
+
class NodeTraverser
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
attr_accessor :raw
|
13
|
+
attr_reader :_java_node
|
14
|
+
|
15
|
+
def initialize(_java_node, raw = false)
|
16
|
+
@_java_node = _java_node
|
17
|
+
@raw = raw
|
18
|
+
@stop_evaluator = DepthStopEvaluator.new(1)
|
19
|
+
@types_and_dirs = [] # what types of relationships and which directions should be traversed
|
20
|
+
@traverser_order = org.neo4j.graphdb.Traverser::Order::BREADTH_FIRST
|
21
|
+
@returnable_evaluator = org.neo4j.graphdb.ReturnableEvaluator::ALL_BUT_START_NODE
|
22
|
+
end
|
23
|
+
|
24
|
+
# if raw == true then it will return raw Java object instead of wrapped JRuby object which can improve performance.
|
25
|
+
def raw(raw = true)
|
26
|
+
@raw = raw
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Sets the depth of the traversal.
|
31
|
+
# Default is 1 if not specified.
|
32
|
+
#
|
33
|
+
# ==== Example
|
34
|
+
# morpheus.outgoing(:friends).depth(:all).each { ... }
|
35
|
+
# morpheus.outgoing(:friends).depth(3).each { ... }
|
36
|
+
#
|
37
|
+
# ==== Arguments
|
38
|
+
# d<Fixnum,Symbol>:: the depth or :all if traversing to the end of the network.
|
39
|
+
# ==== Return
|
40
|
+
# self
|
41
|
+
#
|
42
|
+
# :api: public
|
43
|
+
def depth(d)
|
44
|
+
if d == :all
|
45
|
+
@stop_evaluator = org.neo4j.graphdb.StopEvaluator::END_OF_GRAPH
|
46
|
+
else
|
47
|
+
@stop_evaluator = DepthStopEvaluator.new(d)
|
48
|
+
end
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def filter(&proc)
|
53
|
+
@returnable_evaluator = ReturnableEvaluator.new(proc, @raw)
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def outgoing(*types)
|
58
|
+
types.each do |type|
|
59
|
+
@types_and_dirs << org.neo4j.graphdb.DynamicRelationshipType.withName(type.to_s)
|
60
|
+
@types_and_dirs << org.neo4j.graphdb.Direction::OUTGOING
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def incoming(*types)
|
66
|
+
types.each do |type|
|
67
|
+
@types_and_dirs << org.neo4j.graphdb.DynamicRelationshipType.withName(type.to_s)
|
68
|
+
@types_and_dirs << org.neo4j.graphdb.Direction::INCOMING
|
69
|
+
end
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def both(*types)
|
74
|
+
types.each do |type|
|
75
|
+
@types_and_dirs << org.neo4j.graphdb.DynamicRelationshipType.withName(type.to_s)
|
76
|
+
@types_and_dirs << org.neo4j.graphdb.Direction::BOTH
|
77
|
+
end
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def empty?
|
82
|
+
!iterator.hasNext
|
83
|
+
end
|
84
|
+
|
85
|
+
def first
|
86
|
+
find {true}
|
87
|
+
end
|
88
|
+
|
89
|
+
def each
|
90
|
+
iter = iterator
|
91
|
+
if @raw
|
92
|
+
while (iter.hasNext) do
|
93
|
+
yield iter.next
|
94
|
+
end
|
95
|
+
else
|
96
|
+
while (iter.hasNext) do
|
97
|
+
yield iter.next.wrapper
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Same as #each method but includes the TraversalPosition argument as a yield argument.
|
103
|
+
#
|
104
|
+
#
|
105
|
+
def each_with_position(&block)
|
106
|
+
traverser = create_traverser
|
107
|
+
iter = traverser.iterator
|
108
|
+
while (iter.hasNext) do
|
109
|
+
n = iter.next
|
110
|
+
tp = TraversalPosition.new(traverser.currentPosition(), @raw)
|
111
|
+
block.call Neo4j.load_node(n.get_id), tp
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def create_traverser
|
117
|
+
# check that we know which type of relationship should be traversed
|
118
|
+
if @types_and_dirs.empty?
|
119
|
+
raise IllegalTraversalArguments.new "Unknown type of relationship. Needs to know which type(s) of relationship in order to traverse. Please use the outgoing, incoming or both method."
|
120
|
+
end
|
121
|
+
|
122
|
+
@_java_node.traverse(@traverser_order, @stop_evaluator,
|
123
|
+
@returnable_evaluator, @types_and_dirs.to_java(:object))
|
124
|
+
end
|
125
|
+
|
126
|
+
def iterator
|
127
|
+
create_traverser.iterator
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_s
|
131
|
+
"NodeTraverser [direction=#{@direction}, type=#{@type}]"
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Relationships
|
3
|
+
|
4
|
+
# Enables finding relationships for one node
|
5
|
+
#
|
6
|
+
class RelationshipDSL
|
7
|
+
include Enumerable
|
8
|
+
attr_reader :node
|
9
|
+
|
10
|
+
def initialize(node, direction = :outgoing, type = nil)
|
11
|
+
@raw = false
|
12
|
+
@type = type
|
13
|
+
@node = node
|
14
|
+
|
15
|
+
case direction
|
16
|
+
when :outgoing
|
17
|
+
outgoing(type)
|
18
|
+
when :incoming
|
19
|
+
incoming(type)
|
20
|
+
when :both
|
21
|
+
both(type)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# if raw == true then it will return raw Java object instead of wrapped JRuby object which can improve performance.
|
26
|
+
def raw(raw = true)
|
27
|
+
@raw = raw
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def outgoing(type = nil)
|
32
|
+
@type = type
|
33
|
+
@direction = org.neo4j.graphdb.Direction::OUTGOING
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def incoming(type = nil)
|
38
|
+
@type = type
|
39
|
+
@direction = org.neo4j.graphdb.Direction::INCOMING
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def filter(&filter_proc)
|
44
|
+
@filter_proc = filter_proc
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def both(type = nil)
|
49
|
+
@type = type
|
50
|
+
@direction = org.neo4j.graphdb.Direction::BOTH
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# Creates a not declared relationship between this node and the given other_node with the given relationship type
|
56
|
+
# Use this method if you do not want to declare the relationship with the class methods has_one or has_n.
|
57
|
+
# Can be used at any time on any node.
|
58
|
+
#
|
59
|
+
# Only supports outgoing relationships.
|
60
|
+
#
|
61
|
+
# ==== Example
|
62
|
+
#
|
63
|
+
# node1 = Neo4j::Node.new
|
64
|
+
# node2 = Neo4j::Node.new
|
65
|
+
# node1.rels.outgoing(:some_relationship_type) << node2 << node3
|
66
|
+
#
|
67
|
+
# ==== Returns
|
68
|
+
# self - so that the << can be chained
|
69
|
+
#
|
70
|
+
# :api: public
|
71
|
+
def <<(other_node)
|
72
|
+
source, target = @node, other_node
|
73
|
+
source, target = target, source if @direction == org.neo4j.graphdb.Direction::INCOMING
|
74
|
+
source.add_rel(@type, target)
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def empty?
|
79
|
+
!iterator.hasNext
|
80
|
+
end
|
81
|
+
|
82
|
+
# Return the first relationship or nil
|
83
|
+
def first
|
84
|
+
find {true}
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Returns the relationship object to the other node.
|
89
|
+
#
|
90
|
+
def [](other_node)
|
91
|
+
find {|r| r.end_node.neo_id == other_node.neo_id}
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def each
|
96
|
+
iter = iterator
|
97
|
+
while (iter.hasNext) do
|
98
|
+
rel = @raw ? iter.next : iter.next.wrapper
|
99
|
+
next if @filter_proc && !rel.instance_eval(&@filter_proc)
|
100
|
+
yield rel
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def nodes
|
105
|
+
RelationshipsEnumeration.new(self, @raw)
|
106
|
+
end
|
107
|
+
|
108
|
+
def iterator
|
109
|
+
# if type is nil then we traverse all relationship types of depth one
|
110
|
+
return @node.getRelationships(@direction).iterator if @type.nil?
|
111
|
+
return @node.getRelationships(org.neo4j.graphdb.DynamicRelationshipType.withName(@type.to_s), @direction).iterator unless @type.nil?
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_s
|
115
|
+
"RelationshipDSL [direction=#{@direction}, type=#{@type}]"
|
116
|
+
end
|
117
|
+
|
118
|
+
# Used from RelationshipDSL when traversing nodes instead of relationships.
|
119
|
+
#
|
120
|
+
class RelationshipsEnumeration #:nodoc:
|
121
|
+
include Enumerable
|
122
|
+
|
123
|
+
def initialize(relationships, raw)
|
124
|
+
@relationships = relationships
|
125
|
+
@raw = raw
|
126
|
+
end
|
127
|
+
|
128
|
+
def first
|
129
|
+
find {true}
|
130
|
+
end
|
131
|
+
|
132
|
+
def empty?
|
133
|
+
first.nil?
|
134
|
+
end
|
135
|
+
|
136
|
+
def each
|
137
|
+
if @raw
|
138
|
+
@relationships.each { |relationship| yield relationship.other_node(@relationships.node) }
|
139
|
+
else
|
140
|
+
@relationships.each { |relationship| yield relationship.other_node(@relationships.node).wrapper }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|