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,6 @@
1
+ include Java
2
+
3
+ module Neo4j
4
+ require 'neo4j/jars/neo4j-kernel-1.0.jar'
5
+ require 'neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar'
6
+ end
@@ -0,0 +1,139 @@
1
+ module Neo4j::JavaListMixin
2
+
3
+ # --------------------------------------------------------------------------
4
+ # List methods
5
+ #
6
+
7
+
8
+ # Returns true if this nodes belongs to a list of the given name
9
+ #
10
+ def list?(list_name)
11
+ regexp = Regexp.new "_list_#{list_name}"
12
+ rels.both.find { |rel| regexp.match(rel.relationship_type.to_s) } != nil
13
+ end
14
+
15
+ # Returns one or more list of the given list_name and list_node.
16
+ # If the optional list_node parameter is given the specific list belonging to that list node will be returned (or nil)
17
+ # If only the list_name parameter is given the first list matching the given list_name will be returned.
18
+ # (There might be several list of the same name but from different list nodes.)
19
+ #
20
+ # ==== Returns
21
+ #
22
+ # The node but with the extra instance methods
23
+ # * next - the next node in the list
24
+ # * prev - the previous node in the list
25
+ # * head - the head node (the node that has the has_list method)
26
+ # * size (if the size optional parameter is given in the has_list class method)
27
+ #
28
+ # ==== Example
29
+ # class Foo
30
+ # include Neo4j::NodeMixin
31
+ # has_list :baar
32
+ # end
33
+ #
34
+ # f = Foo.new
35
+ # n1 = Neo4j::Node.new
36
+ # n2 = Neo4j::Node.new
37
+ # f.baar << n1 << n2
38
+ #
39
+ # n2.list(:baar).next # => n1
40
+ # n2.list(:baar).prev # => f
41
+ # n2.list(:baar).head # => f
42
+ #
43
+ def list(list_name, list_node = nil)
44
+ if list_node
45
+ list_id = "_list_#{list_name}_#{list_node.neo_id}"
46
+ add_list_item_methods(list_id, list_name, list_node)
47
+ else
48
+ list_items = []
49
+ lists(list_name) {|list_item| list_items << list_item}
50
+ list_items[0]
51
+ end
52
+ end
53
+
54
+
55
+ # Returns an array of lists with the given names that this nodes belongs to.
56
+ # Expects a block to yield for each found list
57
+ # That block will be given one parameter - the node with the extra method (see #list method)
58
+ #
59
+ def lists(*list_names)
60
+ list_names.collect! {|n| n.to_sym}
61
+
62
+ rels.both.inject({}) do |res, rel|
63
+ rel_type = rel.relationship_type.to_s
64
+ md = /_list_(\w*)_(\d*)/.match(rel_type)
65
+ next res if md.nil?
66
+ next res unless list_names.empty? || list_names.include?(md[1].to_sym)
67
+ res[rel_type] = [md[1], Neo4j.load_node(md[2])]
68
+ res
69
+ end.each_pair do |rel_id, list_name_and_head_node|
70
+ yield self.add_list_item_methods(rel_id, list_name_and_head_node[0], list_name_and_head_node[1]) # clone ?
71
+ end
72
+ end
73
+
74
+
75
+ def add_list_item_methods(list_id, list_name, head_node) #:no_doc:
76
+ mod = Module.new do
77
+ define_method :head do
78
+ head_node
79
+ end
80
+
81
+ define_method :size do
82
+ head_node["_#{list_name}_size"] || 0
83
+ end
84
+
85
+ define_method :size= do |new_size|
86
+ head_node["_#{list_name}_size"] = new_size
87
+ end
88
+
89
+ define_method :next do
90
+ next_node = rels.outgoing(list_id).nodes.first
91
+ return nil if next_node.nil?
92
+ next_node.add_list_item_methods(list_id, list_name, head_node)
93
+ next_node
94
+ end
95
+
96
+ define_method :next= do |new_next|
97
+ # does it have a next pointer ?
98
+ next_rel = rels.outgoing(list_id).first
99
+ # delete the relationship if exists
100
+ next_rel.delete if (next_rel.nil?)
101
+ rels.outgoing(list_id) << new_next unless new_next.nil?
102
+ nil
103
+ end
104
+
105
+ define_method :prev do
106
+ prev_node = rels.incoming(list_id).nodes.first
107
+ return nil if prev_node.nil?
108
+ prev_node.add_list_item_methods(list_id, list_name, head_node)
109
+ prev_node
110
+ end
111
+
112
+ define_method :prev= do |new_prev|
113
+ # does it have a next pointer ?
114
+ prev_rel = rels.incoming(list_id).first
115
+ # delete the relationship if exists
116
+ prev_rel.delete if (prev_rel.nil?)
117
+ rels.outgoing(list_id) << new_prev unless new_prev.nil?
118
+ nil
119
+ end
120
+ end
121
+
122
+ self.extend mod
123
+ end
124
+
125
+ def add_list_head_methods(list_name) # :nodoc:
126
+ prop_name = "_#{list_name}_size".to_sym
127
+ mod = Module.new do
128
+ define_method :size do
129
+ self[prop_name] || 0
130
+ end
131
+
132
+ define_method :size= do |new_size|
133
+ self[prop_name]=new_size
134
+ end
135
+ end
136
+ self.extend mod
137
+ end
138
+
139
+ end
@@ -0,0 +1,205 @@
1
+ module Neo4j::JavaNodeMixin
2
+
3
+
4
+ # Check if the given relationship exists
5
+ # Returns true if there are one or more relationships from this node to other nodes
6
+ # with the given relationship.
7
+ # It will not return true only because the relationship is defined.
8
+ #
9
+ # ==== Parameters
10
+ # rel_name<#to_s>:: the key and value to be set
11
+ # dir:: optional default :outgoing (either, :outgoing, :incoming, :both)
12
+ #
13
+ # ==== Returns
14
+ # true if one or more relationships exists for the given rel_name and dir
15
+ # otherwise false
16
+ #
17
+ def rel? (rel_name, dir=:outgoing)
18
+ type = org.neo4j.graphdb.DynamicRelationshipType.withName(rel_name.to_s)
19
+ java_dir = _to_java_direction(dir)
20
+ hasRelationship(type, java_dir)
21
+ end
22
+
23
+
24
+ # Returns a Neo4j::Relationships::RelationshipDSL object for accessing relationships from and to this node.
25
+ # The Neo4j::Relationships::RelationshipDSL is an Enumerable that returns Neo4j::RelationshipMixin objects.
26
+ #
27
+ # ==== Returns
28
+ # A Neo4j::Relationships::RelationshipDSL object
29
+ #
30
+ # ==== See Also
31
+ # * Neo4j::Relationships::RelationshipDSL
32
+ # * Neo4j::RelationshipMixin
33
+ #
34
+ # ==== Example
35
+ #
36
+ # person_node.rels.outgoing(:friends).each { ... }
37
+ #
38
+ def rels(direction = :outgoing)
39
+ Neo4j::Relationships::RelationshipDSL.new(self, direction)
40
+ end
41
+
42
+ # Returns a single relationship or nil if none available.
43
+ # If there are more then one relationship of the given type it will raise an exception.
44
+ #
45
+ # ==== Parameters
46
+ # type<#to_s>:: the key and value to be set
47
+ # dir:: optional, default :outgoing (either, :outgoing, :incoming, :both)
48
+ # raw:: optional, true|false (false default). If false return the ruby wrapped relationship object instead of the raw java neo4j obejct.
49
+
50
+ #
51
+ # ==== Returns
52
+ # An object that mixins the Neo4j::RelationshipMixin representing the given relationship type or nil if there are no relationships.
53
+ # If there are more then one relationship it will raise an Exception (java exception of type org.neo4j.graphdb.NotFoundException)
54
+ #
55
+ # ==== See Also
56
+ # * JavaDoc for http://api.neo4j.org/current/org/neo4j/api/core/Node.html#getSingleRelationship(org.neo4j.graphdb.RelationshipType,%20org.neo4j.graphdb.Direction)
57
+ # * Neo4j::RelationshipMixin
58
+ #
59
+ # ==== Example
60
+ #
61
+ # person_node.rel(:address).end_node[:street]
62
+ #
63
+ def rel(rel_name, dir=:outgoing, raw=false)
64
+ java_dir = _to_java_direction(dir)
65
+ rel_type = org.neo4j.graphdb.DynamicRelationshipType.withName(rel_name.to_s)
66
+ rel = getSingleRelationship(rel_type, java_dir)
67
+ return nil if rel.nil?
68
+ return rel.wrapper unless raw
69
+ rel
70
+ end
71
+
72
+
73
+ # Adds an outgoing relationship from this node to another node.
74
+ # Will trigger a relationship_created event.
75
+ #
76
+ # ==== Parameters
77
+ # type:: the relationship type between the nodes (respond_to :to_s)
78
+ # to:: the other node (Neo4j::Node || kind_of?(Neo4j::NodeMixin)
79
+ #
80
+ # ==== Returns
81
+ # a Neo4j::Relationship object
82
+ #
83
+ # === Example
84
+ # nodeA = Neo4j::Node.new
85
+ # nodeB = Neo4j::Node.new
86
+ # nodeA.add_rel(:friend, nodeB)
87
+ #
88
+
89
+ # all creation of relationships uses this method
90
+ def add_rel (type, to, rel_clazz = nil) # :nodoc:
91
+ java_type = org.neo4j.graphdb.DynamicRelationshipType.withName(type.to_s)
92
+ java_rel = createRelationshipTo(to._java_node, java_type)
93
+ # check if we should create a wrapped Ruby Relationship class or use the raw java one.
94
+ rel = (rel_clazz.nil?) ? java_rel : rel_clazz.new(java_rel)
95
+ Neo4j.event_handler.relationship_created(rel)
96
+ @_wrapper.class.indexer.on_relationship_created(@_wrapper, type) if @_wrapper
97
+ rel
98
+ end
99
+
100
+ def _to_java_direction(dir) # :nodoc:
101
+ case dir
102
+ when :outgoing
103
+ org.neo4j.graphdb.Direction::OUTGOING
104
+ when :incoming
105
+ org.neo4j.graphdb.Direction::INCOMING
106
+ when :both
107
+ org.neo4j.graphdb.Direction::BOTH
108
+ else
109
+ raise "Unknown parameter: '#{dir}', only accept :outgoing, :incoming or :both"
110
+ end
111
+ end
112
+
113
+
114
+ # Returns a Neo4j::Relationships::NodeTraverser object for traversing outgoing nodes from and to this node.
115
+ # The Neo4j::Relationships::NodeTraverser is an Enumerable that returns Neo4j::NodeMixin objects.
116
+ #
117
+ # ==== See Also
118
+ # Neo4j::Relationships::NodeTraverser
119
+ #
120
+ # ==== Example
121
+ #
122
+ # person_node.outgoing(:friends).each { ... }
123
+ # person_node.outgoing(:friends).raw(true).each { }
124
+ #
125
+ # The raw false parameter means that the ruby wrapper object will not be loaded, instead the raw Java Neo4j object will be used,
126
+ # it might improve the performance.
127
+ #
128
+ def outgoing(*args)
129
+ Neo4j::Relationships::NodeTraverser.new(self).outgoing(*args)
130
+ end
131
+
132
+ # Returns a Neo4j::Relationships::NodeTraverser object for traversing outgoing nodes from and to this node.
133
+ # The Neo4j::Relationships::NodeTraverser is an Enumerable that returns Neo4j::NodeMixin objects.
134
+ #
135
+ # ==== See Also
136
+ # Neo4j::Relationships::NodeTraverser
137
+ #
138
+ # ==== Example
139
+ #
140
+ # person_node.incoming(:friends).each { ... }
141
+ # person_node.incoming(:friends).raw(true).each { }
142
+ #
143
+ # The raw false parameter means that the ruby wrapper object will not be loaded, instead the raw Java Neo4j object will be used,
144
+ # it might improve the performance.
145
+ #
146
+ def incoming(*args)
147
+ Neo4j::Relationships::NodeTraverser.new(self).incoming(*args)
148
+ end
149
+
150
+
151
+ # Deletes this node.
152
+ # Deletes all relationships as well.
153
+ # Invoking any methods on this node after delete() has returned is invalid and may lead to unspecified behavior.
154
+ #
155
+ # :api: public
156
+ def del
157
+ Neo4j.event_handler.node_deleted(wrapper)
158
+
159
+ # delete outgoing relationships, and check for cascade delete
160
+ rels.outgoing.each { |r| r.del; r.end_node.del if r[:_cascade_delete_outgoing]}
161
+
162
+ rels.incoming.each do |r|
163
+ r.del
164
+ if r[:_cascade_delete_incoming]
165
+ node_id = r[:_cascade_delete_incoming]
166
+ node = Neo4j.load_node(node_id)
167
+ # check node has no outgoing relationships
168
+ no_outgoing = node.rels.outgoing.empty?
169
+ # check node has only incoming relationship with cascade_delete_incoming
170
+ no_incoming = node.rels.incoming.find{|r| !node.ignore_incoming_cascade_delete?(r)}.nil?
171
+ # only cascade delete incoming if no outgoing and no incoming (exception cascade_delete_incoming) relationships
172
+ node.del if no_outgoing and no_incoming
173
+ end
174
+ end
175
+ delete
176
+ @_wrapper.class.indexer.delete_index(self) if @_wrapper
177
+ end
178
+
179
+ # --------------------------------------------------------------------------
180
+ # Debug
181
+ #
182
+
183
+ # Used for debugging purpose, traverse the graph of given depth and direction and prints nodes and relationship information.
184
+ def print(levels = 0, dir = :outgoing)
185
+ print_sub(0, levels, dir)
186
+ end
187
+
188
+ def print_sub(level, max_level, dir) # :nodoc:
189
+ spaces = " " * level
190
+ node_class = (self[:_classname].nil?) ? Neo4j::Node.to_s : self[:_classname]
191
+ node_desc = "#{spaces}neo_id=#{neo_id} #{node_class}"
192
+ props.each_pair {|key, value| next if %w[id].include?(key) or key.match(/^_/) ; node_desc << " #{key}='#{value}'"}
193
+ puts node_desc
194
+
195
+ if (level != max_level)
196
+ rels(dir).each do |rel|
197
+ cascade_desc = ""
198
+ cascade_desc << "cascade in: #{rel[:_cascade_delete_incoming]}" if rel.property?(:_cascade_delete_incoming)
199
+ cascade_desc << "cascade out: #{rel[:_cascade_delete_outgoing]}" if rel.property?(:_cascade_delete_outgoing)
200
+ rel.other_node(self).print_sub(level + 1, max_level, dir)
201
+ end
202
+ end
203
+ end
204
+
205
+ end
@@ -0,0 +1,169 @@
1
+ module Neo4j::JavaPropertyMixin
2
+
3
+ # This is the property to use to map ruby classes to Neo4j Nodes
4
+ CLASSNAME_PROPERTY = "_classname"
5
+
6
+ # Returns the unique id of this node.
7
+ # Ids are garbage collected over time so are only guaranteed to be unique at a specific set of time: if the node is deleted,
8
+ # it's likely that a new node at some point will get the old id. Note: this make node ids brittle as public APIs.
9
+ def neo_id
10
+ getId
11
+ end
12
+
13
+ def _wrapper=(wrapper) # :nodoc:
14
+ @_wrapper = wrapper
15
+ end
16
+
17
+ def _java_node
18
+ self
19
+ end
20
+
21
+ # Returns true if this property container has a property accessible through the given key, false otherwise.
22
+ def property?(key)
23
+ has_property?(key.to_s)
24
+ end
25
+
26
+ # Returns the given property if it exist or nil if it does not exist.
27
+ def [](key)
28
+ return unless property?(key)
29
+ if @_wrapper and @_wrapper.class.marshal?(key)
30
+ Marshal.load(String.from_java_bytes(get_property(key.to_s)))
31
+ else
32
+ get_property(key.to_s)
33
+ end
34
+ end
35
+
36
+ # Sets the given property to given value.
37
+ # Will generate an event if the property does not start with '_' (which could be an internal property, like _classname)
38
+ #
39
+ def []=(key, value)
40
+ k = key.to_s
41
+ old_value = self[key]
42
+
43
+ if value.nil?
44
+ delete_property(k)
45
+ elsif @_wrapper and @_wrapper.class.marshal?(key)
46
+ setProperty(k, Marshal.dump(value).to_java_bytes)
47
+ else
48
+ value = java.lang.Double.new(value) if value.is_a? Float
49
+ setProperty(k, value)
50
+ end
51
+
52
+ if (@_wrapper and k[0, 1] != '_') # do not want events on internal properties
53
+ @_wrapper.class.indexer.on_property_changed(@_wrapper, k) if @_wrapper.class.respond_to? :indexer
54
+ Neo4j.event_handler.property_changed(@_wrapper, k, old_value, value)
55
+ end
56
+
57
+ end
58
+
59
+
60
+ # Removes the property from this node.
61
+ # This is same as setting a property value to nil.
62
+ #
63
+ # For more information see JavaDoc PropertyContainer#removeProperty
64
+ #
65
+ # ==== Example
66
+ # a = Node.new
67
+ # a[:foo] = 2
68
+ # a.delete_property('foo')
69
+ # a[:foo] # => nil
70
+ #
71
+ # ==== Returns
72
+ # <tt>true</tt> if the property was removed, <tt>false</tt> otherwise
73
+ #
74
+ def delete_property (name)
75
+ removed = !removeProperty(name).nil?
76
+ if (removed and @_wrapper and name[0] != '_') # do not want events on internal properties
77
+ @_wrapper.class.indexer.on_property_changed(self, name)
78
+ end
79
+ removed
80
+ end
81
+
82
+ # Returns a hash of all properties.
83
+ #
84
+ # === Returns
85
+ # Hash:: property key and property value with the '_neo_id' as the neo_id
86
+ #
87
+ def props
88
+ ret = {"_neo_id" => getId()}
89
+ iter = getPropertyKeys.iterator
90
+ while (iter.hasNext) do
91
+ key = iter.next
92
+ ret[key] = getProperty(key)
93
+ end
94
+ ret
95
+ end
96
+
97
+ # Updates this node/relationship's properties by using the provided struct/hash.
98
+ # If the option <code>{:strict => true}</code> is given, any properties present on
99
+ # the node but not present in the hash will be removed from the node.
100
+ #
101
+ # === Parameters
102
+ # struct_or_hash<#each_pair>:: the key and value to be set, should respond to 'each_pair'
103
+ # options:: further options defining the context of the update, should be a Hash
104
+ #
105
+ # === Returns
106
+ # self
107
+ #
108
+ def update(struct_or_hash, options={})
109
+ strict = options[:strict]
110
+ keys_to_delete = props.keys - %w(_neo_id _classname) if strict
111
+ struct_or_hash.each_pair do |key, value|
112
+ next if %w(_neo_id _classname).include? key.to_s # do not allow special properties to be mass assigned
113
+ keys_to_delete.delete(key) if strict
114
+ setter_meth = "#{key}=".to_sym
115
+ if @_wrapper && @_wrapper.respond_to?(setter_meth)
116
+ @_wrapper.send(setter_meth, value)
117
+ else
118
+ self[key] = value
119
+ end
120
+ end
121
+ keys_to_delete.each{|key| delete_property(key) } if strict
122
+ self
123
+ end
124
+
125
+
126
+ def equal?(o)
127
+ eql?(o)
128
+ end
129
+
130
+ def eql?(o)
131
+ return false unless o.respond_to?(:neo_id)
132
+ o.neo_id == neo_id
133
+ end
134
+
135
+ def ==(o)
136
+ eql?(o)
137
+ end
138
+
139
+
140
+ # Same as neo_id but returns a String instead of a Fixnum.
141
+ # Used by Ruby on Rails.
142
+ #
143
+ def to_param
144
+ neo_id.to_s
145
+ end
146
+
147
+ # Loads a Neo node wrapper if possible
148
+ # If the neo property '_classname' does not exist then it will map the neo node to the ruby class Neo4j::Node
149
+ def wrapper
150
+ return self unless wrapper?
151
+ @_wrapper ||= wrapper_class.new(self)
152
+ @_wrapper
153
+ end
154
+
155
+ def wrapper?
156
+ property?(CLASSNAME_PROPERTY)
157
+ end
158
+
159
+ def wrapper_class # :nodoc:
160
+ return nil unless wrapper?
161
+ classname = get_property(CLASSNAME_PROPERTY)
162
+ classname.split("::").inject(Kernel) do |container, name|
163
+ container.const_get(name.to_s)
164
+ end
165
+ end
166
+
167
+
168
+ end
169
+