neo4j 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/CHANGELOG +141 -0
  2. data/CONTRIBUTORS +15 -0
  3. data/Gemfile +3 -0
  4. data/README.rdoc +2015 -0
  5. data/lib/neo4j.old/batch_inserter.rb +144 -0
  6. data/lib/neo4j.old/config.rb +138 -0
  7. data/lib/neo4j.old/event_handler.rb +73 -0
  8. data/lib/neo4j.old/extensions/activemodel.rb +158 -0
  9. data/lib/neo4j.old/extensions/aggregate.rb +12 -0
  10. data/lib/neo4j.old/extensions/aggregate/aggregate_enum.rb +40 -0
  11. data/lib/neo4j.old/extensions/aggregate/ext/node_mixin.rb +69 -0
  12. data/lib/neo4j.old/extensions/aggregate/node_aggregate.rb +8 -0
  13. data/lib/neo4j.old/extensions/aggregate/node_aggregate_mixin.rb +331 -0
  14. data/lib/neo4j.old/extensions/aggregate/node_aggregator.rb +216 -0
  15. data/lib/neo4j.old/extensions/aggregate/node_group.rb +43 -0
  16. data/lib/neo4j.old/extensions/aggregate/prop_group.rb +30 -0
  17. data/lib/neo4j.old/extensions/aggregate/property_enum.rb +24 -0
  18. data/lib/neo4j.old/extensions/aggregate/props_aggregate.rb +8 -0
  19. data/lib/neo4j.old/extensions/aggregate/props_aggregate_mixin.rb +31 -0
  20. data/lib/neo4j.old/extensions/aggregate/props_aggregator.rb +80 -0
  21. data/lib/neo4j.old/extensions/find_path.rb +117 -0
  22. data/lib/neo4j.old/extensions/graph_algo.rb +1 -0
  23. data/lib/neo4j.old/extensions/graph_algo/all_simple_paths.rb +133 -0
  24. data/lib/neo4j.old/extensions/graph_algo/neo4j-graph-algo-0.3.jar +0 -0
  25. data/lib/neo4j.old/extensions/reindexer.rb +104 -0
  26. data/lib/neo4j.old/extensions/rest.rb +21 -0
  27. data/lib/neo4j.old/extensions/rest/rest.rb +336 -0
  28. data/lib/neo4j.old/extensions/rest/rest_mixin.rb +193 -0
  29. data/lib/neo4j.old/extensions/rest/server.rb +50 -0
  30. data/lib/neo4j.old/extensions/rest/stubs.rb +141 -0
  31. data/lib/neo4j.old/extensions/rest_master.rb +34 -0
  32. data/lib/neo4j.old/extensions/rest_slave.rb +31 -0
  33. data/lib/neo4j.old/extensions/tx_tracker.rb +392 -0
  34. data/lib/neo4j.old/indexer.rb +187 -0
  35. data/lib/neo4j.old/jars.rb +6 -0
  36. data/lib/neo4j.old/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  37. data/lib/neo4j.old/jars/neo4j-kernel-1.0.jar +0 -0
  38. data/lib/neo4j.old/mixins/java_list_mixin.rb +139 -0
  39. data/lib/neo4j.old/mixins/java_node_mixin.rb +205 -0
  40. data/lib/neo4j.old/mixins/java_property_mixin.rb +169 -0
  41. data/lib/neo4j.old/mixins/java_relationship_mixin.rb +60 -0
  42. data/lib/neo4j.old/mixins/migration_mixin.rb +157 -0
  43. data/lib/neo4j.old/mixins/node_mixin.rb +249 -0
  44. data/lib/neo4j.old/mixins/property_class_methods.rb +265 -0
  45. data/lib/neo4j.old/mixins/rel_class_methods.rb +167 -0
  46. data/lib/neo4j.old/mixins/relationship_mixin.rb +103 -0
  47. data/lib/neo4j.old/neo.rb +247 -0
  48. data/lib/neo4j.old/node.rb +49 -0
  49. data/lib/neo4j.old/reference_node.rb +15 -0
  50. data/lib/neo4j.old/relationship.rb +85 -0
  51. data/lib/neo4j.old/relationships/decl_relationship_dsl.rb +164 -0
  52. data/lib/neo4j.old/relationships/has_list.rb +101 -0
  53. data/lib/neo4j.old/relationships/has_n.rb +129 -0
  54. data/lib/neo4j.old/relationships/node_traverser.rb +138 -0
  55. data/lib/neo4j.old/relationships/relationship_dsl.rb +149 -0
  56. data/lib/neo4j.old/relationships/traversal_position.rb +50 -0
  57. data/lib/neo4j.old/relationships/wrappers.rb +51 -0
  58. data/lib/neo4j.old/search_result.rb +72 -0
  59. data/lib/neo4j.old/transaction.rb +254 -0
  60. data/lib/neo4j.old/version.rb +3 -0
  61. data/lib/neo4j.rb +50 -0
  62. data/lib/neo4j/config.rb +137 -0
  63. data/lib/neo4j/database.rb +43 -0
  64. data/lib/neo4j/equal.rb +22 -0
  65. data/lib/neo4j/event_handler.rb +91 -0
  66. data/lib/neo4j/index.rb +157 -0
  67. data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  68. data/lib/neo4j/jars/lucene-core-2.9.2.jar +0 -0
  69. data/lib/neo4j/jars/lucene-core-3.0.1.jar +0 -0
  70. data/lib/neo4j/jars/neo4j-index-1.1.jar +0 -0
  71. data/lib/neo4j/jars/neo4j-kernel-1.1.1.jar +0 -0
  72. data/lib/neo4j/jars/neo4j-kernel-1.1.jar +0 -0
  73. data/lib/neo4j/jars/neo4j-lucene-index-0.1-20100916.085626-67.jar +0 -0
  74. data/lib/neo4j/mapping/class_methods/index.rb +21 -0
  75. data/lib/neo4j/mapping/class_methods/property.rb +139 -0
  76. data/lib/neo4j/mapping/class_methods/relationship.rb +96 -0
  77. data/lib/neo4j/mapping/class_methods/rule.rb +135 -0
  78. data/lib/neo4j/mapping/decl_relationship_dsl.rb +151 -0
  79. data/lib/neo4j/mapping/has_n.rb +117 -0
  80. data/lib/neo4j/mapping/node_mixin.rb +70 -0
  81. data/lib/neo4j/neo4j.rb +65 -0
  82. data/lib/neo4j/node.rb +82 -0
  83. data/lib/neo4j/node_mixin.rb +4 -0
  84. data/lib/neo4j/node_relationship.rb +60 -0
  85. data/lib/neo4j/node_traverser.rb +141 -0
  86. data/lib/neo4j/property.rb +72 -0
  87. data/lib/neo4j/rails/lucene_connection_closer.rb +19 -0
  88. data/lib/neo4j/rails/model.rb +210 -0
  89. data/lib/neo4j/rails/railtie.rb +16 -0
  90. data/lib/neo4j/rails/transaction.rb +29 -0
  91. data/lib/neo4j/rails/value.rb +43 -0
  92. data/lib/neo4j/relationship.rb +88 -0
  93. data/lib/neo4j/relationship_traverser.rb +57 -0
  94. data/lib/neo4j/to_java.rb +17 -0
  95. data/lib/neo4j/transaction.rb +69 -0
  96. data/lib/neo4j/version.rb +3 -0
  97. data/neo4j.gemspec +30 -0
  98. metadata +243 -0
