neo4j 1.0.0.beta.21-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/CHANGELOG +141 -0
  2. data/CONTRIBUTORS +17 -0
  3. data/Gemfile +16 -0
  4. data/README.rdoc +135 -0
  5. data/lib/generators/neo4j.rb +65 -0
  6. data/lib/generators/neo4j/model/model_generator.rb +39 -0
  7. data/lib/generators/neo4j/model/templates/model.erb +7 -0
  8. data/lib/neo4j.rb +77 -0
  9. data/lib/neo4j/config.rb +153 -0
  10. data/lib/neo4j/database.rb +56 -0
  11. data/lib/neo4j/equal.rb +21 -0
  12. data/lib/neo4j/event_handler.rb +116 -0
  13. data/lib/neo4j/index/class_methods.rb +62 -0
  14. data/lib/neo4j/index/index.rb +33 -0
  15. data/lib/neo4j/index/indexer.rb +312 -0
  16. data/lib/neo4j/index/indexer_registry.rb +68 -0
  17. data/lib/neo4j/index/lucene_query.rb +191 -0
  18. data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  19. data/lib/neo4j/jars/lucene-core-3.0.2.jar +0 -0
  20. data/lib/neo4j/jars/neo4j-index-1.2-1.2.M03.jar +0 -0
  21. data/lib/neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar +0 -0
  22. data/lib/neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar +0 -0
  23. data/lib/neo4j/load.rb +21 -0
  24. data/lib/neo4j/mapping/class_methods/init_node.rb +50 -0
  25. data/lib/neo4j/mapping/class_methods/init_rel.rb +35 -0
  26. data/lib/neo4j/mapping/class_methods/list.rb +13 -0
  27. data/lib/neo4j/mapping/class_methods/property.rb +82 -0
  28. data/lib/neo4j/mapping/class_methods/relationship.rb +91 -0
  29. data/lib/neo4j/mapping/class_methods/rule.rb +295 -0
  30. data/lib/neo4j/mapping/decl_relationship_dsl.rb +214 -0
  31. data/lib/neo4j/mapping/has_list.rb +134 -0
  32. data/lib/neo4j/mapping/has_n.rb +83 -0
  33. data/lib/neo4j/mapping/node_mixin.rb +112 -0
  34. data/lib/neo4j/mapping/relationship_mixin.rb +120 -0
  35. data/lib/neo4j/model.rb +4 -0
  36. data/lib/neo4j/neo4j.rb +95 -0
  37. data/lib/neo4j/node.rb +131 -0
  38. data/lib/neo4j/node_mixin.rb +4 -0
  39. data/lib/neo4j/node_relationship.rb +149 -0
  40. data/lib/neo4j/node_traverser.rb +157 -0
  41. data/lib/neo4j/property.rb +111 -0
  42. data/lib/neo4j/rails/attributes.rb +155 -0
  43. data/lib/neo4j/rails/callbacks.rb +34 -0
  44. data/lib/neo4j/rails/finders.rb +134 -0
  45. data/lib/neo4j/rails/lucene_connection_closer.rb +19 -0
  46. data/lib/neo4j/rails/mapping/property.rb +60 -0
  47. data/lib/neo4j/rails/model.rb +105 -0
  48. data/lib/neo4j/rails/persistence.rb +260 -0
  49. data/lib/neo4j/rails/railtie.rb +21 -0
  50. data/lib/neo4j/rails/relationships/mapper.rb +96 -0
  51. data/lib/neo4j/rails/relationships/relationship.rb +30 -0
  52. data/lib/neo4j/rails/relationships/relationships.rb +60 -0
  53. data/lib/neo4j/rails/serialization.rb +25 -0
  54. data/lib/neo4j/rails/timestamps.rb +65 -0
  55. data/lib/neo4j/rails/transaction.rb +67 -0
  56. data/lib/neo4j/rails/tx_methods.rb +15 -0
  57. data/lib/neo4j/rails/validations.rb +38 -0
  58. data/lib/neo4j/rails/validations/non_nil.rb +11 -0
  59. data/lib/neo4j/rails/validations/uniqueness.rb +37 -0
  60. data/lib/neo4j/relationship.rb +169 -0
  61. data/lib/neo4j/relationship_mixin.rb +4 -0
  62. data/lib/neo4j/relationship_traverser.rb +92 -0
  63. data/lib/neo4j/to_java.rb +31 -0
  64. data/lib/neo4j/transaction.rb +68 -0
  65. data/lib/neo4j/type_converters.rb +117 -0
  66. data/lib/neo4j/version.rb +3 -0
  67. data/lib/orm_adapter/adapters/neo4j.rb +55 -0
  68. data/lib/tmp/neo4j/active_tx_log +1 -0
  69. data/lib/tmp/neo4j/index/lucene-store.db +0 -0
  70. data/lib/tmp/neo4j/index/lucene.log.active +0 -0
  71. data/lib/tmp/neo4j/lucene-fulltext/lucene-store.db +0 -0
  72. data/lib/tmp/neo4j/lucene-fulltext/lucene.log.active +0 -0
  73. data/lib/tmp/neo4j/lucene/lucene-store.db +0 -0
  74. data/lib/tmp/neo4j/lucene/lucene.log.active +0 -0
  75. data/lib/tmp/neo4j/messages.log +85 -0
  76. data/lib/tmp/neo4j/neostore +0 -0
  77. data/lib/tmp/neo4j/neostore.id +0 -0
  78. data/lib/tmp/neo4j/neostore.nodestore.db +0 -0
  79. data/lib/tmp/neo4j/neostore.nodestore.db.id +0 -0
  80. data/lib/tmp/neo4j/neostore.propertystore.db +0 -0
  81. data/lib/tmp/neo4j/neostore.propertystore.db.arrays +0 -0
  82. data/lib/tmp/neo4j/neostore.propertystore.db.arrays.id +0 -0
  83. data/lib/tmp/neo4j/neostore.propertystore.db.id +0 -0
  84. data/lib/tmp/neo4j/neostore.propertystore.db.index +0 -0
  85. data/lib/tmp/neo4j/neostore.propertystore.db.index.id +0 -0
  86. data/lib/tmp/neo4j/neostore.propertystore.db.index.keys +0 -0
  87. data/lib/tmp/neo4j/neostore.propertystore.db.index.keys.id +0 -0
  88. data/lib/tmp/neo4j/neostore.propertystore.db.strings +0 -0
  89. data/lib/tmp/neo4j/neostore.propertystore.db.strings.id +0 -0
  90. data/lib/tmp/neo4j/neostore.relationshipstore.db +0 -0
  91. data/lib/tmp/neo4j/neostore.relationshipstore.db.id +0 -0
  92. data/lib/tmp/neo4j/neostore.relationshiptypestore.db +0 -0
  93. data/lib/tmp/neo4j/neostore.relationshiptypestore.db.id +0 -0
  94. data/lib/tmp/neo4j/neostore.relationshiptypestore.db.names +0 -0
  95. data/lib/tmp/neo4j/neostore.relationshiptypestore.db.names.id +0 -0
  96. data/lib/tmp/neo4j/nioneo_logical.log.active +0 -0
  97. data/lib/tmp/neo4j/tm_tx_log.1 +0 -0
  98. data/neo4j.gemspec +31 -0
  99. metadata +216 -0
