neo4j 2.0.0.alpha.5-java → 2.0.0.alpha.6-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/Gemfile +0 -4
- data/README.rdoc +106 -62
- data/lib/neo4j.rb +7 -33
- data/lib/neo4j/performance.rb +43 -0
- data/lib/neo4j/rails/accept_id.rb +19 -18
- data/lib/neo4j/rails/attributes.rb +366 -120
- data/lib/neo4j/rails/finders.rb +41 -15
- data/lib/neo4j/rails/has_n.rb +203 -0
- data/lib/neo4j/rails/identity.rb +25 -0
- data/lib/neo4j/rails/model.rb +65 -242
- data/lib/neo4j/rails/nested_attributes.rb +108 -0
- data/lib/neo4j/rails/node_persistance.rb +56 -0
- data/lib/neo4j/rails/observer.rb +0 -2
- data/lib/neo4j/rails/persistence.rb +32 -154
- data/lib/neo4j/rails/rack_middleware.rb +26 -2
- data/lib/neo4j/rails/rails.rb +9 -6
- data/lib/neo4j/rails/railtie.rb +1 -2
- data/lib/neo4j/rails/relationship.rb +18 -125
- data/lib/neo4j/rails/relationship_persistence.rb +107 -0
- data/lib/neo4j/rails/relationships/node_dsl.rb +72 -44
- data/lib/neo4j/rails/relationships/relationships.rb +187 -59
- data/lib/neo4j/rails/relationships/rels_dsl.rb +18 -17
- data/lib/neo4j/rails/relationships/storage.rb +19 -17
- data/lib/neo4j/rails/timestamps.rb +53 -51
- data/lib/neo4j/rails/transaction.rb +9 -1
- data/lib/neo4j/rails/validations/uniqueness.rb +1 -1
- data/lib/neo4j/rails/versioning/versioning.rb +2 -2
- data/lib/neo4j/version.rb +1 -1
- data/lib/orm_adapter/adapters/neo4j.rb +47 -46
- data/neo4j.gemspec +1 -1
- metadata +10 -69
- data/lib/neo4j/algo/algo.rb +0 -294
- data/lib/neo4j/batch/batch.rb +0 -4
- data/lib/neo4j/batch/indexer.rb +0 -109
- data/lib/neo4j/batch/inserter.rb +0 -179
- data/lib/neo4j/batch/rule_inserter.rb +0 -24
- data/lib/neo4j/batch/rule_node.rb +0 -72
- data/lib/neo4j/config.rb +0 -177
- data/lib/neo4j/core_ext/class/inheritable_attributes.rb +0 -12
- data/lib/neo4j/core_ext/class/rewrite_inheritable_attributes.rb +0 -170
- data/lib/neo4j/database.rb +0 -158
- data/lib/neo4j/equal.rb +0 -21
- data/lib/neo4j/event_handler.rb +0 -263
- data/lib/neo4j/has_list/class_methods.rb +0 -11
- data/lib/neo4j/has_list/has_list.rb +0 -3
- data/lib/neo4j/has_list/mapping.rb +0 -133
- data/lib/neo4j/has_n/class_methods.rb +0 -119
- data/lib/neo4j/has_n/decl_relationship_dsl.rb +0 -246
- data/lib/neo4j/has_n/has_n.rb +0 -3
- data/lib/neo4j/has_n/mapping.rb +0 -98
- data/lib/neo4j/identity_map.rb +0 -140
- data/lib/neo4j/index/class_methods.rb +0 -108
- data/lib/neo4j/index/index.rb +0 -39
- data/lib/neo4j/index/indexer.rb +0 -341
- data/lib/neo4j/index/indexer_registry.rb +0 -68
- data/lib/neo4j/index/lucene_query.rb +0 -256
- data/lib/neo4j/load.rb +0 -25
- data/lib/neo4j/migrations/class_methods.rb +0 -110
- data/lib/neo4j/migrations/extensions.rb +0 -58
- data/lib/neo4j/migrations/lazy_node_mixin.rb +0 -41
- data/lib/neo4j/migrations/migration.rb +0 -112
- data/lib/neo4j/migrations/migrations.rb +0 -6
- data/lib/neo4j/migrations/node_mixin.rb +0 -80
- data/lib/neo4j/migrations/ref_node_wrapper.rb +0 -32
- data/lib/neo4j/model.rb +0 -4
- data/lib/neo4j/neo4j.rb +0 -216
- data/lib/neo4j/node.rb +0 -270
- data/lib/neo4j/node_mixin/class_methods.rb +0 -51
- data/lib/neo4j/node_mixin/node_mixin.rb +0 -141
- data/lib/neo4j/paginated.rb +0 -23
- data/lib/neo4j/property/class_methods.rb +0 -79
- data/lib/neo4j/property/property.rb +0 -111
- data/lib/neo4j/rails/mapping/property.rb +0 -183
- data/lib/neo4j/rails/rel_persistence.rb +0 -237
- data/lib/neo4j/relationship.rb +0 -239
- data/lib/neo4j/relationship_mixin/class_methods.rb +0 -36
- data/lib/neo4j/relationship_mixin/relationship_mixin.rb +0 -142
- data/lib/neo4j/relationship_set.rb +0 -58
- data/lib/neo4j/rels/rels.rb +0 -110
- data/lib/neo4j/rels/traverser.rb +0 -102
- data/lib/neo4j/rule/class_methods.rb +0 -201
- data/lib/neo4j/rule/event_listener.rb +0 -66
- data/lib/neo4j/rule/functions/count.rb +0 -43
- data/lib/neo4j/rule/functions/function.rb +0 -74
- data/lib/neo4j/rule/functions/functions.rb +0 -3
- data/lib/neo4j/rule/functions/sum.rb +0 -29
- data/lib/neo4j/rule/rule.rb +0 -150
- data/lib/neo4j/rule/rule_node.rb +0 -217
- data/lib/neo4j/to_java.rb +0 -31
- data/lib/neo4j/transaction.rb +0 -73
- data/lib/neo4j/traversal/filter_predicate.rb +0 -25
- data/lib/neo4j/traversal/prune_evaluator.rb +0 -14
- data/lib/neo4j/traversal/rel_expander.rb +0 -31
- data/lib/neo4j/traversal/traversal.rb +0 -141
- data/lib/neo4j/traversal/traverser.rb +0 -284
- data/lib/neo4j/type_converters/type_converters.rb +0 -288
@@ -1,12 +0,0 @@
|
|
1
|
-
# This is copied from Rails Active Support since it has been depricated and I still need it
|
2
|
-
|
3
|
-
# Taken from: https://raw.github.com/lifo/docrails/dd6c3676af3fa6019c53a59f62c4fd14966be728/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
|
4
|
-
|
5
|
-
# Changes made:
|
6
|
-
# - Remove deprecation warnings
|
7
|
-
# - Ignore if already available from ActiveSupport
|
8
|
-
#
|
9
|
-
# Can't use class_attribute because we want to use the same value for all subclasses
|
10
|
-
|
11
|
-
|
12
|
-
require 'neo4j/core_ext/class/rewrite_inheritable_attributes.rb'
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/object/duplicable'
|
2
|
-
require 'active_support/core_ext/array/extract_options'
|
3
|
-
|
4
|
-
# Retained for backward compatibility. Methods are now included in Class.
|
5
|
-
module ClassInheritableAttributes # :nodoc:
|
6
|
-
end
|
7
|
-
|
8
|
-
# It is recommended to use <tt>class_attribute</tt> over methods defined in this file. Please
|
9
|
-
# refer to documentation for <tt>class_attribute</tt> for more information. Officially it is not
|
10
|
-
#
|
11
|
-
# Allows attributes to be shared within an inheritance hierarchy. Each descendant gets a copy of
|
12
|
-
# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
|
13
|
-
# to, for example, an array without those additions being shared with either their parent, siblings, or
|
14
|
-
# children. This is unlike the regular class-level attributes that are shared across the entire hierarchy.
|
15
|
-
#
|
16
|
-
# The copies of inheritable parent attributes are added to subclasses when they are created, via the
|
17
|
-
# +inherited+ hook.
|
18
|
-
#
|
19
|
-
# class Person
|
20
|
-
# class_inheritable_accessor :hair_colors
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# Person.hair_colors = [:brown, :black, :blonde, :red]
|
24
|
-
# Person.hair_colors # => [:brown, :black, :blonde, :red]
|
25
|
-
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
|
26
|
-
#
|
27
|
-
# To opt out of the instance writer method, pass :instance_writer => false.
|
28
|
-
# To opt out of the instance reader method, pass :instance_reader => false.
|
29
|
-
#
|
30
|
-
# class Person
|
31
|
-
# class_inheritable_accessor :hair_colors :instance_writer => false, :instance_reader => false
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# Person.new.hair_colors = [:brown] # => NoMethodError
|
35
|
-
# Person.new.hair_colors # => NoMethodError
|
36
|
-
class Class # :nodoc:
|
37
|
-
def class_inheritable_reader(*syms)
|
38
|
-
options = syms.extract_options!
|
39
|
-
syms.each do |sym|
|
40
|
-
next if sym.is_a?(Hash)
|
41
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
42
|
-
def self.#{sym} # def self.after_add
|
43
|
-
read_inheritable_attribute(:#{sym}) # read_inheritable_attribute(:after_add)
|
44
|
-
end # end
|
45
|
-
#
|
46
|
-
#{" #
|
47
|
-
def #{sym} # def after_add
|
48
|
-
self.class.#{sym} # self.class.after_add
|
49
|
-
end # end
|
50
|
-
" unless options[:instance_reader] == false } # # the reader above is generated unless options[:instance_reader] == false
|
51
|
-
EOS
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def class_inheritable_writer(*syms)
|
56
|
-
options = syms.extract_options!
|
57
|
-
syms.each do |sym|
|
58
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
59
|
-
def self.#{sym}=(obj) # def self.color=(obj)
|
60
|
-
write_inheritable_attribute(:#{sym}, obj) # write_inheritable_attribute(:color, obj)
|
61
|
-
end # end
|
62
|
-
#
|
63
|
-
#{" #
|
64
|
-
def #{sym}=(obj) # def color=(obj)
|
65
|
-
self.class.#{sym} = obj # self.class.color = obj
|
66
|
-
end # end
|
67
|
-
" unless options[:instance_writer] == false } # # the writer above is generated unless options[:instance_writer] == false
|
68
|
-
EOS
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def class_inheritable_array_writer(*syms)
|
73
|
-
options = syms.extract_options!
|
74
|
-
syms.each do |sym|
|
75
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
76
|
-
def self.#{sym}=(obj) # def self.levels=(obj)
|
77
|
-
write_inheritable_array(:#{sym}, obj) # write_inheritable_array(:levels, obj)
|
78
|
-
end # end
|
79
|
-
#
|
80
|
-
#{" #
|
81
|
-
def #{sym}=(obj) # def levels=(obj)
|
82
|
-
self.class.#{sym} = obj # self.class.levels = obj
|
83
|
-
end # end
|
84
|
-
" unless options[:instance_writer] == false } # # the writer above is generated unless options[:instance_writer] == false
|
85
|
-
EOS
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def class_inheritable_hash_writer(*syms)
|
90
|
-
options = syms.extract_options!
|
91
|
-
syms.each do |sym|
|
92
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
93
|
-
def self.#{sym}=(obj) # def self.nicknames=(obj)
|
94
|
-
write_inheritable_hash(:#{sym}, obj) # write_inheritable_hash(:nicknames, obj)
|
95
|
-
end # end
|
96
|
-
#
|
97
|
-
#{" #
|
98
|
-
def #{sym}=(obj) # def nicknames=(obj)
|
99
|
-
self.class.#{sym} = obj # self.class.nicknames = obj
|
100
|
-
end # end
|
101
|
-
" unless options[:instance_writer] == false } # # the writer above is generated unless options[:instance_writer] == false
|
102
|
-
EOS
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def class_inheritable_accessor(*syms)
|
107
|
-
class_inheritable_reader(*syms)
|
108
|
-
class_inheritable_writer(*syms)
|
109
|
-
end
|
110
|
-
|
111
|
-
def class_inheritable_array(*syms)
|
112
|
-
class_inheritable_reader(*syms)
|
113
|
-
class_inheritable_array_writer(*syms)
|
114
|
-
end
|
115
|
-
|
116
|
-
def class_inheritable_hash(*syms)
|
117
|
-
class_inheritable_reader(*syms)
|
118
|
-
class_inheritable_hash_writer(*syms)
|
119
|
-
end
|
120
|
-
|
121
|
-
def inheritable_attributes
|
122
|
-
@inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
|
123
|
-
end
|
124
|
-
|
125
|
-
def write_inheritable_attribute(key, value)
|
126
|
-
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
127
|
-
@inheritable_attributes = {}
|
128
|
-
end
|
129
|
-
inheritable_attributes[key] = value
|
130
|
-
end
|
131
|
-
|
132
|
-
def write_inheritable_array(key, elements)
|
133
|
-
write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
|
134
|
-
write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
|
135
|
-
end
|
136
|
-
|
137
|
-
def write_inheritable_hash(key, hash)
|
138
|
-
write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
|
139
|
-
write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
|
140
|
-
end
|
141
|
-
|
142
|
-
def read_inheritable_attribute(key)
|
143
|
-
inheritable_attributes[key]
|
144
|
-
end
|
145
|
-
|
146
|
-
def reset_inheritable_attributes
|
147
|
-
@inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
148
|
-
end
|
149
|
-
|
150
|
-
private
|
151
|
-
# Prevent this constant from being created multiple times
|
152
|
-
EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze
|
153
|
-
|
154
|
-
def inherited_with_inheritable_attributes(child)
|
155
|
-
inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
|
156
|
-
|
157
|
-
if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
|
158
|
-
new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
|
159
|
-
else
|
160
|
-
new_inheritable_attributes = Hash[inheritable_attributes.map do |(key, value)|
|
161
|
-
[key, value.duplicable? ? value.dup : value]
|
162
|
-
end]
|
163
|
-
end
|
164
|
-
|
165
|
-
child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
|
166
|
-
end
|
167
|
-
|
168
|
-
alias inherited_without_inheritable_attributes inherited
|
169
|
-
alias inherited inherited_with_inheritable_attributes
|
170
|
-
end
|
data/lib/neo4j/database.rb
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
require 'neo4j/config'
|
2
|
-
require 'neo4j/event_handler'
|
3
|
-
require 'neo4j/transaction'
|
4
|
-
|
5
|
-
module Neo4j
|
6
|
-
# Wraps both Java Neo4j GraphDatabaseService and Lucene.
|
7
|
-
# You can access the raw java neo4j and lucene db's with the <tt>graph</tt> and <tt>lucene</tt>
|
8
|
-
# properties.
|
9
|
-
#
|
10
|
-
# This class is also responsible for checking if there is already a running neo4j database.
|
11
|
-
# If one tries to start an already started database then a read only instance to neo4j will be used.
|
12
|
-
#
|
13
|
-
class Database
|
14
|
-
attr_reader :graph, :lucene, :event_handler, :storage_path
|
15
|
-
|
16
|
-
alias_method :index, :lucene # needed by cypher
|
17
|
-
|
18
|
-
def initialize()
|
19
|
-
@event_handler = EventHandler.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def start #:nodoc:
|
23
|
-
return if running?
|
24
|
-
@running = true
|
25
|
-
@storage_path = Config.storage_path
|
26
|
-
|
27
|
-
begin
|
28
|
-
if self.class.locked?
|
29
|
-
start_readonly_graph_db
|
30
|
-
elsif Neo4j::Config['ha.db']
|
31
|
-
start_ha_graph_db
|
32
|
-
Neo4j.migrate!
|
33
|
-
else
|
34
|
-
start_local_graph_db
|
35
|
-
Neo4j.migrate!
|
36
|
-
end
|
37
|
-
rescue
|
38
|
-
@running = false
|
39
|
-
raise
|
40
|
-
end
|
41
|
-
|
42
|
-
at_exit { shutdown }
|
43
|
-
end
|
44
|
-
|
45
|
-
def start_readonly_graph_db #:nodoc:
|
46
|
-
Neo4j.logger.info "Starting Neo4j in readonly mode since the #{@storage_path} is locked"
|
47
|
-
@graph = org.neo4j.kernel.EmbeddedReadOnlyGraphDatabase.new(@storage_path, Config.to_java_map)
|
48
|
-
@lucene = @graph.index
|
49
|
-
end
|
50
|
-
|
51
|
-
def start_local_graph_db #:nodoc:
|
52
|
-
Neo4j.logger.info "Starting local Neo4j using db #{@storage_path}"
|
53
|
-
@graph = org.neo4j.kernel.EmbeddedGraphDatabase.new(@storage_path, Config.to_java_map)
|
54
|
-
@graph.register_transaction_event_handler(@event_handler)
|
55
|
-
@lucene = @graph.index
|
56
|
-
@event_handler.neo4j_started(self)
|
57
|
-
end
|
58
|
-
|
59
|
-
# needed by cypher
|
60
|
-
def getNodeById(id) #:nodoc:
|
61
|
-
Neo4j::Node.load(id)
|
62
|
-
end
|
63
|
-
|
64
|
-
# needed by cypher
|
65
|
-
def getRelationshipById(id) #:nodoc:
|
66
|
-
Neo4j::Relationship.load(id)
|
67
|
-
end
|
68
|
-
|
69
|
-
def start_ha_graph_db
|
70
|
-
Neo4j.logger.info "starting Neo4j in HA mode, machine id: #{Neo4j.config['ha.server_id']} at #{Neo4j.config['ha.server']} db #{@storage_path}"
|
71
|
-
# Modify the public base classes for the HA Node and Relationships
|
72
|
-
# (instead of private org.neo4j.kernel.HighlyAvailableGraphDatabase::LookupNode)
|
73
|
-
@graph = org.neo4j.kernel.HighlyAvailableGraphDatabase.new(@storage_path, Neo4j.config.to_java_map)
|
74
|
-
@graph.register_transaction_event_handler(@event_handler)
|
75
|
-
@lucene = @graph.index
|
76
|
-
@event_handler.neo4j_started(self)
|
77
|
-
end
|
78
|
-
|
79
|
-
def start_external_db(external_graph_db)
|
80
|
-
begin
|
81
|
-
@running = true
|
82
|
-
@graph = external_graph_db
|
83
|
-
Neo4j.migrate!
|
84
|
-
@graph.register_transaction_event_handler(@event_handler)
|
85
|
-
@lucene = @graph.index #org.neo4j.index.impl.lucene.LuceneIndexProvider.new
|
86
|
-
@event_handler.neo4j_started(self)
|
87
|
-
Neo4j.logger.info("Started with external db")
|
88
|
-
rescue
|
89
|
-
@running = false
|
90
|
-
raise
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def running? #:nodoc:
|
95
|
-
@running
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns true if the neo4j db was started in read only mode.
|
99
|
-
# This can occur if the database was locked (it was already one instance running).
|
100
|
-
def read_only?
|
101
|
-
@graph.java_class == org.neo4j.kernel.EmbeddedGraphDatabase
|
102
|
-
end
|
103
|
-
|
104
|
-
# check if the database is locked. A neo4j database is locked when the database is running.
|
105
|
-
def self.locked?
|
106
|
-
lock_file = File.join(Neo4j.config.storage_path, 'neostore')
|
107
|
-
return false unless File.exist?(lock_file)
|
108
|
-
rfile = java.io.RandomAccessFile.new(lock_file, 'rw')
|
109
|
-
begin
|
110
|
-
lock = rfile.getChannel.tryLock
|
111
|
-
lock.release if lock
|
112
|
-
return lock == nil # we got the lock, so that means it is not locked.
|
113
|
-
rescue Exception => e
|
114
|
-
return false
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def shutdown #:nodoc:
|
119
|
-
if @running
|
120
|
-
@graph.unregister_transaction_event_handler(@event_handler) unless read_only?
|
121
|
-
@event_handler.neo4j_shutdown(self)
|
122
|
-
@graph.shutdown
|
123
|
-
@graph = nil
|
124
|
-
@lucene = nil
|
125
|
-
@running = false
|
126
|
-
@neo4j_manager = nil
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
|
132
|
-
def management(jmx_clazz) #:nodoc:
|
133
|
-
@neo4j_manager ||= org.neo4j.management.Neo4jManager.new(@graph.get_management_bean(org.neo4j.jmx.Kernel.java_class))
|
134
|
-
@neo4j_manager.getBean(jmx_clazz.java_class)
|
135
|
-
end
|
136
|
-
|
137
|
-
def begin_tx #:nodoc:
|
138
|
-
@graph.begin_tx
|
139
|
-
end
|
140
|
-
|
141
|
-
|
142
|
-
def each_node #:nodoc:
|
143
|
-
iter = @graph.all_nodes.iterator
|
144
|
-
while (iter.hasNext)
|
145
|
-
yield iter.next.wrapper
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def _each_node #:nodoc:
|
150
|
-
iter = @graph.all_nodes.iterator
|
151
|
-
while (iter.hasNext)
|
152
|
-
yield iter.next
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
data/lib/neo4j/equal.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
|
3
|
-
# == This mixin is used for both nodes and relationships to decide if two entities are equal or not.
|
4
|
-
#
|
5
|
-
module Equal
|
6
|
-
def equal?(o)
|
7
|
-
eql?(o)
|
8
|
-
end
|
9
|
-
|
10
|
-
def eql?(o)
|
11
|
-
return false unless o.respond_to?(:getId)
|
12
|
-
o.getId == getId
|
13
|
-
end
|
14
|
-
|
15
|
-
def ==(o)
|
16
|
-
eql?(o)
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
data/lib/neo4j/event_handler.rb
DELETED
@@ -1,263 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
|
3
|
-
# == Handles Transactional Events
|
4
|
-
#
|
5
|
-
# You can use this to receive event before the transaction commits.
|
6
|
-
# The following events are supported:
|
7
|
-
# * <tt>on_neo4j_started</tt>
|
8
|
-
# * <tt>on_neo4j_shutdown</tt>
|
9
|
-
# * <tt>on_node_created</tt>
|
10
|
-
# * <tt>on_node_deleted</tt>
|
11
|
-
# * <tt>on_relationship_created</tt>
|
12
|
-
# * <tt>on_relationship_deleted</tt>
|
13
|
-
# * <tt>on_property_changed</tt>
|
14
|
-
# * <tt>on_rel_property_changed</tt>
|
15
|
-
# * <tt>on_after_commit</tt>
|
16
|
-
#
|
17
|
-
# ==== on_neo4j_started(db)
|
18
|
-
#
|
19
|
-
# Called when the neo4j engine starts.
|
20
|
-
# Notice that the neo4j will be started automatically when the first neo4j operation is performed.
|
21
|
-
# You can also start Neo4j: <tt>Neo4j.start</tt>
|
22
|
-
#
|
23
|
-
# * <tt>db</tt> :: the Neo4j::Database instance
|
24
|
-
#
|
25
|
-
# ==== on_neo4j_shutdown(db)
|
26
|
-
#
|
27
|
-
# Called when the neo4j engine shutdown. You don't need to call <tt>Neo4j.shutdown</tt> since
|
28
|
-
# the it will automatically be shutdown when the application exits (using the at_exit ruby hook).
|
29
|
-
#
|
30
|
-
# * <tt>db</tt> :: the Neo4j::Database instance
|
31
|
-
#
|
32
|
-
# ==== on_after_commit(data, state)
|
33
|
-
#
|
34
|
-
# Called after the transaction has successfully committed.
|
35
|
-
# See http://api.neo4j.org/1.4/org/neo4j/graphdb/event/TransactionEventHandler.html for the data and state parameter.
|
36
|
-
#
|
37
|
-
# ==== on_node_created(node)
|
38
|
-
#
|
39
|
-
# * <tt>node</tt> :: the node that was created
|
40
|
-
#
|
41
|
-
# ==== on_node_deleted(node, old_props, deleted_relationship_set, deleted_node_identity_map)
|
42
|
-
#
|
43
|
-
# * <tt>node</tt> :: the node that was deleted
|
44
|
-
# * <tt>old_props</tt> :: a hash of the old properties this node had
|
45
|
-
# * <tt>deleted_relationship_set</tt> :: the set of deleted relationships. See Neo4j::RelationshipSet
|
46
|
-
# * <tt>deleted_node_identity_map</tt> :: the identity map of deleted nodes. The key is the node id, and the value is the node
|
47
|
-
#
|
48
|
-
# ==== on_relationship_created(rel, created_node_identity_map)
|
49
|
-
#
|
50
|
-
# * <tt>rel</tt> :: the relationship that was created
|
51
|
-
# * <tt>created_node_identity_map</tt> :: the identity map of created nodes. The key is the node id, and the value is the node
|
52
|
-
#
|
53
|
-
# ==== on_relationship_deleted(rel, old_props, deleted_relationship_set, deleted_node_identity_map)
|
54
|
-
#
|
55
|
-
# * <tt>rel</tt> :: the relationship that was created
|
56
|
-
# * <tt>old_props</tt> :: a hash of the old properties this relationship had
|
57
|
-
# * <tt>deleted_relationship_set</tt> :: the set of deleted relationships. See Neo4j::RelationshipSet
|
58
|
-
# * <tt>deleted_node_identity_map</tt> :: the identity map of deleted nodes. The key is the node id, and the value is the node
|
59
|
-
#
|
60
|
-
# ==== on_property_changed(node, key, old_value, new_value)
|
61
|
-
#
|
62
|
-
# * <tt>node</tt> :: the node
|
63
|
-
# * <tt>key</tt> :: the name of the property that was changed (String)
|
64
|
-
# * <tt>old_value</tt> :: old value of the property
|
65
|
-
# * <tt>new_value</tt> :: new value of the property
|
66
|
-
#
|
67
|
-
# ==== on_rel_property_changed(rel, key, old_value, new_value)
|
68
|
-
#
|
69
|
-
# * <tt>rel</tt> :: the node that was created
|
70
|
-
# * <tt>key</tt> :: the name of the property that was changed (String)
|
71
|
-
# * <tt>old_value</tt> :: old value of the property
|
72
|
-
# * <tt>new_value</tt> :: new value of the property
|
73
|
-
#
|
74
|
-
# ==== classes_changed(class_change_map)
|
75
|
-
# * <tt>class_change_map</tt> :: a hash with class names as keys, and class changes as values. See Neo4j::ClassChanges
|
76
|
-
#
|
77
|
-
# == Usage
|
78
|
-
#
|
79
|
-
# class MyListener
|
80
|
-
# def on_node_deleted(node, old_props, deleted_relationship_set, deleted_node_identity_map)
|
81
|
-
# end
|
82
|
-
# end
|
83
|
-
#
|
84
|
-
# # to add an listener without starting neo4j:
|
85
|
-
# Neo4j.unstarted_db.event_handler.add(MyListener.new)
|
86
|
-
#
|
87
|
-
# You only need to implement the methods that you need.
|
88
|
-
#
|
89
|
-
class EventHandler
|
90
|
-
include org.neo4j.graphdb.event.TransactionEventHandler
|
91
|
-
|
92
|
-
def initialize
|
93
|
-
@listeners = []
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
def after_commit(data, state)
|
98
|
-
@listeners.each {|li| li.on_after_commit(data, state) if li.respond_to?(:on_after_commit)}
|
99
|
-
end
|
100
|
-
|
101
|
-
def after_rollback(data, state)
|
102
|
-
end
|
103
|
-
|
104
|
-
def before_commit(data)
|
105
|
-
class_change_map = java.util.HashMap.new
|
106
|
-
created_node_identity_map = iterate_created_nodes(data.created_nodes, class_change_map)
|
107
|
-
deleted_node_identity_map = deleted_node_identity_map(data.deleted_nodes)
|
108
|
-
deleted_relationship_set = relationship_set(data.deleted_relationships)
|
109
|
-
removed_node_properties_map = property_map(data.removed_node_properties)
|
110
|
-
removed_relationship_properties_map = property_map(data.removed_relationship_properties)
|
111
|
-
add_deleted_nodes(data, class_change_map, removed_node_properties_map)
|
112
|
-
empty_map = java.util.HashMap.new
|
113
|
-
data.assigned_node_properties.each { |tx_data| property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, tx_data.value) unless tx_data.key == '_classname'}
|
114
|
-
data.removed_node_properties.each { |tx_data| property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, nil) unless deleted_node_identity_map.containsKey(tx_data.entity.getId) }
|
115
|
-
data.deleted_nodes.each { |node| node_deleted(node, removed_node_properties_map.get(node.getId)||empty_map, deleted_relationship_set, deleted_node_identity_map)}
|
116
|
-
data.created_relationships.each {|rel| relationship_created(rel, created_node_identity_map)}
|
117
|
-
data.deleted_relationships.each {|rel| relationship_deleted(rel, removed_relationship_properties_map.get(rel.getId)||empty_map, deleted_relationship_set, deleted_node_identity_map)}
|
118
|
-
data.assigned_relationship_properties.each { |tx_data| rel_property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, tx_data.value) }
|
119
|
-
data.removed_relationship_properties.each {|tx_data| rel_property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, nil) unless deleted_relationship_set.contains_rel?(tx_data.entity) }
|
120
|
-
classes_changed(class_change_map)
|
121
|
-
rescue Exception => e
|
122
|
-
# since these exceptions gets swallowed
|
123
|
-
puts "ERROR in before commit hook #{e}"
|
124
|
-
puts e.backtrace.join("\n")
|
125
|
-
end
|
126
|
-
|
127
|
-
|
128
|
-
def iterate_created_nodes(nodes, class_change_map)
|
129
|
-
identity_map = java.util.HashMap.new
|
130
|
-
nodes.each do |node|
|
131
|
-
identity_map.put(node.neo_id,node) #using put due to a performance regression in JRuby 1.6.4
|
132
|
-
instance_created(node, class_change_map)
|
133
|
-
node_created(node)
|
134
|
-
end
|
135
|
-
identity_map
|
136
|
-
end
|
137
|
-
|
138
|
-
def deleted_node_identity_map(nodes)
|
139
|
-
identity_map = java.util.HashMap.new
|
140
|
-
nodes.each{|node| identity_map.put(node.neo_id,node)} #using put due to a performance regression in JRuby 1.6.4
|
141
|
-
identity_map
|
142
|
-
end
|
143
|
-
|
144
|
-
def relationship_set(relationships)
|
145
|
-
relationship_set = Neo4j::RelationshipSet.new#(relationships.size)
|
146
|
-
relationships.each{|rel| relationship_set.add(rel)}
|
147
|
-
relationship_set
|
148
|
-
end
|
149
|
-
|
150
|
-
def property_map(properties)
|
151
|
-
map = java.util.HashMap.new
|
152
|
-
properties.each do |property|
|
153
|
-
map(property.entity.getId, map).put(property.key, property.previously_commited_value)
|
154
|
-
end
|
155
|
-
map
|
156
|
-
end
|
157
|
-
|
158
|
-
def map(key,map)
|
159
|
-
map.get(key) || add_map(key,map)
|
160
|
-
end
|
161
|
-
|
162
|
-
def add_map(key,map)
|
163
|
-
map.put(key, java.util.HashMap.new)
|
164
|
-
map.get(key)
|
165
|
-
end
|
166
|
-
|
167
|
-
def add(listener)
|
168
|
-
@listeners << listener unless @listeners.include?(listener)
|
169
|
-
end
|
170
|
-
|
171
|
-
def remove(listener)
|
172
|
-
@listeners.delete(listener)
|
173
|
-
end
|
174
|
-
|
175
|
-
def remove_all
|
176
|
-
@listeners = []
|
177
|
-
end
|
178
|
-
|
179
|
-
def print
|
180
|
-
puts "Listeners #{@listeners.size}"
|
181
|
-
@listeners.each {|li| puts " Listener '#{li}'"}
|
182
|
-
end
|
183
|
-
|
184
|
-
def neo4j_started(db)
|
185
|
-
@listeners.each { |li| li.on_neo4j_started(db) if li.respond_to?(:on_neo4j_started) }
|
186
|
-
end
|
187
|
-
|
188
|
-
def neo4j_shutdown(db)
|
189
|
-
@listeners.each { |li| li.on_neo4j_shutdown(db) if li.respond_to?(:on_neo4j_shutdown) }
|
190
|
-
end
|
191
|
-
|
192
|
-
def node_created(node)
|
193
|
-
@listeners.each {|li| li.on_node_created(node) if li.respond_to?(:on_node_created)}
|
194
|
-
end
|
195
|
-
|
196
|
-
def node_deleted(node,old_properties, deleted_relationship_set, deleted_node_identity_map)
|
197
|
-
@listeners.each {|li| li.on_node_deleted(node,old_properties, deleted_relationship_set, deleted_node_identity_map) if li.respond_to?(:on_node_deleted)}
|
198
|
-
end
|
199
|
-
|
200
|
-
def relationship_created(relationship, created_node_identity_map)
|
201
|
-
@listeners.each {|li| li.on_relationship_created(relationship, created_node_identity_map) if li.respond_to?(:on_relationship_created)}
|
202
|
-
end
|
203
|
-
|
204
|
-
def relationship_deleted(relationship, old_props, deleted_relationship_set, deleted_node_identity_map)
|
205
|
-
@listeners.each {|li| li.on_relationship_deleted(relationship, old_props, deleted_relationship_set, deleted_node_identity_map) if li.respond_to?(:on_relationship_deleted)}
|
206
|
-
end
|
207
|
-
|
208
|
-
def property_changed(node, key, old_value, new_value)
|
209
|
-
@listeners.each {|li| li.on_property_changed(node, key, old_value, new_value) if li.respond_to?(:on_property_changed)}
|
210
|
-
end
|
211
|
-
|
212
|
-
def rel_property_changed(rel, key, old_value, new_value)
|
213
|
-
@listeners.each {|li| li.on_rel_property_changed(rel, key, old_value, new_value) if li.respond_to?(:on_rel_property_changed)}
|
214
|
-
end
|
215
|
-
|
216
|
-
def add_deleted_nodes(data, class_change_map, removed_node_properties_map)
|
217
|
-
data.deleted_nodes.each{|node| instance_deleted(node, removed_node_properties_map, class_change_map)}
|
218
|
-
end
|
219
|
-
|
220
|
-
def instance_created(node, class_change_map)
|
221
|
-
classname = node[:_classname]
|
222
|
-
class_change(classname, class_change_map).add(node) if classname
|
223
|
-
end
|
224
|
-
|
225
|
-
def instance_deleted(node, removed_node_properties_map, class_change_map)
|
226
|
-
properties = removed_node_properties_map.get(node.getId)
|
227
|
-
if properties
|
228
|
-
classname = properties.get("_classname")
|
229
|
-
class_change(classname, class_change_map).delete(node) if classname
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
def class_change(classname, class_change_map)
|
234
|
-
class_change_map.put(classname, ClassChanges.new) if class_change_map.get(classname).nil?
|
235
|
-
class_change_map.get(classname)
|
236
|
-
end
|
237
|
-
|
238
|
-
def classes_changed(changed_class_map)
|
239
|
-
@listeners.each {|li| li.classes_changed(changed_class_map) if li.respond_to?(:classes_changed)}
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
class ClassChanges
|
244
|
-
attr_accessor :added, :deleted
|
245
|
-
|
246
|
-
def initialize
|
247
|
-
self.added = []
|
248
|
-
self.deleted = []
|
249
|
-
end
|
250
|
-
|
251
|
-
def add(node)
|
252
|
-
self.added << node
|
253
|
-
end
|
254
|
-
|
255
|
-
def delete(node)
|
256
|
-
self.deleted << node
|
257
|
-
end
|
258
|
-
|
259
|
-
def net_change
|
260
|
-
self.added.size - self.deleted.size
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|