neo4j 1.0.0.beta.28-java → 1.0.0.beta.29-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 CHANGED
@@ -2,6 +2,7 @@ Maintainer:
2
2
  Andreas Ronge <andreas dot ronge at gmail dot com>
3
3
 
4
4
  Contributors:
5
+ * Stephan Hagemann
5
6
  * Bobby Calderwood
6
7
  * Ben Jackson
7
8
  * Dwight van Tuyl
data/bin/neo4j-shell CHANGED
@@ -1,107 +1,5 @@
1
- #!/bin/sh
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
- # Copyright (c) 2001-2002 The Apache Software Foundation. All rights
19
- # reserved.
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'
@@ -1,2 +1,4 @@
1
1
  require 'neo4j/batch/inserter'
2
2
  require 'neo4j/batch/indexer'
3
+ require 'neo4j/batch/rule_inserter'
4
+ require 'neo4j/batch/rule_node'
@@ -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
@@ -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::RuleEventListener.rule_node_for(self).rule_node
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::RuleEventListener
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)
@@ -64,7 +64,7 @@ module Neo4j
64
64
  self[key] = value
65
65
  end
66
66
  end
67
- keys_to_delete.each { |key| delete_property(key) } if strict
67
+ keys_to_delete.each { |key| remove_property(key) } if strict
68
68
  self
69
69
  end
70
70
 
@@ -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
- attributes.each { |k, v| respond_to?("#{k}=") ? send("#{k}=", v) : self[k] = v }
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
@@ -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
- reset_attributes
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
- new? ? self.__id__ == other.__id__ : @_java_node == (other)
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
- extend ActiveModel::Translation
93
-
94
- include Persistence # handles how to save, create and update the model
95
- include Attributes # handles how to save and retrieve attributes
96
- include Mapping::Property # allows some additional options on the #property class method
97
- include Serialization # enable to_xml and to_json
98
- include Timestamps # handle created_at, updated_at timestamp properties
99
- include Validations # enable validations
100
- include Callbacks # enable callbacks
101
- include Finders # ActiveRecord style find
102
- include Relationships # for none persisted 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 = RuleEventListener.rule_node_for(self)
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 = RuleEventListener.add(self, rule_name, props, &block)
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 = RuleEventListener.rule_node_for(self)
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
- RuleEventListener.inherit(clazz, self)
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 = RuleEventListener.rule_node_for(self)
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
- RuleEventListener.trigger_rules(node, *changes)
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 = RuleEventListener.rule_node_for(self)
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
@@ -1,5 +1,130 @@
1
- require 'neo4j/rule/rule_event_listener'
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
@@ -65,7 +65,7 @@ module Neo4j
65
65
 
66
66
  def to_ruby(value)
67
67
  return nil if value.nil?
68
- Time.at(value).utc
68
+ Time.at(value).utc.to_date
69
69
  end
70
70
  end
71
71
  end
data/lib/neo4j/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = "1.0.0.beta.28"
2
+ VERSION = "1.0.0.beta.29"
3
3
  end
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.28
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-02 00:00:00 +01:00
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/rule_event_listener.rb
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