@@ -0,0 +1,157 @@
1
+ module Neo4j
2
+
3
+ class PruneEvaluator # :nodoc:
4
+ include org.neo4j.graphdb.traversal.PruneEvaluator
5
+ def initialize(proc)
6
+ @proc = proc
7
+ end
8
+
9
+ def prune_after(path)
10
+ @proc.call(path)
11
+ end
12
+ end
13
+
14
+ class FilterPredicate # :nodoc:
15
+ include org.neo4j.helpers.Predicate
16
+ def initialize
17
+ @procs = []
18
+ end
19
+
20
+ def add(proc)
21
+ @procs << proc
22
+ end
23
+
24
+ def include_start_node
25
+ @include_start_node = true
26
+ end
27
+
28
+ def accept(path)
29
+ return false if @include_start_node && path.length == 0
30
+ # find the first filter which returns false
31
+ # if not found then we will accept this path
32
+ @procs.find {|p| !p.call(path)}.nil?
33
+ end
34
+ end
35
+
36
+
37
+ class NodeTraverser
38
+ include Enumerable
39
+ include ToJava
40
+
41
+ def initialize(from, type = nil, dir=nil)
42
+ @from = from
43
+ @depth = 1
44
+ if type.nil? || dir.nil?
45
+ @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first()
46
+ else
47
+ @type = type_to_java(type)
48
+ @dir = dir_to_java(dir)
49
+ @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first().relationships(@type, @dir)
50
+ end
51
+ end
52
+
53
+
54
+ def to_s
55
+ "NodeTraverser [from: #{@from.neo_id} depth: #{@depth} type: #{@type} dir:#{@dir}"
56
+ end
57
+
58
+ def <<(other_node)
59
+ new(other_node)
60
+ self
61
+ end
62
+
63
+ def new(other_node)
64
+ case @dir
65
+ when org.neo4j.graphdb.Direction::OUTGOING
66
+ @from.create_relationship_to(other_node, @type)
67
+ when org.neo4j.graphdb.Direction::INCOMING
68
+ other_node._java_node.create_relationship_to(@from, @type)
69
+ else
70
+ raise "Only allowed to create outgoing or incoming relationships (not #@dir)"
71
+ end
72
+ end
73
+
74
+ def both(type)
75
+ @type = type_to_java(type) if type
76
+ @dir = dir_to_java(:both)
77
+ @td = @td.relationships(type_to_java(type), @dir)
78
+ self
79
+ end
80
+
81
+ def outgoing(type)
82
+ @type = type_to_java(type) if type
83
+ @dir = dir_to_java(:outgoing)
84
+ @td = @td.relationships(type_to_java(type), @dir)
85
+ self
86
+ end
87
+
88
+ def incoming(type)
89
+ @type = type_to_java(type) if type
90
+ @dir = dir_to_java(:incoming)
91
+ @td = @td.relationships(type_to_java(type), @dir)
92
+ self
93
+ end
94
+
95
+ def filter_method(name, &proc)
96
+ # add method name
97
+ singelton = class << self; self; end
98
+ singelton.send(:define_method, name) {filter &proc}
99
+ self
100
+ end
101
+
102
+ def prune(&block)
103
+ @td = @td.prune(PruneEvaluator.new(block))
104
+ self
105
+ end
106
+
107
+ def filter(&block)
108
+ # we keep a reference to filter predicate since only one filter is allowed and we might want to modify it
109
+ @filter_predicate ||= FilterPredicate.new
110
+ @filter_predicate.add(block)
111
+ @td = @td.filter(@filter_predicate)
112
+ self
113
+ end
114
+
115
+ # Sets depth, if :all then it will traverse any depth
116
+ def depth(d)
117
+ @depth = d
118
+ self
119
+ end
120
+
121
+ def include_start_node
122
+ @include_start_node = true
123
+ self
124
+ end
125
+
126
+ def size
127
+ [*self].size
128
+ end
129
+
130
+ alias_method :length, :size
131
+
132
+ def [](index)
133
+ each_with_index {|node,i| break node if index == i}
134
+ end
135
+
136
+ def empty?
137
+ first == nil
138
+ end
139
+
140
+ def each
141
+ iterator.each {|i| yield i.wrapper}
142
+ end
143
+
144
+ def iterator
145
+ unless @include_start_node
146
+ if @filter_predicate
147
+ @filter_predicate.include_start_node
148
+ else
149
+ @td = @td.filter(org.neo4j.kernel.Traversal.return_all_but_start_node)
150
+ end
151
+ end
152
+ @td = @td.prune(org.neo4j.kernel.Traversal.pruneAfterDepth( @depth ) ) unless @depth == :all
153
+ @td.traverse(@from).nodes
154
+ end
155
+ end
156
+
157
+ end
@@ -0,0 +1,111 @@
1
+ module Neo4j
2
+ module Property
3
+
4
+ # Returns a hash of all properties
5
+ # It also include the id of the node with the key <tt>_neo_id</tt>
6
+ #
7
+ def props
8
+ ret = {"_neo_id" => neo_id}
9
+ iter = getPropertyKeys.iterator
10
+ while (iter.hasNext) do
11
+ key = iter.next
12
+ ret[key] = get_property(key)
13
+ end
14
+ ret
15
+ end
16
+
17
+ # Returns the unique id of this node.
18
+ # Ids are garbage collected over time so they are only guaranteed to be unique during a specific time span:
19
+ # if the node is deleted, it's likely that a new node at some point will get the old id. Note:
20
+ # this makes node ids brittle as public APIs.
21
+ def neo_id
22
+ getId
23
+ end
24
+
25
+ # Returns a hash of properties with keys not starting with <tt>_</tt>
26
+ # That means that the neo_id will not be included in the returned hash.
27
+ #
28
+ def attributes
29
+ attr = props
30
+ ret = {}
31
+ attr.each_pair { |k, v| ret[k] = wrapper.respond_to?(k) ? wrapper.send(k) : v unless k.to_s[0] == ?_ }
32
+ ret
33
+ end
34
+
35
+ # Checks if the given key exist as a property.
36
+ def property?(key)
37
+ has_property?(key.to_s)
38
+ end
39
+
40
+ # Updates this node/relationship's properties by using the provided struct/hash.
41
+ # If the option <code>{:strict => true}</code> is given, any properties present on
42
+ # the node but not present in the hash will be removed from the node.
43
+ #
44
+ # ==== Parameters
45
+ # struct_or_hash:: the key and value to be set, should respond to <tt>each_pair</tt>
46
+ # options:: further options defining the context of the update, should be a Hash
47
+ #
48
+ # ==== Returns
49
+ # self
50
+ #
51
+ def update(struct_or_hash, options={})
52
+ strict = options[:strict]
53
+ keys_to_delete = props.keys - %w(_neo_id _classname) if strict
54
+ struct_or_hash.each_pair do |key, value|
55
+ next if %w(_neo_id _classname).include? key.to_s
56
+ # do not allow special properties to be mass assigned
57
+ keys_to_delete.delete(key) if strict
58
+ setter_meth = "#{key}=".to_sym
59
+ if @_wrapper && @_wrapper.respond_to?(setter_meth)
60
+ @_wrapper.send(setter_meth, value)
61
+ else
62
+ self[key] = value
63
+ end
64
+ end
65
+ keys_to_delete.each { |key| delete_property(key) } if strict
66
+ self
67
+ end
68
+
69
+
70
+ # Returns the value of the given key or nil if the property does not exist.
71
+ def [](key)
72
+ return unless property?(key)
73
+ val = get_property(key.to_s)
74
+ val.class.superclass == ArrayJavaProxy ? val.to_a : val
75
+ end
76
+
77
+ # Sets the property of this node.
78
+ # Property keys are always strings. Valid property value types are the primitives(<tt>String</tt>, <tt>Fixnum</tt>, <tt>Float</tt>, <tt>FalseClass</tt>, <tt>TrueClass</tt>) or array of those primitives.
79
+ #
80
+ # ==== Gotchas
81
+ # * Values in the array must be of the same type.
82
+ # * You can *not* delete or add one item in the array (e.g. person.phones.delete('123')) but instead you must create a new array instead.
83
+ #
84
+ def []=(key, value)
85
+ k = key.to_s
86
+ if value.nil?
87
+ remove_property(k)
88
+ elsif (Array === value)
89
+ case value[0]
90
+ when NilClass
91
+ set_property(k, [].to_java(:string))
92
+ when String
93
+ set_property(k, value.to_java(:string))
94
+ when Float
95
+ set_property(k, value.to_java(:double))
96
+ when FalseClass, TrueClass
97
+ set_property(k, value.to_java(:boolean))
98
+ when Fixnum
99
+ set_property(k, value.to_java(:long))
100
+ when Boolean
101
+ set_property(k, value.to_java(:boolean))
102
+ else
103
+ raise "Not allowed to store array with value #{value[0]} type #{value[0].class}"
104
+ end
105
+ else
106
+ set_property(k, value)
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,155 @@
1
+ # This module handles the getting, setting and updating of attributes or properties
2
+ # in a Railsy way. This typically means not writing anything to the DB until the
3
+ # object is saved (after validation).
4
+ #
5
+ # Externally, when we talk about properties (e.g. #property?, #property_names, #properties),
6
+ # we mean all of the stored properties for this object include the 'hidden' props
7
+ # with underscores at the beginning such as _neo_id and _classname. When we talk
8
+ # about attributes, we mean all the properties apart from those hidden ones.
9
+ module Neo4j
10
+ module Rails
11
+ module Attributes
12
+ extend ActiveSupport::Concern
13
+
14
+ included do
15
+ include ActiveModel::Dirty # track changes to attributes
16
+ include ActiveModel::MassAssignmentSecurity # handle attribute hash assignment
17
+
18
+ class_inheritable_hash :attribute_defaults
19
+ self.attribute_defaults ||= {}
20
+
21
+ # save the original [] and []= to use as read/write to Neo4j
22
+ alias_method :read_attribute, :[]
23
+ alias_method :write_attribute, :[]=
24
+
25
+ # wrap the read/write in type conversion
26
+ alias_method_chain :read_local_property, :type_conversion
27
+ alias_method_chain :write_local_property, :type_conversion
28
+
29
+ # whenever we refer to [] or []=. use our local properties store
30
+ alias_method :[], :read_local_property
31
+ alias_method :[]=, :write_local_property
32
+ end
33
+
34
+ # The behaviour of []= changes with a Rails Model, where nothing gets written
35
+ # to Neo4j until the object is saved, during which time all the validations
36
+ # and callbacks are run to ensure correctness
37
+ def write_local_property(key, value)
38
+ key_s = key.to_s
39
+ if @properties[key_s] != value
40
+ attribute_will_change!(key_s)
41
+ @properties[key_s] = value
42
+ end
43
+ value
44
+ end
45
+
46
+ # Returns the locally stored value for the key or retrieves the value from
47
+ # the DB if we don't have one
48
+ def read_local_property(key)
49
+ key = key.to_s
50
+ if @properties.has_key?(key)
51
+ @properties[key]
52
+ else
53
+ @properties[key] = (persisted? && _java_node.has_property?(key)) ? read_attribute(key) : attribute_defaults[key]
54
+ end
55
+ end
56
+
57
+ # Mass-assign attributes. Stops any protected attributes from being assigned.
58
+ def attributes=(attributes, guard_protected_attributes = true)
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 }
61
+ end
62
+
63
+ # Tracks the current changes and clears the changed attributes hash. Called
64
+ # after saving the object.
65
+ def clear_changes
66
+ @previously_changed = changes
67
+ @changed_attributes.clear
68
+ end
69
+
70
+ # Return the properties from the Neo4j Node, merged with those that haven't
71
+ # yet been saved
72
+ def props
73
+ ret = {}
74
+ property_names.each do |property_name|
75
+ ret[property_name] = respond_to?(property_name) ? send(property_name) : send(:[], property_name)
76
+ end
77
+ ret
78
+ end
79
+
80
+ # Return all the attributes for this model as a hash attr => value. Doesn't
81
+ # include properties that start with <tt>_</tt>.
82
+ def attributes
83
+ ret = {}
84
+ attribute_names.each do |attribute_name|
85
+ ret[attribute_name] = respond_to?(attribute_name) ? send(attribute_name) : send(:[], attribute_name)
86
+ end
87
+ ret
88
+ end
89
+
90
+ # Known properties are either in the @properties, the declared
91
+ # attributes or the property keys for the persisted node.
92
+ def property_names
93
+ keys = @properties.keys + self.class._decl_props.keys.map { |k| k.to_s }
94
+ keys += _java_node.property_keys.to_a if persisted?
95
+ keys.flatten.uniq
96
+ end
97
+
98
+ # Known attributes are either in the @properties, the declared
99
+ # attributes or the property keys for the persisted node. Any attributes
100
+ # that start with <tt>_</tt> are rejected
101
+ def attribute_names
102
+ property_names.reject { |property_name| property_name[0] == ?_ }
103
+ end
104
+
105
+ # Known properties are either in the @properties, the declared
106
+ # properties or the property keys for the persisted node
107
+ def property?(name)
108
+ @properties.keys.include?(name) ||
109
+ self.class._decl_props.map { |k| k.to_s }.include?(name) ||
110
+ begin
111
+ super
112
+ rescue org.neo4j.graphdb.NotFoundException
113
+ set_deleted_properties
114
+ nil
115
+ end
116
+ end
117
+
118
+ # Return true if method_name is the name of an appropriate attribute
119
+ # method
120
+ def attribute?(name)
121
+ name[0] != ?_ && property?(name)
122
+ end
123
+
124
+ # To get ActiveModel::Dirty to work, we need to be able to call undeclared
125
+ # properties as though they have get methods
126
+ def method_missing(method_id, *args, &block)
127
+ method_name = method_id.to_s
128
+ if property?(method_name)
129
+ self[method_name]
130
+ else
131
+ super
132
+ end
133
+ end
134
+
135
+ def respond_to?(method_id, include_private = false)
136
+ method_name = method_id.to_s
137
+ if property?(method_name)
138
+ true
139
+ else
140
+ super
141
+ end
142
+ end
143
+
144
+ # Wrap the getter in a conversion from Java to Ruby
145
+ def read_local_property_with_type_conversion(property)
146
+ Neo4j::TypeConverters.to_ruby(self.class, property, read_local_property_without_type_conversion(property))
147
+ end
148
+
149
+ # Wrap the setter in a conversion from Ruby to Java
150
+ def write_local_property_with_type_conversion(property, value)
151
+ write_local_property_without_type_conversion(property, Neo4j::TypeConverters.to_java(self.class, property, value))
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,34 @@
1
+ module Neo4j
2
+ module Rails
3
+ module Callbacks
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ [:create_or_update, :create, :update, :destroy].each do |method|
8
+ alias_method_chain method, :callbacks
9
+ end
10
+
11
+ extend ActiveModel::Callbacks
12
+
13
+ define_model_callbacks :create, :save, :update, :destroy
14
+ end
15
+
16
+ def destroy_with_callbacks #:nodoc:
17
+ _run_destroy_callbacks { destroy_without_callbacks }
18
+ end
19
+
20
+ private
21
+ def create_or_update_with_callbacks #:nodoc:
22
+ _run_save_callbacks { create_or_update_without_callbacks }
23
+ end
24
+
25
+ def create_with_callbacks #:nodoc:
26
+ _run_create_callbacks { create_without_callbacks }
27
+ end
28
+
29
+ def update_with_callbacks(*) #:nodoc:
30
+ _run_update_callbacks { update_without_callbacks }
31
+ end
32
+ end
33
+ end
34
+ end