/
relationship_traverser.rb
137 lines (113 loc) · 3.78 KB
/
relationship_traverser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
module Neo4j
module Relationships
# Enables finding relationships for one node
#
class RelationshipTraverser
include Enumerable
extend TransactionalMixin
attr_reader :internal_node
def initialize(node)
@node = node
@internal_node = node.internal_node
@direction = org.neo4j.api.core.Direction::OUTGOING
end
def outgoing(type = nil)
@type = type
@direction = org.neo4j.api.core.Direction::OUTGOING
self
end
def incoming(type = nil)
@type = type
@direction = org.neo4j.api.core.Direction::INCOMING
self
end
def filter(&filter_proc)
@filter_proc = filter_proc
self
end
def both(type = nil)
@type = type
@direction = org.neo4j.api.core.Direction::BOTH
self
end
# Creates a not declared relationship between this node and the given other_node with the given relationship type
# Use this method if you do not want to declare the relationship with the class methods has_one or has_n.
# Can be used at any time on any node.
#
# Only supports outgoing relationships.
#
# ==== Example
#
# node1 = Neo4j::Node.new
# node2 = Neo4j::Node.new
# node1.relationships.outgoing(:some_relationship_type) << node2
#
# ==== Returns
# a Relationship object (see Neo4j::RelationshipMixin) representing this created relationship
#
# :api: public
def <<(other_node)
source,target = @node, other_node
source,target = target,source if @direction == org.neo4j.api.core.Direction::INCOMING
source._create_relationship(@type.to_s, target)
end
def empty?
!iterator.hasNext
end
# Return the first relationship or nil
# TODO does not work together with filter, will be removed in JRuby 1.4 (not needed since it is included)
def first
iter = iterator
return nil unless iter.hasNext
return Neo4j.instance.load_relationship(iter.next)
end
#
# Returns the relationship object to the other node.
#
def [](other_node)
find {|r| r.end_node.neo_node_id == other_node.neo_node_id}
end
def each
iter = iterator
while (iter.hasNext) do
n = iter.next
rel = Neo4j.instance.load_relationship(n)
next if @filter_proc && !rel.instance_eval(&@filter_proc)
yield rel
end
end
def nodes
RelationshipsEnumeration.new(self)
end
def iterator
# if type is nil then we traverse all relationship types of depth one
return @internal_node.getRelationships(@direction).iterator if @type.nil?
return @internal_node.getRelationships(RelationshipType.instance(@type), @direction).iterator unless @type.nil?
end
def to_s
"RelationshipTraverser [direction=#{@direction}, type=#{@type}]"
end
# Used from RelationshipTraverser when traversing nodes instead of relationships.
#
class RelationshipsEnumeration #:nodoc:
include Enumerable
def initialize(relationships)
@relationships = relationships
end
# TODO does not work together with filter, will be removed in JRuby 1.4 (not needed since it is included)
def first
iter = @relationships.iterator
return nil unless iter.hasNext()
rel = Neo4j.instance.load_relationship(iter.next)
rel.other_node(@relationships.internal_node)
end
def each
@relationships.each do |relationship|
yield relationship.other_node(@relationships.internal_node)
end
end
end
transactional :empty?, :<<
end
end
end