@@ -0,0 +1,144 @@
1
+ module Neo4j
2
+
3
+ class BatchItem # :nodoc:
4
+ attr_accessor :_wrapper, :neo_id
5
+
6
+ include Neo4j::JavaPropertyMixin
7
+
8
+ def initialize(neo_id, inserter)
9
+ @neo_id = neo_id
10
+ @inserter = inserter
11
+ end
12
+
13
+ def getId(); neo_id end
14
+
15
+ def has_property?(key)
16
+ props.include?(key.to_s)
17
+ end
18
+
19
+ def get_property(key)
20
+ props[key]
21
+ end
22
+
23
+ def props
24
+ # not sure why I have to do it like this, Strange why I can't use the Java Hash ?
25
+ # gets java.lang.UnsupportedOperationException: null, in java/util/AbstractMap.java:186:in `put'
26
+ java_props = @inserter.getNodeProperties(neo_id)
27
+ ruby_props = {}
28
+ java_props.keySet().each{|k| ruby_props[k] = java_props[k]}
29
+ ruby_props
30
+ end
31
+
32
+
33
+ def setProperty(key, value)
34
+ ruby_props = props
35
+ ruby_props[key.to_s] = value
36
+ @inserter.setNodeProperties(neo_id, ruby_props)
37
+
38
+ if (wrapper_class and key[0, 1] != '_') # do not want events on internal properties
39
+ wrapper_class.indexer.on_property_changed(wrapper, key)
40
+ end
41
+ end
42
+ end
43
+
44
+ # Neo4j has a batch insert mode that drops support for transactions and concurrency in favor of insertion speed.
45
+ # This is useful when you have a big dataset that needs to be loaded once. In our experience, the batch inserter will
46
+ # typically inject data around five times faster than running in normal transactional mode.
47
+ #
48
+ # === Usage
49
+ #
50
+ # The initialize method takes a code block that will use the BatchInserter.
51
+ #
52
+ # Neo4j::BatchInserter.new do |b|
53
+ # a = Neo4j::Node.new :name => 'a'
54
+ # b = Neo4j::Node.new :name => 'b'
55
+ # c = Foo.new :key1 => 'val1', :key2 => 'val2'
56
+ # c[:name] = "c"
57
+ # Neo4j::Relationship.new(:friend, a, b, :since => '2001-01-01')
58
+ # Neo4j::Relationship.new(:friend, Neo4j.ref_node, c, :since => '2001-01-01')
59
+ # end
60
+ #
61
+ # After the code block the normal creation for nodes and relationship will be used.
62
+ # Traversals inside the batch inserter block is not possible.
63
+ # The BatchInserter can be used together with Neo4j Migrations (see Neo4j#migration)
64
+ #
65
+ class BatchInserter
66
+
67
+ # See class description for usage.
68
+ #
69
+ # === Parameters
70
+ # storage_path:: optional, the location of the neo4j dabase on file system, default Neo4j::Config[:storage_path]
71
+ # db_version:: optional, sets version number on reference node, default nil -> do not set this property
72
+ def initialize(storage_path = Neo4j::Config[:storage_path], db_version=nil) # :yields: batch_inserter
73
+ # create the batch inserter
74
+ inserter = org.neo4j.kernel.impl.batchinsert.BatchInserterImpl.new(storage_path)
75
+
76
+ # save original methods
77
+ create_node_meth = Neo4j.method(:create_node)
78
+ create_rel_meth = Neo4j.method(:create_rel)
79
+ ref_node_meth = Neo4j.method(:ref_node)
80
+ instance_meth = Neo4j.method(:instance)
81
+
82
+ # replace methods
83
+ neo4j_meta = (class << Neo4j; self; end)
84
+ neo4j_meta.instance_eval do
85
+ define_method(:create_node) do |props|
86
+ props ||= {}
87
+ id = inserter.createNode(props.keys.inject({}) {|hash, key| hash[key.to_s] = props[key]; hash})
88
+ BatchItem.new(id, inserter)
89
+ end
90
+ define_method(:create_rel) do |type, from_node, to_node, props|
91
+ props = Hash[*props.map{|k, v| [k.to_s, v]}.flatten] if props
92
+ java_type = org.neo4j.graphdb.DynamicRelationshipType.withName(type.to_s)
93
+ id = inserter.createRelationship(from_node.neo_id, to_node.neo_id, java_type, props)
94
+ BatchItem.new(id, inserter)
95
+ end
96
+ define_method(:ref_node) do
97
+ BatchItem.new(inserter.getReferenceNode, inserter)
98
+ end
99
+ define_method(:instance) do
100
+ Neo4j::BatchInstance.new
101
+ end
102
+ end
103
+
104
+ begin
105
+ yield inserter
106
+ Neo4j.ref_node[:db_version] = db_version if db_version
107
+ ensure
108
+ inserter.shutdown
109
+ # restore old methods
110
+ neo4j_meta.instance_eval do
111
+ define_method(:create_node, create_node_meth)
112
+ define_method(:create_rel, create_rel_meth)
113
+ define_method(:ref_node, ref_node_meth)
114
+ define_method(:instance, instance_meth)
115
+ end
116
+ end
117
+ end
118
+
119
+ # This method is used if the batch inserter is used from the Migration API.
120
+ #
121
+ # === Parameters
122
+ # context:: the context on which the batch inserter code block is evaluated in, not used.
123
+ # version:: optional, if given then will set the property db_version on the context
124
+ def self.execute(context, version=nil, &block)
125
+ # Neo4j must not be running while using batch inserter, stop it just in case ...
126
+ Neo4j::Transaction.finish
127
+ Neo4j.stop
128
+
129
+ BatchInserter.new(Neo4j::Config[:storage_path], version, &block)
130
+
131
+ Neo4j.start
132
+ end
133
+ end
134
+
135
+ # Used instead of Neo4j.instance object - will happily accept any methods - like transaction methods.
136
+ class BatchInstance # :nodoc:
137
+ def method_missing(m, *args, &block)
138
+ return BatchInstance.new
139
+ end
140
+ end
141
+ end
142
+
143
+
144
+
@@ -0,0 +1,138 @@
1
+
2
+ module Neo4j
3
+
4
+
5
+ # Keeps configuration for neo4j.
6
+ #
7
+ # Neo4j::Config[:storage_path]:: is used for locating the neo4j database on the filesystem.
8
+ # Neo4j::Config[:rest_port]:: used by the REST extension for starting a web server on a port
9
+ #
10
+ class Config
11
+ # This code is copied from merb-core/config.rb.
12
+ class << self
13
+ # Returns the hash of default config values for neo4j
14
+ #
15
+ # ==== Returns
16
+ # Hash:: The defaults for the config.
17
+ def defaults
18
+ @defaults ||= {
19
+ :storage_path => 'tmp/neo4j',
20
+ :rest_port => 9123
21
+ }
22
+ end
23
+
24
+
25
+ # Yields the configuration.
26
+ #
27
+ # ==== Block parameters
28
+ # c<Hash>:: The configuration parameters.
29
+ #
30
+ # ==== Examples
31
+ # Neo4j::Config.use do |config|
32
+ # config[:storage_path] = '/var/neo4j'
33
+ # end
34
+ #
35
+ # ==== Returns
36
+ # nil
37
+ def use
38
+ @configuration ||= {}
39
+ yield @configuration
40
+ nil
41
+ end
42
+
43
+
44
+ # Set the value of a config entry.
45
+ #
46
+ # ==== Parameters
47
+ # key<Object>:: The key to set the parameter for.
48
+ # val<Object>:: The value of the parameter.
49
+ #
50
+ def []=(key, val)
51
+ (@configuration ||= setup)[key] = val
52
+ end
53
+
54
+
55
+ # Gets the the value of a config entry
56
+ #
57
+ # ==== Parameters
58
+ # key<Object>:: The key of the config entry value we want
59
+ #
60
+ def [](key)
61
+ (@configuration ||= setup)[key]
62
+ end
63
+
64
+
65
+ # Remove the value of a config entry.
66
+ #
67
+ # ==== Parameters
68
+ # key<Object>:: The key of the parameter to delete.
69
+ #
70
+ # ==== Returns
71
+ # Object:: The value of the removed entry.
72
+ #
73
+ def delete(key)
74
+ @configuration.delete(key)
75
+ end
76
+
77
+
78
+ # Remove all configuration. This can be useful for testing purpose.
79
+ #
80
+ #
81
+ # ==== Returns
82
+ # nil
83
+ #
84
+ def delete_all
85
+ @configuration = nil
86
+ end
87
+
88
+
89
+ # Retrieve the value of a config entry, returning the provided default if the key is not present
90
+ #
91
+ # ==== Parameters
92
+ # key<Object>:: The key to retrieve the parameter for.
93
+ # default<Object>::
94
+ # The default value to return if the parameter is not set.
95
+ #
96
+ # ==== Returns
97
+ # Object:: The value of the configuration parameter or the default.
98
+ #
99
+ def fetch(key, default)
100
+ @configuration.fetch(key, default)
101
+ end
102
+
103
+ # Sets up the configuration
104
+ #
105
+ # ==== Returns
106
+ # The configuration as a hash.
107
+ #
108
+ def setup()
109
+ @configuration = {}
110
+ @configuration.merge!(defaults)
111
+ @configuration
112
+ end
113
+
114
+
115
+ # Returns the configuration as a hash.
116
+ #
117
+ # ==== Returns
118
+ # Hash:: The config as a hash.
119
+ #
120
+ # :api: public
121
+ def to_hash
122
+ @configuration
123
+ end
124
+
125
+ # Returns the config as YAML.
126
+ #
127
+ # ==== Returns
128
+ # String:: The config as YAML.
129
+ #
130
+ # :api: public
131
+ def to_yaml
132
+ require "yaml"
133
+ @configuration.to_yaml
134
+ end
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,73 @@
1
+ module Neo4j
2
+
3
+ # Handles events like a new node is created or deleted
4
+ class EventHandler
5
+ def initialize
6
+ @listeners = []
7
+ @filter_classes = []
8
+ end
9
+
10
+ def add(listener)
11
+ @listeners << listener unless @listeners.include?(listener)
12
+ add_filter(listener) # the listener do not want to get events on it self
13
+ end
14
+
15
+ def remove(listener)
16
+ @listeners.delete(listener)
17
+ end
18
+
19
+ def remove_all
20
+ @listeners = []
21
+ end
22
+
23
+ def print
24
+ puts "Listeners #{@listeners.size}"
25
+ @listeners.each {|li| puts " Listener '#{li}'"}
26
+ end
27
+
28
+ def add_filter(filter_class)
29
+ @filter_classes << filter_class unless @filter_classes.include?(filter_class)
30
+ end
31
+
32
+ def remove_filter(filter_class)
33
+ @filter_classes.delete filter_class
34
+ end
35
+
36
+ def node_created(node)
37
+ return if @filter_classes.include?(node.class)
38
+ @listeners.each {|li| li.on_node_created(node) if li.respond_to?(:on_node_created)}
39
+ end
40
+
41
+ def node_deleted(node)
42
+ return if @filter_classes.include?(node.class)
43
+ @listeners.each {|li| li.on_node_deleted(node) if li.respond_to?(:on_node_deleted)}
44
+ end
45
+
46
+ def relationship_created(relationship)
47
+ return if @filter_classes.include?(relationship.class)
48
+ @listeners.each {|li| li.on_relationship_created(relationship) if li.respond_to?(:on_relationship_created)}
49
+ end
50
+
51
+ def relationship_deleted(relationship)
52
+ return if @filter_classes.include?(relationship.class)
53
+ @listeners.each {|li| li.on_relationship_deleted(relationship) if li.respond_to?(:on_relationship_deleted)}
54
+ end
55
+
56
+ def property_changed(node, key, old_value, new_value)
57
+ return if @filter_classes.include?(node.class)
58
+ @listeners.each {|li| li.on_property_changed(node, key, old_value, new_value) if li.respond_to?(:on_property_changed)}
59
+ end
60
+
61
+ def tx_finished(tx)
62
+ @listeners.each {|li| li.on_tx_finished(tx) if li.respond_to?(:on_tx_finished)}
63
+ end
64
+
65
+ def neo_started(neo_instance)
66
+ @listeners.each {|li| li.on_neo_started(neo_instance) if li.respond_to?(:on_neo_started)}
67
+ end
68
+
69
+ def neo_stopped(neo_instance)
70
+ @listeners.each {|li| li.on_neo_stopped(neo_instance) if li.respond_to?(:on_neo_stopped)}
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,158 @@
1
+ require 'rubygems'
2
+ require 'singleton'
3
+ require 'neo4j'
4
+ require 'active_model'
5
+
6
+
7
+ module Neo4j::NodeMixin
8
+ def to_model
9
+ Neo4j::ActiveModel::ActiveModelFactory.instance.to_model(self)
10
+ end
11
+
12
+ def attributes
13
+ attr = props
14
+ attr.keys.each {|k| attr.delete k if k[0] == ?_}
15
+ attr
16
+ end
17
+
18
+ end
19
+
20
+ module Neo4j::ActiveModel
21
+
22
+ def self.on_property_changed(node, key, old_value, new_value)
23
+ # make model dirty since it is changed
24
+ ActiveModelFactory.instance.dirty_node!(node.neo_id)
25
+ end
26
+
27
+ def self.on_tx_finished(tx)
28
+ # make all models clean again
29
+ ActiveModelFactory.instance.clean!
30
+ end
31
+
32
+ class ActiveModelFactory
33
+ private
34
+ def initialize
35
+ @classes = {}
36
+ @node_models = {}
37
+ Thread.current[:neo4j_active_model_factory] = self
38
+ Neo4j.event_handler.add(self)
39
+ end
40
+
41
+ public
42
+ def self.instance
43
+ # create one Neo4jActiveModelFactory for each thread
44
+ # since a transaction belongs to a thread and we don't want
45
+ # side effect of one transaction making model object dirty or clean for a different transaction
46
+ # in a different thread.
47
+ Thread.current[:neo4j_active_model_factory] || ActiveModelFactory.new
48
+ end
49
+
50
+ def dirty_node!(neo_id)
51
+ @node_models[neo_id] && @node_models[neo_id].dirty!
52
+ end
53
+
54
+ def clean!
55
+ @node_models.clear
56
+ end
57
+
58
+ def to_model(obj)
59
+ @node_models[obj.neo_id] || create_model_for(obj)
60
+ end
61
+
62
+ def create_model_for(obj)
63
+ clazz = @classes[obj.class] || create_wrapped_class_for(obj)
64
+ @node_models[obj.neo_id] = clazz.new(obj)
65
+ end
66
+
67
+ def create_wrapped_class_for(obj)
68
+ clazz = Class.new do
69
+ def initialize(wrapped)
70
+ @dirty = false
71
+ @wrapped = wrapped
72
+ end
73
+
74
+ def dirty!
75
+ @dirty = true
76
+ end
77
+
78
+ def persisted?
79
+ ! @dirty
80
+ end
81
+
82
+ def to_key
83
+ persisted? ? @wrapped.neo_id : nil
84
+ end
85
+
86
+ def to_param
87
+ to_key
88
+ end
89
+
90
+ if obj.respond_to?(:errors)
91
+ def errors;
92
+ @wrapped.errors;
93
+ end
94
+ else
95
+ def errors
96
+ object = Object.new
97
+
98
+ def object.[](key)
99
+ []
100
+ end
101
+
102
+ def object.full_messages()
103
+ []
104
+ end
105
+
106
+ object
107
+ end
108
+ end
109
+
110
+ if obj.respond_to?(:valid?)
111
+ def valid?;
112
+ @wrapped.valid?;
113
+ end
114
+ else
115
+ def valid?
116
+ true
117
+ end
118
+ end
119
+ end
120
+
121
+ singleton = class << clazz;
122
+ self;
123
+ end
124
+ singleton.class_eval do
125
+ # class methods
126
+ define_method :model_name do
127
+ @_model_name ||= ActiveModel::Name.new(obj.class)
128
+ end
129
+ end
130
+
131
+ @classes[obj.class] = clazz
132
+ clazz
133
+ end
134
+
135
+ end
136
+
137
+ Neo4j.event_handler.add(self)
138
+ end
139
+
140
+
141
+
142
+ #class LintTest < ActiveModel::TestCase
143
+ # include ActiveModel::Lint::Tests
144
+ #
145
+ # class MyModel
146
+ # include Neo4j::NodeMixin
147
+ # end
148
+ #
149
+ # def setup
150
+ # @model = MyModel.new
151
+ # end
152
+ #
153
+ #end
154
+ #
155
+ #require 'test/unit/ui/console/testrunner'
156
+ #Neo4j::Transaction.run do
157
+ # Test::Unit::UI::Console::TestRunner.run(LintTest)
158
+ #end