neo4j 1.0.0.beta.27-java → 1.0.0.beta.28-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CONTRIBUTORS +1 -0
- data/lib/neo4j.rb +38 -72
- data/lib/neo4j/{algo.rb → algo/algo.rb} +5 -1
- data/lib/neo4j/batch/batch.rb +2 -0
- data/lib/neo4j/batch/indexer.rb +108 -0
- data/lib/neo4j/batch/inserter.rb +168 -0
- data/lib/neo4j/database.rb +13 -8
- data/lib/neo4j/{mapping/class_methods/list.rb → has_list/class_methods.rb} +2 -4
- data/lib/neo4j/has_list/has_list.rb +3 -0
- data/lib/neo4j/{mapping/has_list.rb → has_list/mapping.rb} +2 -2
- data/lib/neo4j/{mapping/class_methods/relationship.rb → has_n/class_methods.rb} +42 -12
- data/lib/neo4j/has_n/decl_relationship_dsl.rb +216 -0
- data/lib/neo4j/has_n/has_n.rb +3 -0
- data/lib/neo4j/{mapping/has_n.rb → has_n/mapping.rb} +16 -7
- data/lib/neo4j/index/index.rb +5 -0
- data/lib/neo4j/index/indexer.rb +27 -22
- data/lib/neo4j/index/lucene_query.rb +3 -1
- data/lib/neo4j/jars/core/neo4j-graph-algo-0.8-1.3.M01.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-index-1.3-1.3.M01.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-kernel-1.3-1.3.M01.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-lucene-index-0.5-1.3.M01.jar +0 -0
- data/lib/neo4j/jars/ha/{neo4j-ha-0.6-SNAPSHOT.jar → neo4j-ha-0.6-1.3.M01.jar} +0 -0
- data/lib/neo4j/jars/ha/neo4j-management-1.3-1.3.M01.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-shell-1.3-1.3.M01.jar +0 -0
- data/lib/neo4j/migrations/class_methods.rb +102 -0
- data/lib/neo4j/migrations/extensions.rb +10 -9
- data/lib/neo4j/migrations/lazy_node_mixin.rb +50 -0
- data/lib/neo4j/migrations/migration.rb +84 -81
- data/lib/neo4j/migrations/migrations.rb +6 -100
- data/lib/neo4j/migrations/node_mixin.rb +80 -0
- data/lib/neo4j/migrations/ref_node_wrapper.rb +32 -0
- data/lib/neo4j/neo4j.rb +11 -0
- data/lib/neo4j/node.rb +55 -25
- data/lib/neo4j/{mapping/class_methods/init_node.rb → node_mixin/class_methods.rb} +3 -3
- data/lib/neo4j/{mapping → node_mixin}/node_mixin.rb +35 -18
- data/lib/neo4j/{mapping/class_methods/property.rb → property/class_methods.rb} +5 -4
- data/lib/neo4j/{property.rb → property/property.rb} +2 -0
- data/lib/neo4j/rails/finders.rb +21 -7
- data/lib/neo4j/rails/rails.rb +19 -0
- data/lib/neo4j/rails/timestamps.rb +1 -1
- data/lib/neo4j/relationship.rb +7 -0
- data/lib/neo4j/{mapping/class_methods/init_rel.rb → relationship_mixin/class_methods.rb} +4 -4
- data/lib/neo4j/{mapping → relationship_mixin}/relationship_mixin.rb +23 -5
- data/lib/neo4j/rels/rels.rb +85 -0
- data/lib/neo4j/rels/traverser.rb +102 -0
- data/lib/neo4j/{mapping/class_methods/rule.rb → rule/class_methods.rb} +11 -11
- data/lib/neo4j/rule/functions/count.rb +37 -0
- data/lib/neo4j/rule/functions/function.rb +74 -0
- data/lib/neo4j/rule/functions/functions.rb +3 -0
- data/lib/neo4j/rule/functions/sum.rb +29 -0
- data/lib/neo4j/rule/rule.rb +5 -0
- data/lib/neo4j/rule/rule_event_listener.rb +162 -0
- data/lib/neo4j/rule/rule_node.rb +182 -0
- data/lib/neo4j/to_java.rb +0 -14
- data/lib/neo4j/traversal/filter_predicate.rb +25 -0
- data/lib/neo4j/traversal/prune_evaluator.rb +14 -0
- data/lib/neo4j/traversal/rel_expander.rb +31 -0
- data/lib/neo4j/traversal/traversal.rb +90 -0
- data/lib/neo4j/traversal/traverser.rb +173 -0
- data/lib/neo4j/{type_converters.rb → type_converters/type_converters.rb} +0 -0
- data/lib/neo4j/version.rb +1 -1
- data/lib/test.rb~ +2 -0
- data/neo4j.gemspec +11 -10
- metadata +48 -37
- data/lib/neo4j/functions/count.rb +0 -33
- data/lib/neo4j/functions/function.rb +0 -72
- data/lib/neo4j/functions/sum.rb +0 -27
- data/lib/neo4j/jars/core/neo4j-graph-algo-0.8-SNAPSHOT.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-index-1.3-SNAPSHOT.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-kernel-1.3-SNAPSHOT.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-lucene-index-0.5-SNAPSHOT.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-management-1.3-SNAPSHOT.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-shell-1.3-SNAPSHOT.jar +0 -0
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +0 -214
- data/lib/neo4j/mapping/rule.rb +0 -158
- data/lib/neo4j/mapping/rule_node.rb +0 -176
- data/lib/neo4j/migrations.rb +0 -12
- data/lib/neo4j/migrations/global_migration.rb +0 -29
- data/lib/neo4j/migrations/lazy_migration_mixin.rb +0 -47
- data/lib/neo4j/migrations/migration_mixin.rb +0 -78
- data/lib/neo4j/node_mixin.rb +0 -4
- data/lib/neo4j/node_relationship.rb +0 -161
- data/lib/neo4j/node_traverser.rb +0 -224
- data/lib/neo4j/relationship_mixin.rb +0 -4
- data/lib/neo4j/relationship_traverser.rb +0 -92
@@ -1,33 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Functions
|
3
|
-
class Count < Function
|
4
|
-
def initialize
|
5
|
-
@property = '_classname'
|
6
|
-
end
|
7
|
-
|
8
|
-
def calculate?(changed_property)
|
9
|
-
true
|
10
|
-
end
|
11
|
-
|
12
|
-
def delete(rule_name, rule_node, old_value)
|
13
|
-
key = rule_node_property(rule_name)
|
14
|
-
rule_node[key] ||= 0
|
15
|
-
rule_node[key] -= 1
|
16
|
-
end
|
17
|
-
|
18
|
-
def add(rule_name, rule_node, new_value)
|
19
|
-
key = rule_node_property(rule_name)
|
20
|
-
rule_node[key] ||= 0
|
21
|
-
rule_node[key] += 1
|
22
|
-
end
|
23
|
-
|
24
|
-
def update(*)
|
25
|
-
# we are only counting, not interested in property changes
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.function_name
|
29
|
-
:count
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Functions
|
3
|
-
|
4
|
-
# The base class of rule functions.
|
5
|
-
#
|
6
|
-
# You are expected to at least implement two methods:
|
7
|
-
# * update :: update the rule node value of this function
|
8
|
-
# * function_name :: the name of this function, the name of the generated method - A class method !
|
9
|
-
#
|
10
|
-
class Function
|
11
|
-
|
12
|
-
# Initialize the the function with a property which is usually the same as the function identity.
|
13
|
-
# See the #calculate? method how this property is used.
|
14
|
-
#
|
15
|
-
def initialize(property)
|
16
|
-
@property = property.to_s
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
"Function #{self.class.function_name} function_id: #{function_id}"
|
21
|
-
end
|
22
|
-
|
23
|
-
# Decides if the function should be called are not
|
24
|
-
#
|
25
|
-
def calculate?(changed_property)
|
26
|
-
@property == changed_property
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
# The identity of the function.
|
31
|
-
# Used to identify function.
|
32
|
-
#
|
33
|
-
# ==== Example
|
34
|
-
# Person.sum(:young, :age)
|
35
|
-
#
|
36
|
-
# In the example above the property :age is the used to identify which function will be called
|
37
|
-
# since there could be several sum method. In the example we want use the sum method that uses the :age property.
|
38
|
-
#
|
39
|
-
def function_id
|
40
|
-
@property
|
41
|
-
end
|
42
|
-
|
43
|
-
# The value of the rule
|
44
|
-
def value(rule_node, rule_name)
|
45
|
-
key = rule_node_property(rule_name)
|
46
|
-
rule_node[key] || 0
|
47
|
-
end
|
48
|
-
|
49
|
-
# Called when a node is removed from a rule group
|
50
|
-
# Default is calling update method which is expected to be implemented in a subclass
|
51
|
-
def delete(rule_name, rule_node, old_value)
|
52
|
-
update(rule_name, rule_node, old_value, nil)
|
53
|
-
end
|
54
|
-
|
55
|
-
# Called when a node is added to a rule group
|
56
|
-
# Default is calling update method which is expected to be implemented in a subclass
|
57
|
-
def add(rule_name, rule_node, new_value)
|
58
|
-
update(rule_name, rule_node, nil, new_value)
|
59
|
-
end
|
60
|
-
|
61
|
-
# the name of the property that holds the value of the function
|
62
|
-
def rule_node_property(rule_name)
|
63
|
-
self.class.rule_node_property(self.class.function_name, rule_name, @property)
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.rule_node_property(function_name, rule_name, prop)
|
67
|
-
"_#{function_name}_#{rule_name}_#{prop}"
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
data/lib/neo4j/functions/sum.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Functions
|
3
|
-
|
4
|
-
class Sum < Function
|
5
|
-
# Updates the function's value.
|
6
|
-
# Called after the transactions commits and a property has been changed on a node.
|
7
|
-
#
|
8
|
-
# ==== Arguments
|
9
|
-
# * rule_name :: the name of the rule group
|
10
|
-
# * rule_node :: the node which contains the value of this function
|
11
|
-
# * old_value new value :: the changed value of the property (when the transaction commits)
|
12
|
-
def update(rule_name, rule_node, old_value, new_value)
|
13
|
-
key = rule_node_property(rule_name)
|
14
|
-
rule_node[key] ||= 0
|
15
|
-
old_value ||= 0
|
16
|
-
new_value ||= 0
|
17
|
-
rule_node[key] += new_value - old_value
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.function_name
|
21
|
-
:sum
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,214 +0,0 @@
|
|
1
|
-
module Neo4j::Mapping
|
2
|
-
|
3
|
-
|
4
|
-
# A DSL for declared relationships has_n and has_one
|
5
|
-
# This DSL will be used to create accessor methods for relationships.
|
6
|
-
# Instead of using the 'raw' Neo4j::NodeMixin#rels method where one needs to know
|
7
|
-
# the name of relationship and direction one can use the generated accessor methods.
|
8
|
-
#
|
9
|
-
# The DSL can also be used to specify a mapping to a Ruby class for a relationship, see Neo4j::Relationships::DeclRelationshipDsl#relationship
|
10
|
-
#
|
11
|
-
# ==== Example
|
12
|
-
#
|
13
|
-
# class Folder
|
14
|
-
# include Neo4j::NodeMixin
|
15
|
-
# property :name
|
16
|
-
# # Declaring a Many relationship to any other node
|
17
|
-
# has_n(:files)
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# class File
|
21
|
-
# include Neo4j::NodeMixin
|
22
|
-
# # declaring a incoming relationship from Folder's relationship files
|
23
|
-
# has_one(:folder).from(Folder, :files)
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# The following methods will be generated:
|
27
|
-
# <b>Folder#files</b> :: returns an Enumerable of outgoing nodes for relationship 'files'
|
28
|
-
# <b>Folder#files_rels</b> :: returns an Enumerable of outgoing relationships for relationship 'files'
|
29
|
-
# <b>File#folder</b> :: for adding one node for the relationship 'files' from the outgoing Folder node
|
30
|
-
# <b>File#folder_rel</b> :: for accessing relationship 'files' from the outgoing Folder node
|
31
|
-
# <b>File#folder</b> :: for accessing nodes from relationship 'files' from the outgoing Folder node
|
32
|
-
#
|
33
|
-
class DeclRelationshipDsl
|
34
|
-
include Neo4j::ToJava
|
35
|
-
|
36
|
-
attr_reader :target_class, :direction, :rel_type
|
37
|
-
|
38
|
-
def initialize(method_id, has_one, target_class, params)
|
39
|
-
@direction = :outgoing
|
40
|
-
@method_id = method_id
|
41
|
-
@has_one = has_one
|
42
|
-
@rel_type = method_id
|
43
|
-
@target_class = target_class
|
44
|
-
end
|
45
|
-
|
46
|
-
def to_s
|
47
|
-
"DeclRelationshipDsl #{object_id} dir: #{@direction} rel_id: #{@method_id}, rel_type: #{@rel_type}, target_class:#{@target_class} rel_class:#{@relationship}"
|
48
|
-
end
|
49
|
-
|
50
|
-
def has_one?
|
51
|
-
@has_one
|
52
|
-
end
|
53
|
-
|
54
|
-
def each_node(node, direction, raw = false, &block) #:nodoc:
|
55
|
-
type = type_to_java(rel_type)
|
56
|
-
dir = dir_to_java(direction)
|
57
|
-
node._java_node.getRelationships(type, dir).each do |rel|
|
58
|
-
other = raw ? rel.getOtherNode(node) : rel.getOtherNode(node).wrapper
|
59
|
-
block.call other
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def incoming? #:nodoc:
|
64
|
-
@direction == :incoming
|
65
|
-
end
|
66
|
-
|
67
|
-
def single_node(node) #:nodoc:
|
68
|
-
rel = single_relationship(node)
|
69
|
-
rel && rel.other_node(node).wrapper
|
70
|
-
end
|
71
|
-
|
72
|
-
def single_relationship(node) #:nodoc:
|
73
|
-
node._java_node.rel(direction, rel_type)
|
74
|
-
end
|
75
|
-
|
76
|
-
def _all_relationships(node) #:nodoc:
|
77
|
-
type = type_to_java(rel_type)
|
78
|
-
dir = dir_to_java(direction)
|
79
|
-
node._java_node.getRelationships(type, dir)
|
80
|
-
end
|
81
|
-
|
82
|
-
def all_relationships(node) #:nodoc:
|
83
|
-
Neo4j::RelationshipTraverser.new(node._java_node, [rel_type], direction)
|
84
|
-
end
|
85
|
-
|
86
|
-
def create_relationship_to(node, other) # :nodoc:
|
87
|
-
from, to = incoming? ? [other, node] : [node, other]
|
88
|
-
java_type = type_to_java(rel_type)
|
89
|
-
|
90
|
-
rel = from._java_node.create_relationship_to(to._java_node, java_type)
|
91
|
-
rel[:_classname] = relationship_class.to_s if relationship_class
|
92
|
-
rel.wrapper
|
93
|
-
end
|
94
|
-
|
95
|
-
# Specifies an outgoing relationship.
|
96
|
-
# The name of the outgoing class will be used as a prefix for the relationship used.
|
97
|
-
#
|
98
|
-
# ==== Arguments
|
99
|
-
# clazz:: to which class this relationship goes
|
100
|
-
# relationship:: optional, the relationship to use
|
101
|
-
#
|
102
|
-
# ==== Example
|
103
|
-
# class FolderNode
|
104
|
-
# include Neo4j::NodeMixin
|
105
|
-
# has_n(:files).to(FileNode)
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# folder = FolderNode.new
|
109
|
-
# # generate a relationship between folder and file of type 'FileNode#files'
|
110
|
-
# folder.files << FileNode.new
|
111
|
-
#
|
112
|
-
def to(*args)
|
113
|
-
@direction = :outgoing
|
114
|
-
|
115
|
-
if (args.size > 1)
|
116
|
-
raise "only one argument expected - the class of the node this relationship points to, got #{args.inspect}"
|
117
|
-
elsif (Class === args[0])
|
118
|
-
# handle e.g. has_n(:friends).to(class)
|
119
|
-
@target_class = args[0]
|
120
|
-
@rel_type = "#{@target_class}##{@method_id}"
|
121
|
-
else
|
122
|
-
raise "Expected a class for, got #{args[0]}"
|
123
|
-
end
|
124
|
-
self
|
125
|
-
end
|
126
|
-
|
127
|
-
# Specifies an incoming relationship.
|
128
|
-
# Will use the outgoing relationship given by the from class.
|
129
|
-
#
|
130
|
-
# ==== Example, with prefix FileNode
|
131
|
-
# class FolderNode
|
132
|
-
# include Neo4j::NodeMixin
|
133
|
-
# has_n(:files).to(FileNode)
|
134
|
-
# end
|
135
|
-
#
|
136
|
-
# class FileNode
|
137
|
-
# include Neo4j::NodeMixin
|
138
|
-
# # will only traverse any incoming relationship of type files from node FileNode
|
139
|
-
# has_one(:folder).from(FileNode, :files)
|
140
|
-
# end
|
141
|
-
#
|
142
|
-
# file = FileNode.new
|
143
|
-
# # create an outgoing relationship of type 'FileNode#files' from folder node to file (FileNode is the prefix).
|
144
|
-
# file.folder = FolderNode.new
|
145
|
-
#
|
146
|
-
# ==== Example, without prefix
|
147
|
-
#
|
148
|
-
# class FolderNode
|
149
|
-
# include Neo4j::NodeMixin
|
150
|
-
# has_n(:files)
|
151
|
-
# end
|
152
|
-
#
|
153
|
-
# class FileNode
|
154
|
-
# include Neo4j::NodeMixin
|
155
|
-
# has_one(:folder).from(:files) # will traverse any incoming relationship of type files
|
156
|
-
# end
|
157
|
-
#
|
158
|
-
# file = FileNode.new
|
159
|
-
# # create an outgoing relationship of type 'FileNode#files' from folder node to file
|
160
|
-
# file.folder = FolderNode.new
|
161
|
-
#
|
162
|
-
#
|
163
|
-
def from(*args)
|
164
|
-
@direction = :incoming
|
165
|
-
|
166
|
-
if (args.size > 1)
|
167
|
-
# handle specified (prefixed) relationship, e.g. has_n(:known_by).from(clazz, :type)
|
168
|
-
@rel_type = "#{@target_class}##{args[1]}"
|
169
|
-
@target_class = args[0]
|
170
|
-
other_class_dsl = @target_class._decl_rels[args[1]]
|
171
|
-
if other_class_dsl
|
172
|
-
@relationship = other_class_dsl.relationship_class
|
173
|
-
else
|
174
|
-
Neo4j.logger.warn "Unknown outgoing relationship #{args[1]} on #{@target_class}"
|
175
|
-
end
|
176
|
-
elsif (Symbol === args[0])
|
177
|
-
# handle unspecified (unprefixed) relationship, e.g. has_n(:known_by).from(:type)
|
178
|
-
@rel_type = args[0]
|
179
|
-
else
|
180
|
-
raise "Expected a symbol for, got #{args[0]}"
|
181
|
-
end
|
182
|
-
self
|
183
|
-
end
|
184
|
-
|
185
|
-
# Specifies which relationship ruby class to use for the relationship
|
186
|
-
#
|
187
|
-
# ==== Example
|
188
|
-
#
|
189
|
-
# class OrderLine
|
190
|
-
# include Neo4j::RelationshipMixin
|
191
|
-
# property :units
|
192
|
-
# property :unit_price
|
193
|
-
# end
|
194
|
-
#
|
195
|
-
# class Order
|
196
|
-
# property :total_cost
|
197
|
-
# property :dispatched
|
198
|
-
# has_n(:products).to(Product).relationship(OrderLine)
|
199
|
-
# end
|
200
|
-
#
|
201
|
-
# order = Order.new
|
202
|
-
# order.products << Product.new
|
203
|
-
# order.products_rels.first # => OrderLine
|
204
|
-
#
|
205
|
-
def relationship(rel_class)
|
206
|
-
@relationship = rel_class
|
207
|
-
self
|
208
|
-
end
|
209
|
-
|
210
|
-
def relationship_class # :nodoc:
|
211
|
-
@relationship
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
data/lib/neo4j/mapping/rule.rb
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
module Neo4j::Mapping
|
2
|
-
|
3
|
-
|
4
|
-
# Holds all defined rules and trigger them when an event is received.
|
5
|
-
#
|
6
|
-
# See Neo4j::Mapping::ClassMethods::Rule
|
7
|
-
#
|
8
|
-
class Rule #:nodoc:
|
9
|
-
|
10
|
-
attr_reader :rule_name, :filter, :triggers, :functions
|
11
|
-
|
12
|
-
def initialize(rule_name, props, &block)
|
13
|
-
@rule_name = rule_name
|
14
|
-
@triggers = props[:triggers]
|
15
|
-
@functions = props[:functions]
|
16
|
-
@triggers = [@triggers] if @triggers && !@triggers.respond_to?(:each)
|
17
|
-
@functions = [@functions] if @functions && !@functions.respond_to?(:each)
|
18
|
-
@filter = block
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_s
|
22
|
-
"Rule #{rule_name} props=#{props.inspect}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def find_function(function_name, function_id)
|
26
|
-
function_id = function_id.to_s
|
27
|
-
@functions && @functions.find{|f| f.function_id == function_id && f.class.function_name == function_name}
|
28
|
-
end
|
29
|
-
|
30
|
-
# Reconstruct the properties given when created this rule
|
31
|
-
# Needed when inheriting a rule and we want to duplicate a rule
|
32
|
-
def props
|
33
|
-
props = {}
|
34
|
-
props[:triggers] = @triggers if @triggers
|
35
|
-
props[:functions] = @functions if @functions
|
36
|
-
props
|
37
|
-
end
|
38
|
-
|
39
|
-
def functions_for(property)
|
40
|
-
@functions && @functions.find_all { |f| f.calculate?(property) }
|
41
|
-
end
|
42
|
-
|
43
|
-
def execute_filter(node)
|
44
|
-
if @filter.nil?
|
45
|
-
true
|
46
|
-
elsif @filter.arity != 1
|
47
|
-
node.wrapper.instance_eval(&@filter)
|
48
|
-
else
|
49
|
-
@filter.call(node)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# ------------------------------------------------------------------------------------------------------------------
|
54
|
-
# Class Methods
|
55
|
-
# ------------------------------------------------------------------------------------------------------------------
|
56
|
-
|
57
|
-
class << self
|
58
|
-
def add(clazz, rule_name, props, &block)
|
59
|
-
rule_node = rule_node_for(clazz.to_s)
|
60
|
-
rule_node.remove_rule(rule_name) # remove any previously inherited rules
|
61
|
-
rule_node.add_rule(rule_name, props, &block)
|
62
|
-
end
|
63
|
-
|
64
|
-
def rule_names_for(clazz)
|
65
|
-
rule_node = rule_node_for(clazz)
|
66
|
-
rule_node.rules.map { |rule| rule.rule_name }
|
67
|
-
end
|
68
|
-
|
69
|
-
def rule_node_for(clazz)
|
70
|
-
return nil if clazz.nil?
|
71
|
-
@rule_nodes ||= {}
|
72
|
-
@rule_nodes[clazz.to_s] ||= RuleNode.new(clazz)
|
73
|
-
end
|
74
|
-
|
75
|
-
def inherit(parent_class, subclass)
|
76
|
-
# copy all the rules
|
77
|
-
if rule_node = rule_node_for(parent_class)
|
78
|
-
rule_node.inherit(subclass)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def delete(clazz)
|
83
|
-
if rule_node = rule_node_for(clazz)
|
84
|
-
rule_node.delete_node
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def trigger?(node)
|
89
|
-
classname = node[:_classname]
|
90
|
-
@rule_nodes && classname && rule_node_for(classname)
|
91
|
-
end
|
92
|
-
|
93
|
-
def trigger_rules(node, *changes)
|
94
|
-
classname = node[:_classname]
|
95
|
-
return unless classname # there are no rules if there is not a :_classname property
|
96
|
-
rule_node = rule_node_for(classname)
|
97
|
-
rule_node.execute_rules(node, *changes)
|
98
|
-
|
99
|
-
# recursively add relationships for all the parent classes with rules that also pass for this node
|
100
|
-
if (clazz = eval("#{classname}.superclass")) && clazz.include?(Neo4j::NodeMixin)
|
101
|
-
rule_node = rule_node_for(clazz)
|
102
|
-
rule_node && rule_node.execute_rules(node, *changes)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
# ----------------------------------------------------------------------------------------------------------------
|
108
|
-
# Event handling methods
|
109
|
-
# ----------------------------------------------------------------------------------------------------------------
|
110
|
-
|
111
|
-
def on_relationship_created(rel, *)
|
112
|
-
trigger_start_node = trigger?(rel._start_node)
|
113
|
-
trigger_end_node = trigger?(rel._end_node)
|
114
|
-
trigger_rules(rel._start_node) if trigger_start_node
|
115
|
-
trigger_rules(rel._end_node) if trigger_end_node
|
116
|
-
end
|
117
|
-
|
118
|
-
def on_property_changed(node, *changes)
|
119
|
-
trigger_rules(node, *changes) if trigger?(node)
|
120
|
-
end
|
121
|
-
|
122
|
-
def on_node_deleted(node, old_properties, data)
|
123
|
-
# have we deleted a rule node ?
|
124
|
-
del_rule_node = @rule_nodes && @rule_nodes.values.find{|rn| rn.rule_node?(node)}
|
125
|
-
del_rule_node && del_rule_node.clear_rule_node
|
126
|
-
return if del_rule_node
|
127
|
-
|
128
|
-
# do we have prop_aggregations for this
|
129
|
-
clazz = old_properties['_classname']
|
130
|
-
rule_node = rule_node_for(clazz)
|
131
|
-
return if rule_node.nil?
|
132
|
-
|
133
|
-
id = node.getId
|
134
|
-
rule_node.rules.each do |rule|
|
135
|
-
next if rule.functions.nil?
|
136
|
-
rule_name = rule.rule_name.to_s
|
137
|
-
|
138
|
-
# is the rule node deleted ?
|
139
|
-
deleted_rule_node = data.deletedNodes.find{|n| n == rule_node.rule_node}
|
140
|
-
next if deleted_rule_node
|
141
|
-
|
142
|
-
rule.functions.each do |function|
|
143
|
-
next unless data.deletedRelationships.find do |r|
|
144
|
-
r.getEndNode().getId() == id && r.rel_type == rule_name
|
145
|
-
end
|
146
|
-
previous_value = old_properties[function.function_id]
|
147
|
-
function.delete(rule_name, rule_node.rule_node, previous_value) if previous_value
|
148
|
-
end if rule.functions
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def on_neo4j_started(*)
|
153
|
-
@rule_nodes.each_value { |rule_node| rule_node.on_neo4j_started } if @rule_nodes
|
154
|
-
end
|
155
|
-
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|