neo4j 1.0.0.beta.28-java → 1.0.0.beta.29-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTORS +1 -0
- data/bin/neo4j-shell +4 -106
- data/lib/neo4j.rb +5 -2
- data/lib/neo4j/batch/batch.rb +2 -0
- data/lib/neo4j/batch/inserter.rb +4 -1
- data/lib/neo4j/batch/rule_inserter.rb +24 -0
- data/lib/neo4j/batch/rule_node.rb +72 -0
- data/lib/neo4j/database.rb +13 -0
- data/lib/neo4j/migrations/node_mixin.rb +1 -1
- data/lib/neo4j/neo4j.rb +27 -0
- data/lib/neo4j/node_mixin/node_mixin.rb +1 -1
- data/lib/neo4j/property/property.rb +1 -1
- data/lib/neo4j/rails/attributes.rb +95 -1
- data/lib/neo4j/rails/model.rb +30 -18
- data/lib/neo4j/rule/class_methods.rb +7 -8
- data/lib/neo4j/rule/event_listener.rb +60 -0
- data/lib/neo4j/rule/rule.rb +127 -2
- data/lib/neo4j/type_converters/type_converters.rb +1 -1
- data/lib/neo4j/version.rb +1 -1
- metadata +5 -3
- data/lib/neo4j/rule/rule_event_listener.rb +0 -162
data/CONTRIBUTORS
CHANGED
data/bin/neo4j-shell
CHANGED
@@ -1,107 +1,5 @@
|
|
1
|
-
#!/bin/
|
2
|
-
# ----------------------------------------------------------------------------
|
3
|
-
# Copyright 2001-2006 The Apache Software Foundation.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
# ----------------------------------------------------------------------------
|
1
|
+
#!/usr/bin/env ruby
|
17
2
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
BASEDIR=`dirname $0`/..
|
22
|
-
BASEDIR=`(cd "$BASEDIR"; pwd)`
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
# OS specific support. $var _must_ be set to either true or false.
|
27
|
-
cygwin=false;
|
28
|
-
darwin=false;
|
29
|
-
case "`uname`" in
|
30
|
-
CYGWIN*) cygwin=true ;;
|
31
|
-
Darwin*) darwin=true
|
32
|
-
if [ -z "$JAVA_VERSION" ] ; then
|
33
|
-
JAVA_VERSION="CurrentJDK"
|
34
|
-
else
|
35
|
-
echo "Using Java version: $JAVA_VERSION"
|
36
|
-
fi
|
37
|
-
if [ -z "$JAVA_HOME" ] ; then
|
38
|
-
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home
|
39
|
-
fi
|
40
|
-
;;
|
41
|
-
esac
|
42
|
-
|
43
|
-
if [ -z "$JAVA_HOME" ] ; then
|
44
|
-
if [ -r /etc/gentoo-release ] ; then
|
45
|
-
JAVA_HOME=`java-config --jre-home`
|
46
|
-
fi
|
47
|
-
fi
|
48
|
-
|
49
|
-
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
50
|
-
if $cygwin ; then
|
51
|
-
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
52
|
-
[ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
53
|
-
fi
|
54
|
-
|
55
|
-
# If a specific java binary isn't specified search for the standard 'java' binary
|
56
|
-
if [ -z "$JAVACMD" ] ; then
|
57
|
-
if [ -n "$JAVA_HOME" ] ; then
|
58
|
-
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
59
|
-
# IBM's JDK on AIX uses strange locations for the executables
|
60
|
-
JAVACMD="$JAVA_HOME/jre/sh/java"
|
61
|
-
else
|
62
|
-
JAVACMD="$JAVA_HOME/bin/java"
|
63
|
-
fi
|
64
|
-
else
|
65
|
-
JAVACMD=`which java`
|
66
|
-
fi
|
67
|
-
fi
|
68
|
-
|
69
|
-
if [ ! -x "$JAVACMD" ] ; then
|
70
|
-
echo "Error: JAVA_HOME is not defined correctly."
|
71
|
-
echo " We cannot execute $JAVACMD"
|
72
|
-
exit 1
|
73
|
-
fi
|
74
|
-
|
75
|
-
if [ -z "$REPO" ]
|
76
|
-
then
|
77
|
-
REPO="$BASEDIR"/lib/neo4j/jars
|
78
|
-
fi
|
79
|
-
|
80
|
-
LIBRARY_JARS=""
|
81
|
-
for jar in $(find $REPO -iname "*.jar")
|
82
|
-
do
|
83
|
-
LIBRARY_JARS=${LIBRARY_JARS}:$jar
|
84
|
-
done
|
85
|
-
|
86
|
-
CLASSPATH=$CLASSPATH_PREFIX${LIBRARY_JARS}
|
87
|
-
|
88
|
-
EXTRA_JVM_ARGUMENTS=""
|
89
|
-
|
90
|
-
# For Cygwin, switch paths to Windows format before running java
|
91
|
-
if $cygwin; then
|
92
|
-
[ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
93
|
-
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
94
|
-
[ -n "$HOME" ] && HOME=`cygpath --path --windows "$HOME"`
|
95
|
-
[ -n "$BASEDIR" ] && BASEDIR=`cygpath --path --windows "$BASEDIR"`
|
96
|
-
[ -n "$REPO" ] && REPO=`cygpath --path --windows "$REPO"`
|
97
|
-
fi
|
98
|
-
|
99
|
-
exec "$JAVACMD" $JAVA_OPTS \
|
100
|
-
$EXTRA_JVM_ARGUMENTS \
|
101
|
-
-classpath "$CLASSPATH" \
|
102
|
-
-Dapp.name="neo4j-shell" \
|
103
|
-
-Dapp.pid="$$" \
|
104
|
-
-Dapp.repo="$REPO" \
|
105
|
-
-Dbasedir="$BASEDIR" \
|
106
|
-
org.neo4j.shell.StartClient \
|
107
|
-
"$@"
|
3
|
+
require 'neo4j'
|
4
|
+
Neo4j.load_shell_jars
|
5
|
+
org.neo4j.shell.StartClient.main(ARGV)
|
data/lib/neo4j.rb
CHANGED
@@ -15,6 +15,7 @@ require 'neo4j/jars/core/geronimo-jta_1.1_spec-1.1.1.jar'
|
|
15
15
|
require 'neo4j/jars/core/lucene-core-3.0.3.jar'
|
16
16
|
require 'neo4j/jars/core/neo4j-lucene-index-0.5-1.3.M01.jar'
|
17
17
|
require 'neo4j/jars/core/neo4j-kernel-1.3-1.3.M01.jar'
|
18
|
+
require 'neo4j/jars/ha/neo4j-management-1.3-1.3.M01.jar'
|
18
19
|
|
19
20
|
module Neo4j
|
20
21
|
|
@@ -24,11 +25,13 @@ module Neo4j
|
|
24
25
|
require 'neo4j/jars/core/neo4j-index-1.3-1.3.M01.jar'
|
25
26
|
end
|
26
27
|
|
28
|
+
def self.load_shell_jars
|
29
|
+
require 'neo4j/jars/ha/neo4j-shell-1.3-1.3.M01.jar'
|
30
|
+
end
|
31
|
+
|
27
32
|
def self.load_ha_jars
|
28
33
|
require 'neo4j/jars/ha/log4j-1.2.16.jar'
|
29
34
|
require 'neo4j/jars/ha/neo4j-ha-0.6-1.3.M01.jar'
|
30
|
-
require 'neo4j/jars/ha/neo4j-management-1.3-1.3.M01.jar'
|
31
|
-
require 'neo4j/jars/ha/neo4j-shell-1.3-1.3.M01.jar'
|
32
35
|
require 'neo4j/jars/ha/netty-3.2.1.Final.jar'
|
33
36
|
require 'neo4j/jars/ha/org.apache.servicemix.bundles.jline-0.9.94_1.jar'
|
34
37
|
require 'neo4j/jars/ha/org.apache.servicemix.bundles.lucene-3.0.1_2.jar'
|
data/lib/neo4j/batch/batch.rb
CHANGED
data/lib/neo4j/batch/inserter.rb
CHANGED
@@ -23,6 +23,7 @@ module Neo4j
|
|
23
23
|
raise "Not allowed to start batch inserter while Neo4j is already running at storage location #{storage_path}" if Neo4j.storage_path == storage_path
|
24
24
|
@batch_inserter = org.neo4j.kernel.impl.batchinsert.BatchInserterImpl.new(storage_path, config)
|
25
25
|
Indexer.index_provider = org.neo4j.index.impl.lucene.LuceneBatchInserterIndexProvider.new(@batch_inserter)
|
26
|
+
@rule_inserter = RuleInserter.new(self)
|
26
27
|
end
|
27
28
|
|
28
29
|
def running?
|
@@ -33,7 +34,8 @@ module Neo4j
|
|
33
34
|
def shutdown
|
34
35
|
@batch_inserter && @batch_inserter.shutdown
|
35
36
|
@batch_inserter = nil
|
36
|
-
|
37
|
+
@rule_inserter = nil
|
38
|
+
|
37
39
|
Indexer.index_provider
|
38
40
|
Indexer.index_provider && Indexer.index_provider.shutdown
|
39
41
|
Indexer.index_provider = nil
|
@@ -48,6 +50,7 @@ module Neo4j
|
|
48
50
|
|
49
51
|
node = @batch_inserter.create_node(props)
|
50
52
|
props && _index(node, props, clazz)
|
53
|
+
@rule_inserter.node_added(node, props)
|
51
54
|
node
|
52
55
|
end
|
53
56
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Batch
|
3
|
+
class RuleInserter #:nodoc:
|
4
|
+
def initialize(inserter)
|
5
|
+
@inserter = inserter
|
6
|
+
end
|
7
|
+
|
8
|
+
def node_added(node, props)
|
9
|
+
classname = props && props['_classname']
|
10
|
+
classname && create_rules(node, props, classname)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def create_rules(node, props, classname)
|
15
|
+
rule_node = RuleNode.rule_node_for(classname, @inserter)
|
16
|
+
rule_node && rule_node.execute_rules(@inserter, node, props)
|
17
|
+
|
18
|
+
if (clazz = eval("#{classname}.superclass")) && clazz.include?(Neo4j::NodeMixin)
|
19
|
+
create_rules(node, props, clazz.to_s)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Batch
|
3
|
+
class RuleNode #:nodoc:
|
4
|
+
attr_reader :node
|
5
|
+
delegate :rules, :to => :@wrapped_rule_node
|
6
|
+
|
7
|
+
def initialize(wrapped_rule_node, node)
|
8
|
+
@wrapped_rule_node = wrapped_rule_node
|
9
|
+
@node = node
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute_rules(inserter, node, props)
|
13
|
+
rules.each do |rule|
|
14
|
+
if execute_filter(rule, props)
|
15
|
+
inserter.create_rel(rule.rule_name, @node, node)
|
16
|
+
execute_add_functions(inserter, rule, props)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute_add_functions(inserter, rule, props)
|
22
|
+
rule_props = nil
|
23
|
+
executed_functions = []
|
24
|
+
props.keys.each do |key|
|
25
|
+
functions = rule.functions_for(key)
|
26
|
+
next unless functions
|
27
|
+
functions -= executed_functions
|
28
|
+
rule_props ||= clone_node_props(inserter) #inserter.node_props(@node)
|
29
|
+
functions.each { |f| executed_functions << f; f.add(rule.rule_name, rule_props, props[key]) }
|
30
|
+
end
|
31
|
+
rule_props && inserter.set_node_props(@node, rule_props)
|
32
|
+
end
|
33
|
+
|
34
|
+
def clone_node_props(inserter)
|
35
|
+
hash = {}
|
36
|
+
props = inserter.node_props(@node) # need to clone this since we can't modify it
|
37
|
+
props.each_pair{|k,v| hash[k]=v}
|
38
|
+
hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def execute_filter(rule, props)
|
42
|
+
if rule.filter.nil?
|
43
|
+
true
|
44
|
+
elsif rule.filter.arity != 1
|
45
|
+
classname = props['_classname'] || 'Neo4j::Node'
|
46
|
+
clazz = Neo4j::Node.to_class(classname)
|
47
|
+
wrapper = clazz.load_wrapper(ActiveSupport::HashWithIndifferentAccess.new(props))
|
48
|
+
wrapper.instance_eval(&rule.filter)
|
49
|
+
else
|
50
|
+
rule.filter.call(ActiveSupport::HashWithIndifferentAccess.new(props))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
def rule_node_for(classname, inserter)
|
56
|
+
return nil unless Neo4j::Rule::Rule.has_rules?(classname)
|
57
|
+
wrapped_rule_node = Neo4j::Rule::Rule.rule_node_for(classname)
|
58
|
+
@rule_nodes ||= {}
|
59
|
+
@rule_nodes[classname] ||= RuleNode.new(wrapped_rule_node, create_node(classname, inserter))
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_node(classname, inserter)
|
63
|
+
rule_node = inserter.create_node
|
64
|
+
inserter.create_rel(classname, inserter.ref_node, rule_node)
|
65
|
+
rule_node
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/neo4j/database.rb
CHANGED
@@ -22,6 +22,12 @@ module Neo4j
|
|
22
22
|
@running = true
|
23
23
|
@storage_path = Config.storage_path
|
24
24
|
|
25
|
+
|
26
|
+
if Config[:enable_remote_shell]
|
27
|
+
Neo4j.logger.info("Enable remote shell at port #{Config[:enable_remote_shell]}")
|
28
|
+
Neo4j.load_shell_jars
|
29
|
+
end
|
30
|
+
|
25
31
|
begin
|
26
32
|
if self.class.locked?
|
27
33
|
start_readonly_graph_db
|
@@ -96,10 +102,17 @@ module Neo4j
|
|
96
102
|
@graph = nil
|
97
103
|
@lucene = nil
|
98
104
|
@running = false
|
105
|
+
@neo4j_manager = nil
|
99
106
|
end
|
100
107
|
|
101
108
|
end
|
102
109
|
|
110
|
+
|
111
|
+
def management(jmx_clazz) #:nodoc:
|
112
|
+
@neo4j_manager ||= org.neo4j.management.Neo4jManager.new(@graph.get_management_bean(org.neo4j.management.Kernel.java_class))
|
113
|
+
@neo4j_manager.getBean(jmx_clazz.java_class)
|
114
|
+
end
|
115
|
+
|
103
116
|
def begin_tx #:nodoc:
|
104
117
|
@graph.begin_tx
|
105
118
|
end
|
@@ -48,7 +48,7 @@ module Neo4j
|
|
48
48
|
|
49
49
|
# The node that holds the db version property
|
50
50
|
def migration_meta_node
|
51
|
-
Neo4j::Rule::
|
51
|
+
Neo4j::Rule::Rule.rule_node_for(self).rule_node
|
52
52
|
end
|
53
53
|
|
54
54
|
# Remote all migration and set migrate_to = nil and set the current version to nil
|
data/lib/neo4j/neo4j.rb
CHANGED
@@ -110,6 +110,33 @@ module Neo4j
|
|
110
110
|
this_db.graph.reference_node
|
111
111
|
end
|
112
112
|
|
113
|
+
# Returns a Management JMX Bean.
|
114
|
+
#
|
115
|
+
# Notice that this information is also provided by the jconsole Java tool, check http://wiki.neo4j.org/content/Monitoring_and_Deployment
|
116
|
+
# and http://docs.neo4j.org/chunked/milestone/operations-monitoring.html
|
117
|
+
#
|
118
|
+
# By default it returns the Primitivies JMX Bean that can be used to find number of nodes in use.
|
119
|
+
#
|
120
|
+
# ==== Example Neo4j Primititives
|
121
|
+
#
|
122
|
+
# Neo4j.management.get_number_of_node_ids_in_use
|
123
|
+
# Neo4j.management.getNumberOfPropertyIdsInUse
|
124
|
+
# Neo4j.management.getNumberOfRelationshipIdsInUse
|
125
|
+
# Neo4j.management.get_number_of_relationship_type_ids_in_use
|
126
|
+
#
|
127
|
+
# ==== Example Neo4j HA Cluster Info
|
128
|
+
#
|
129
|
+
# Neo4j.management(org.neo4j.management.HighAvailability).isMaster
|
130
|
+
#
|
131
|
+
# ==== Arguments
|
132
|
+
#
|
133
|
+
# jmx_clazz :: http://api.neo4j.org/current/org/neo4j/management/package-summary.html
|
134
|
+
# this_db :: default currently runnig instance or a newly started neo4j db instance
|
135
|
+
#
|
136
|
+
def management(jmx_clazz = org.neo4j.management.Primitives, this_db = self.started_db)
|
137
|
+
this_db.management(jmx_clazz)
|
138
|
+
end
|
139
|
+
|
113
140
|
# Returns an Enumerable object for all nodes in the database
|
114
141
|
def all_nodes(this_db = self.started_db)
|
115
142
|
Enumerator.new(this_db, :each_node)
|
@@ -78,7 +78,7 @@ module Neo4j
|
|
78
78
|
|
79
79
|
# Trigger rules.
|
80
80
|
# You don't normally need to call this method (except in Migration) since
|
81
|
-
# it will be triggered automatically by the Neo4j::Rule::
|
81
|
+
# it will be triggered automatically by the Neo4j::Rule::Rule
|
82
82
|
#
|
83
83
|
def trigger_rules
|
84
84
|
self.class.trigger_rules(self)
|
@@ -57,7 +57,101 @@ module Neo4j
|
|
57
57
|
# Mass-assign attributes. Stops any protected attributes from being assigned.
|
58
58
|
def attributes=(attributes, guard_protected_attributes = true)
|
59
59
|
attributes = sanitize_for_mass_assignment(attributes) if guard_protected_attributes
|
60
|
-
|
60
|
+
|
61
|
+
multi_parameter_attributes = []
|
62
|
+
attributes.each do |k, v|
|
63
|
+
if k.to_s.include?("(")
|
64
|
+
multi_parameter_attributes << [ k, v ]
|
65
|
+
else
|
66
|
+
respond_to?("#{k}=") ? send("#{k}=", v) : self[k] = v
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
assign_multiparameter_attributes(multi_parameter_attributes)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
74
|
+
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
75
|
+
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
76
|
+
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
77
|
+
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum,
|
78
|
+
# f for Float, s for String, and a for Array. If all the values for a given attribute are empty, the
|
79
|
+
# attribute will be set to nil.
|
80
|
+
def assign_multiparameter_attributes(pairs)
|
81
|
+
execute_callstack_for_multiparameter_attributes(
|
82
|
+
extract_callstack_for_multiparameter_attributes(pairs)
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def execute_callstack_for_multiparameter_attributes(callstack)
|
87
|
+
errors = []
|
88
|
+
callstack.each do |name, values_with_empty_parameters|
|
89
|
+
begin
|
90
|
+
# (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
|
91
|
+
klass = self.class._decl_props[name.to_sym][:type]
|
92
|
+
raise "Not a multiparameter attribute, missing :type on property #{name} for #{self.class}" unless klass
|
93
|
+
|
94
|
+
# in order to allow a date to be set without a year, we must keep the empty values.
|
95
|
+
values = values_with_empty_parameters.reject { |v| v.nil? }
|
96
|
+
|
97
|
+
if values.empty?
|
98
|
+
send(name + "=", nil)
|
99
|
+
else
|
100
|
+
|
101
|
+
value = if Time == klass
|
102
|
+
instantiate_time_object(name, values)
|
103
|
+
elsif Date == klass
|
104
|
+
begin
|
105
|
+
values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
|
106
|
+
Date.new(*values)
|
107
|
+
rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
|
108
|
+
instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
109
|
+
end
|
110
|
+
else
|
111
|
+
klass.new(*values)
|
112
|
+
end
|
113
|
+
|
114
|
+
send(name + "=", value)
|
115
|
+
end
|
116
|
+
rescue Exception => ex
|
117
|
+
raise "error on assignment #{values.inspect} to #{name}, ex: #{ex}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
unless errors.empty?
|
121
|
+
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def instantiate_time_object(name, values)
|
126
|
+
# if self.class.send(:create_time_zone_conversion_attribute?, name, column_for_attribute(name))
|
127
|
+
# Time.zone.local(*values)
|
128
|
+
# else
|
129
|
+
Time.time_with_datetime_fallback(self.class.default_timezone, *values)
|
130
|
+
# end
|
131
|
+
end
|
132
|
+
|
133
|
+
def extract_callstack_for_multiparameter_attributes(pairs)
|
134
|
+
attributes = { }
|
135
|
+
|
136
|
+
for pair in pairs
|
137
|
+
multiparameter_name, value = pair
|
138
|
+
attribute_name = multiparameter_name.split("(").first
|
139
|
+
attributes[attribute_name] = [] unless attributes.include?(attribute_name)
|
140
|
+
|
141
|
+
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
142
|
+
attributes[attribute_name] << [ find_parameter_position(multiparameter_name), parameter_value ]
|
143
|
+
end
|
144
|
+
|
145
|
+
attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def type_cast_attribute_value(multiparameter_name, value)
|
150
|
+
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
151
|
+
end
|
152
|
+
|
153
|
+
def find_parameter_position(multiparameter_name)
|
154
|
+
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first
|
61
155
|
end
|
62
156
|
|
63
157
|
# Tracks the current changes and clears the changed attributes hash. Called
|
data/lib/neo4j/rails/model.rb
CHANGED
@@ -2,10 +2,10 @@ module Neo4j
|
|
2
2
|
module Rails
|
3
3
|
class Model
|
4
4
|
include Neo4j::NodeMixin
|
5
|
-
|
5
|
+
|
6
6
|
# Initialize a Node with a set of properties (or empty if nothing is passed)
|
7
7
|
def initialize(attributes = {})
|
8
|
-
|
8
|
+
reset_attributes
|
9
9
|
clear_relationships
|
10
10
|
self.attributes = attributes if attributes.is_a?(Hash)
|
11
11
|
end
|
@@ -39,9 +39,10 @@ module Neo4j
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def ==(other)
|
42
|
-
|
42
|
+
new? ? self.__id__ == other.__id__ : @_java_node == (other)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
|
+
|
45
46
|
# --------------------------------------
|
46
47
|
# Public Class Methods
|
47
48
|
# --------------------------------------
|
@@ -49,11 +50,22 @@ module Neo4j
|
|
49
50
|
# NodeMixin overwrites the #new class method but it saves it as orig_new
|
50
51
|
# Here, we just get it back to normal
|
51
52
|
alias :new :orig_new
|
52
|
-
|
53
|
+
|
53
54
|
def transaction(&block)
|
54
55
|
Neo4j::Rails::Transaction.run do |tx|
|
55
56
|
block.call(tx)
|
56
|
-
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling
|
62
|
+
# dates and times from the database. This is set to :local by default.
|
63
|
+
def default_timezone
|
64
|
+
@default_timezone || :local
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_timezone=(zone)
|
68
|
+
@default_timezone = zone
|
57
69
|
end
|
58
70
|
|
59
71
|
def accepts_nested_attributes_for(*attr_names)
|
@@ -87,19 +99,19 @@ module Neo4j
|
|
87
99
|
end
|
88
100
|
end
|
89
101
|
end
|
90
|
-
|
102
|
+
|
91
103
|
Model.class_eval do
|
92
|
-
|
93
|
-
|
94
|
-
include Persistence
|
95
|
-
include Attributes
|
96
|
-
include Mapping::Property
|
97
|
-
include Serialization
|
98
|
-
include Timestamps
|
99
|
-
include Validations
|
100
|
-
include Callbacks
|
101
|
-
include Finders
|
102
|
-
include Relationships
|
104
|
+
extend ActiveModel::Translation
|
105
|
+
|
106
|
+
include Persistence # handles how to save, create and update the model
|
107
|
+
include Attributes # handles how to save and retrieve attributes
|
108
|
+
include Mapping::Property # allows some additional options on the #property class method
|
109
|
+
include Serialization # enable to_xml and to_json
|
110
|
+
include Timestamps # handle created_at, updated_at timestamp properties
|
111
|
+
include Validations # enable validations
|
112
|
+
include Callbacks # enable callbacks
|
113
|
+
include Finders # ActiveRecord style find
|
114
|
+
include Relationships # for none persisted relationships
|
103
115
|
end
|
104
116
|
end
|
105
117
|
end
|
@@ -102,7 +102,7 @@ module Neo4j
|
|
102
102
|
|
103
103
|
# define class methods
|
104
104
|
singleton.send(:define_method, rule_name) do
|
105
|
-
rule_node =
|
105
|
+
rule_node = Rule.rule_node_for(self)
|
106
106
|
rule_node.traversal(rule_name)
|
107
107
|
end unless respond_to?(rule_name)
|
108
108
|
|
@@ -111,11 +111,11 @@ module Neo4j
|
|
111
111
|
instance_eval &block
|
112
112
|
end
|
113
113
|
|
114
|
-
rule =
|
114
|
+
rule = Rule.add(self, rule_name, props, &block)
|
115
115
|
|
116
116
|
rule.functions && rule.functions.each do |func|
|
117
117
|
singleton.send(:define_method, func.class.function_name) do |r_name, *args|
|
118
|
-
rule_node =
|
118
|
+
rule_node = Rule.rule_node_for(self)
|
119
119
|
function_id = args.empty? ? "_classname" : args[0]
|
120
120
|
function = rule_node.find_function(r_name, func.class.function_name, function_id)
|
121
121
|
function.value(rule_node.rule_node, r_name)
|
@@ -124,7 +124,7 @@ module Neo4j
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def inherit_rules_from(clazz)
|
127
|
-
|
127
|
+
Rule.inherit(clazz, self)
|
128
128
|
end
|
129
129
|
|
130
130
|
# This is typically used for RSpecs to clean up rule nodes created by the #rule method.
|
@@ -133,7 +133,7 @@ module Neo4j
|
|
133
133
|
singelton = class << self;
|
134
134
|
self;
|
135
135
|
end
|
136
|
-
rule_node =
|
136
|
+
rule_node = Rule.rule_node_for(self)
|
137
137
|
|
138
138
|
rule_node.rule_names.each {|rule_name| singelton.send(:remove_method, rule_name)}
|
139
139
|
rule_node.rules.clear
|
@@ -145,7 +145,7 @@ module Neo4j
|
|
145
145
|
# Can also be called from an migration.
|
146
146
|
#
|
147
147
|
def trigger_rules(node, *changes)
|
148
|
-
|
148
|
+
Rule.trigger_rules(node, *changes)
|
149
149
|
end
|
150
150
|
|
151
151
|
# Returns a proc that will call add method on the given function
|
@@ -167,7 +167,7 @@ module Neo4j
|
|
167
167
|
# Returns a proc that calls the given method on the given function.
|
168
168
|
def function_for(method, rule_name, function_name_or_class, function_id = '_classname')
|
169
169
|
function_name = function_name_or_class.is_a?(Symbol)? function_name_or_class : function_name_or_class.function_name
|
170
|
-
rule_node =
|
170
|
+
rule_node = Rule.rule_node_for(self)
|
171
171
|
rule = rule_node.find_rule(rule_name)
|
172
172
|
rule_node_raw = rule_node.rule_node
|
173
173
|
|
@@ -179,6 +179,5 @@ module Neo4j
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
-
Neo4j.unstarted_db.event_handler.add(RuleEventListener) unless Neo4j.read_only?
|
183
182
|
end
|
184
183
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rule
|
3
|
+
class EventListener
|
4
|
+
class << self
|
5
|
+
# ----------------------------------------------------------------------------------------------------------------
|
6
|
+
# Event handling methods
|
7
|
+
# ----------------------------------------------------------------------------------------------------------------
|
8
|
+
|
9
|
+
def on_relationship_created(rel, *)
|
10
|
+
trigger_start_node = Rule.trigger?(rel._start_node)
|
11
|
+
trigger_end_node = Rule.trigger?(rel._end_node)
|
12
|
+
Rule.trigger_rules(rel._start_node) if trigger_start_node
|
13
|
+
Rule.trigger_rules(rel._end_node) if trigger_end_node
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_property_changed(node, *changes)
|
17
|
+
Rule.trigger_rules(node, *changes) if Rule.trigger?(node)
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_node_deleted(node, old_properties, data)
|
21
|
+
# have we deleted a rule node ?
|
22
|
+
del_rule_node = Rule.find_rule_node(node)
|
23
|
+
del_rule_node && del_rule_node.clear_rule_node
|
24
|
+
return if del_rule_node
|
25
|
+
|
26
|
+
# do we have prop_aggregations for this
|
27
|
+
clazz = old_properties['_classname']
|
28
|
+
rule_node = Rule.rule_node_for(clazz)
|
29
|
+
return if rule_node.nil?
|
30
|
+
|
31
|
+
id = node.getId
|
32
|
+
rule_node.rules.each do |rule|
|
33
|
+
next if rule.functions.nil?
|
34
|
+
rule_name = rule.rule_name.to_s
|
35
|
+
|
36
|
+
# is the rule node deleted ?
|
37
|
+
deleted_rule_node = data.deletedNodes.find { |n| n == rule_node.rule_node }
|
38
|
+
next if deleted_rule_node
|
39
|
+
|
40
|
+
rule.functions.each do |function|
|
41
|
+
next unless data.deletedRelationships.find do |r|
|
42
|
+
r.getEndNode().getId() == id && r.rel_type == rule_name
|
43
|
+
end
|
44
|
+
previous_value = old_properties[function.function_id]
|
45
|
+
function.delete(rule_name, rule_node.rule_node, previous_value) if previous_value
|
46
|
+
end if rule.functions
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def on_neo4j_started(*)
|
51
|
+
Rule.on_neo4j_started
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
Neo4j.unstarted_db.event_handler.add(EventListener) unless Neo4j.read_only?
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
data/lib/neo4j/rule/rule.rb
CHANGED
@@ -1,5 +1,130 @@
|
|
1
|
-
require 'neo4j/rule/
|
1
|
+
require 'neo4j/rule/event_listener'
|
2
2
|
require 'neo4j/rule/class_methods'
|
3
3
|
require 'neo4j/rule/rule_node'
|
4
4
|
|
5
|
-
require 'neo4j/rule/functions/functions'
|
5
|
+
require 'neo4j/rule/functions/functions'
|
6
|
+
|
7
|
+
|
8
|
+
module Neo4j
|
9
|
+
module Rule
|
10
|
+
|
11
|
+
|
12
|
+
# Holds all defined rules added by the Neo4j::Rule::ClassMethods#rule method.
|
13
|
+
#
|
14
|
+
# See Neo4j::Rule::ClassMethods
|
15
|
+
#
|
16
|
+
class Rule
|
17
|
+
|
18
|
+
attr_reader :rule_name, :filter, :triggers, :functions
|
19
|
+
|
20
|
+
def initialize(rule_name, props, &block)
|
21
|
+
@rule_name = rule_name
|
22
|
+
@triggers = props[:triggers]
|
23
|
+
@functions = props[:functions]
|
24
|
+
@triggers = [@triggers] if @triggers && !@triggers.respond_to?(:each)
|
25
|
+
@functions = [@functions] if @functions && !@functions.respond_to?(:each)
|
26
|
+
@filter = block
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"Rule #{rule_name} props=#{props.inspect}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_function(function_name, function_id)
|
34
|
+
function_id = function_id.to_s
|
35
|
+
@functions && @functions.find { |f| f.function_id == function_id && f.class.function_name == function_name }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Reconstruct the properties given when created this rule
|
39
|
+
# Needed when inheriting a rule and we want to duplicate a rule
|
40
|
+
def props
|
41
|
+
props = {}
|
42
|
+
props[:triggers] = @triggers if @triggers
|
43
|
+
props[:functions] = @functions if @functions
|
44
|
+
props
|
45
|
+
end
|
46
|
+
|
47
|
+
def functions_for(property)
|
48
|
+
@functions && @functions.find_all { |f| f.calculate?(property) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def execute_filter(node)
|
52
|
+
if @filter.nil?
|
53
|
+
true
|
54
|
+
elsif @filter.arity != 1
|
55
|
+
node.wrapper.instance_eval(&@filter)
|
56
|
+
else
|
57
|
+
@filter.call(node)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# ------------------------------------------------------------------------------------------------------------------
|
62
|
+
# Class Methods
|
63
|
+
# ------------------------------------------------------------------------------------------------------------------
|
64
|
+
|
65
|
+
class << self
|
66
|
+
def add(clazz, rule_name, props, &block)
|
67
|
+
rule_node = rule_node_for(clazz.to_s)
|
68
|
+
rule_node.remove_rule(rule_name) # remove any previously inherited rules
|
69
|
+
rule = Rule.new(rule_name, props, &block)
|
70
|
+
rule_node.add_rule(rule)
|
71
|
+
rule
|
72
|
+
end
|
73
|
+
|
74
|
+
def has_rules?(clazz)
|
75
|
+
!@rule_nodes[clazz.to_s].nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
def rule_names_for(clazz)
|
79
|
+
rule_node = rule_node_for(clazz)
|
80
|
+
rule_node.rules.map { |rule| rule.rule_name }
|
81
|
+
end
|
82
|
+
|
83
|
+
def rule_node_for(clazz)
|
84
|
+
return nil if clazz.nil?
|
85
|
+
@rule_nodes ||= {}
|
86
|
+
@rule_nodes[clazz.to_s] ||= RuleNode.new(clazz)
|
87
|
+
end
|
88
|
+
|
89
|
+
def find_rule_node(node)
|
90
|
+
@rule_nodes && @rule_nodes.values.find { |rn| rn.rule_node?(node) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def on_neo4j_started
|
94
|
+
@rule_nodes.each_value { |rule_node| rule_node.on_neo4j_started } if @rule_nodes
|
95
|
+
end
|
96
|
+
|
97
|
+
def inherit(parent_class, subclass)
|
98
|
+
# copy all the rules
|
99
|
+
if rule_node = rule_node_for(parent_class)
|
100
|
+
rule_node.inherit(subclass)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def delete(clazz)
|
105
|
+
if rule_node = rule_node_for(clazz)
|
106
|
+
rule_node.delete_node
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def trigger?(node)
|
111
|
+
classname = node[:_classname]
|
112
|
+
@rule_nodes && classname && rule_node_for(classname)
|
113
|
+
end
|
114
|
+
|
115
|
+
def trigger_rules(node, *changes)
|
116
|
+
classname = node[:_classname]
|
117
|
+
return unless classname # there are no rules if there is not a :_classname property
|
118
|
+
rule_node = rule_node_for(classname)
|
119
|
+
rule_node.execute_rules(node, *changes)
|
120
|
+
|
121
|
+
# recursively add relationships for all the parent classes with rules that also pass for this node
|
122
|
+
if (clazz = eval("#{classname}.superclass")) && clazz.include?(Neo4j::NodeMixin)
|
123
|
+
rule_node = rule_node_for(clazz)
|
124
|
+
rule_node && rule_node.execute_rules(node, *changes)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/neo4j/version.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: neo4j
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 6
|
5
|
-
version: 1.0.0.beta.
|
5
|
+
version: 1.0.0.beta.29
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Andreas Ronge
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-02-
|
13
|
+
date: 2011-02-10 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -154,6 +154,8 @@ files:
|
|
154
154
|
- lib/neo4j/index/index.rb
|
155
155
|
- lib/neo4j/batch/inserter.rb
|
156
156
|
- lib/neo4j/batch/indexer.rb
|
157
|
+
- lib/neo4j/batch/rule_inserter.rb
|
158
|
+
- lib/neo4j/batch/rule_node.rb
|
157
159
|
- lib/neo4j/batch/batch.rb
|
158
160
|
- lib/neo4j/has_n/decl_relationship_dsl.rb
|
159
161
|
- lib/neo4j/has_n/has_n.rb
|
@@ -164,7 +166,7 @@ files:
|
|
164
166
|
- lib/neo4j/rule/rule.rb
|
165
167
|
- lib/neo4j/rule/rule_node.rb
|
166
168
|
- lib/neo4j/rule/class_methods.rb
|
167
|
-
- lib/neo4j/rule/
|
169
|
+
- lib/neo4j/rule/event_listener.rb
|
168
170
|
- lib/neo4j/rule/functions/function.rb
|
169
171
|
- lib/neo4j/rule/functions/count.rb
|
170
172
|
- lib/neo4j/rule/functions/sum.rb
|
@@ -1,162 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Rule
|
3
|
-
|
4
|
-
|
5
|
-
# Holds all defined rules and trigger them when an event is received.
|
6
|
-
#
|
7
|
-
# See Neo4j::Rule::ClassMethods
|
8
|
-
#
|
9
|
-
class RuleEventListener #:nodoc:
|
10
|
-
|
11
|
-
attr_reader :rule_name, :filter, :triggers, :functions
|
12
|
-
|
13
|
-
def initialize(rule_name, props, &block)
|
14
|
-
@rule_name = rule_name
|
15
|
-
@triggers = props[:triggers]
|
16
|
-
@functions = props[:functions]
|
17
|
-
@triggers = [@triggers] if @triggers && !@triggers.respond_to?(:each)
|
18
|
-
@functions = [@functions] if @functions && !@functions.respond_to?(:each)
|
19
|
-
@filter = block
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_s
|
23
|
-
"RuleEventListener #{rule_name} props=#{props.inspect}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def find_function(function_name, function_id)
|
27
|
-
function_id = function_id.to_s
|
28
|
-
@functions && @functions.find { |f| f.function_id == function_id && f.class.function_name == function_name }
|
29
|
-
end
|
30
|
-
|
31
|
-
# Reconstruct the properties given when created this rule
|
32
|
-
# Needed when inheriting a rule and we want to duplicate a rule
|
33
|
-
def props
|
34
|
-
props = {}
|
35
|
-
props[:triggers] = @triggers if @triggers
|
36
|
-
props[:functions] = @functions if @functions
|
37
|
-
props
|
38
|
-
end
|
39
|
-
|
40
|
-
def functions_for(property)
|
41
|
-
@functions && @functions.find_all { |f| f.calculate?(property) }
|
42
|
-
end
|
43
|
-
|
44
|
-
def execute_filter(node)
|
45
|
-
if @filter.nil?
|
46
|
-
true
|
47
|
-
elsif @filter.arity != 1
|
48
|
-
node.wrapper.instance_eval(&@filter)
|
49
|
-
else
|
50
|
-
@filter.call(node)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# ------------------------------------------------------------------------------------------------------------------
|
55
|
-
# Class Methods
|
56
|
-
# ------------------------------------------------------------------------------------------------------------------
|
57
|
-
|
58
|
-
class << self
|
59
|
-
def add(clazz, rule_name, props, &block)
|
60
|
-
rule_node = rule_node_for(clazz.to_s)
|
61
|
-
rule_node.remove_rule(rule_name) # remove any previously inherited rules
|
62
|
-
rule = RuleEventListener.new(rule_name, props, &block)
|
63
|
-
rule_node.add_rule(rule)
|
64
|
-
rule
|
65
|
-
end
|
66
|
-
|
67
|
-
def rule_names_for(clazz)
|
68
|
-
rule_node = rule_node_for(clazz)
|
69
|
-
rule_node.rules.map { |rule| rule.rule_name }
|
70
|
-
end
|
71
|
-
|
72
|
-
def rule_node_for(clazz)
|
73
|
-
return nil if clazz.nil?
|
74
|
-
@rule_nodes ||= {}
|
75
|
-
@rule_nodes[clazz.to_s] ||= RuleNode.new(clazz)
|
76
|
-
end
|
77
|
-
|
78
|
-
def inherit(parent_class, subclass)
|
79
|
-
# copy all the rules
|
80
|
-
if rule_node = rule_node_for(parent_class)
|
81
|
-
rule_node.inherit(subclass)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def delete(clazz)
|
86
|
-
if rule_node = rule_node_for(clazz)
|
87
|
-
rule_node.delete_node
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def trigger?(node)
|
92
|
-
classname = node[:_classname]
|
93
|
-
@rule_nodes && classname && rule_node_for(classname)
|
94
|
-
end
|
95
|
-
|
96
|
-
def trigger_rules(node, *changes)
|
97
|
-
classname = node[:_classname]
|
98
|
-
return unless classname # there are no rules if there is not a :_classname property
|
99
|
-
rule_node = rule_node_for(classname)
|
100
|
-
rule_node.execute_rules(node, *changes)
|
101
|
-
|
102
|
-
# recursively add relationships for all the parent classes with rules that also pass for this node
|
103
|
-
if (clazz = eval("#{classname}.superclass")) && clazz.include?(Neo4j::NodeMixin)
|
104
|
-
rule_node = rule_node_for(clazz)
|
105
|
-
rule_node && rule_node.execute_rules(node, *changes)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
# ----------------------------------------------------------------------------------------------------------------
|
111
|
-
# Event handling methods
|
112
|
-
# ----------------------------------------------------------------------------------------------------------------
|
113
|
-
|
114
|
-
def on_relationship_created(rel, *)
|
115
|
-
trigger_start_node = trigger?(rel._start_node)
|
116
|
-
trigger_end_node = trigger?(rel._end_node)
|
117
|
-
trigger_rules(rel._start_node) if trigger_start_node
|
118
|
-
trigger_rules(rel._end_node) if trigger_end_node
|
119
|
-
end
|
120
|
-
|
121
|
-
def on_property_changed(node, *changes)
|
122
|
-
trigger_rules(node, *changes) if trigger?(node)
|
123
|
-
end
|
124
|
-
|
125
|
-
def on_node_deleted(node, old_properties, data)
|
126
|
-
# have we deleted a rule node ?
|
127
|
-
del_rule_node = @rule_nodes && @rule_nodes.values.find { |rn| rn.rule_node?(node) }
|
128
|
-
del_rule_node && del_rule_node.clear_rule_node
|
129
|
-
return if del_rule_node
|
130
|
-
|
131
|
-
# do we have prop_aggregations for this
|
132
|
-
clazz = old_properties['_classname']
|
133
|
-
rule_node = rule_node_for(clazz)
|
134
|
-
return if rule_node.nil?
|
135
|
-
|
136
|
-
id = node.getId
|
137
|
-
rule_node.rules.each do |rule|
|
138
|
-
next if rule.functions.nil?
|
139
|
-
rule_name = rule.rule_name.to_s
|
140
|
-
|
141
|
-
# is the rule node deleted ?
|
142
|
-
deleted_rule_node = data.deletedNodes.find { |n| n == rule_node.rule_node }
|
143
|
-
next if deleted_rule_node
|
144
|
-
|
145
|
-
rule.functions.each do |function|
|
146
|
-
next unless data.deletedRelationships.find do |r|
|
147
|
-
r.getEndNode().getId() == id && r.rel_type == rule_name
|
148
|
-
end
|
149
|
-
previous_value = old_properties[function.function_id]
|
150
|
-
function.delete(rule_name, rule_node.rule_node, previous_value) if previous_value
|
151
|
-
end if rule.functions
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def on_neo4j_started(*)
|
156
|
-
@rule_nodes.each_value { |rule_node| rule_node.on_neo4j_started } if @rule_nodes
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|