neo4j 1.0.0.beta.20 → 3.0.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +243 -0
  3. data/CONTRIBUTORS +12 -0
  4. data/Gemfile +10 -11
  5. data/README.md +23 -0
  6. data/bin/neo4j-jars +33 -0
  7. data/config/locales/en.yml +5 -0
  8. data/config/neo4j/config.yml +98 -0
  9. data/lib/neo4j.rb +28 -68
  10. data/lib/neo4j/active_node.rb +60 -0
  11. data/lib/neo4j/active_node/callbacks.rb +41 -0
  12. data/lib/neo4j/active_node/has_n.rb +138 -0
  13. data/lib/neo4j/active_node/has_n/decl_rel.rb +236 -0
  14. data/lib/neo4j/active_node/has_n/nodes.rb +82 -0
  15. data/lib/neo4j/active_node/identity.rb +28 -0
  16. data/lib/neo4j/active_node/initialize.rb +24 -0
  17. data/lib/neo4j/active_node/labels.rb +142 -0
  18. data/lib/neo4j/active_node/persistence.rb +193 -0
  19. data/lib/neo4j/active_node/property.rb +41 -0
  20. data/lib/neo4j/active_node/rels.rb +11 -0
  21. data/lib/neo4j/active_node/validations.rb +51 -0
  22. data/lib/neo4j/railtie.rb +40 -0
  23. data/lib/neo4j/version.rb +1 -1
  24. data/lib/neo4j/wrapper.rb +25 -0
  25. data/neo4j.gemspec +25 -15
  26. metadata +136 -149
  27. data/README.rdoc +0 -135
  28. data/lib/generators/neo4j.rb +0 -65
  29. data/lib/generators/neo4j/model/model_generator.rb +0 -39
  30. data/lib/generators/neo4j/model/templates/model.erb +0 -7
  31. data/lib/neo4j/config.rb +0 -153
  32. data/lib/neo4j/database.rb +0 -56
  33. data/lib/neo4j/equal.rb +0 -21
  34. data/lib/neo4j/event_handler.rb +0 -116
  35. data/lib/neo4j/index/class_methods.rb +0 -62
  36. data/lib/neo4j/index/index.rb +0 -33
  37. data/lib/neo4j/index/indexer.rb +0 -312
  38. data/lib/neo4j/index/indexer_registry.rb +0 -68
  39. data/lib/neo4j/index/lucene_query.rb +0 -191
  40. data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  41. data/lib/neo4j/jars/lucene-core-3.0.2.jar +0 -0
  42. data/lib/neo4j/jars/neo4j-index-1.2-1.2.M03.jar +0 -0
  43. data/lib/neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar +0 -0
  44. data/lib/neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar +0 -0
  45. data/lib/neo4j/load.rb +0 -21
  46. data/lib/neo4j/mapping/class_methods/init_node.rb +0 -50
  47. data/lib/neo4j/mapping/class_methods/init_rel.rb +0 -35
  48. data/lib/neo4j/mapping/class_methods/property.rb +0 -80
  49. data/lib/neo4j/mapping/class_methods/relationship.rb +0 -90
  50. data/lib/neo4j/mapping/class_methods/root.rb +0 -31
  51. data/lib/neo4j/mapping/class_methods/rule.rb +0 -295
  52. data/lib/neo4j/mapping/decl_relationship_dsl.rb +0 -214
  53. data/lib/neo4j/mapping/has_n.rb +0 -83
  54. data/lib/neo4j/mapping/node_mixin.rb +0 -97
  55. data/lib/neo4j/mapping/relationship_mixin.rb +0 -117
  56. data/lib/neo4j/model.rb +0 -4
  57. data/lib/neo4j/neo4j.rb +0 -95
  58. data/lib/neo4j/node.rb +0 -131
  59. data/lib/neo4j/node_mixin.rb +0 -4
  60. data/lib/neo4j/node_relationship.rb +0 -149
  61. data/lib/neo4j/node_traverser.rb +0 -157
  62. data/lib/neo4j/property.rb +0 -111
  63. data/lib/neo4j/rails/finders.rb +0 -121
  64. data/lib/neo4j/rails/lucene_connection_closer.rb +0 -19
  65. data/lib/neo4j/rails/mapping/property.rb +0 -35
  66. data/lib/neo4j/rails/model.rb +0 -324
  67. data/lib/neo4j/rails/railtie.rb +0 -16
  68. data/lib/neo4j/rails/transaction.rb +0 -67
  69. data/lib/neo4j/rails/tx_methods.rb +0 -15
  70. data/lib/neo4j/rails/validations/non_nil.rb +0 -11
  71. data/lib/neo4j/rails/validations/uniqueness.rb +0 -31
  72. data/lib/neo4j/rails/value.rb +0 -124
  73. data/lib/neo4j/rails/value_properties.rb +0 -29
  74. data/lib/neo4j/relationship.rb +0 -169
  75. data/lib/neo4j/relationship_mixin.rb +0 -4
  76. data/lib/neo4j/relationship_traverser.rb +0 -92
  77. data/lib/neo4j/to_java.rb +0 -31
  78. data/lib/neo4j/transaction.rb +0 -68
  79. data/lib/neo4j/type_converters.rb +0 -98
@@ -1,4 +0,0 @@
1
- module Neo4j
2
- # make an alias so that we don't have to write the long name Neo4j::Mapping::NodeMixin
3
- NodeMixin = Neo4j::Mapping::NodeMixin
4
- end
@@ -1,149 +0,0 @@
1
- module Neo4j
2
-
3
-
4
- module NodeRelationship
5
- include ToJava
6
-
7
-
8
- # Returns the outgoing nodes for this node.
9
- #
10
- # ==== Returns
11
- # a Neo4j::NodeTraverser which can be used to further specify which nodes should be included
12
- # in traversal by using the <tt>depth</tt>, <tt>filter</tt> and <tt>prune</tt> methods.
13
- #
14
- # ==== Examples
15
- # # Find all my friends (nodes of depth 1 of type <tt>friends</tt>)
16
- # me.outgoing(:friends).each {|friend| puts friend[:name]}
17
- #
18
- # # Find all my friends and their friends (nodes of depth 1 of type <tt>friends</tt>)
19
- # # me.outgoing(:friends).depth(2).each {|friend| puts friend[:name]}
20
- #
21
- # # Find all my friends and include my self in the result
22
- # me.outgoing(:friends).depth(4).include_start_node.each {...}
23
- #
24
- # # Find all my friends friends friends, etc. at any depth
25
- # me.outgoing(:friends).depth(:all).each {...}
26
- #
27
- # # Find all my friends friends but do not include my friends (only depth == 2)
28
- # me.outgoing(:friends).depth(2).filter{|path| path.length == 2}
29
- #
30
- # # Find all my friends but 'cut off' some parts of the traversal path
31
- # me.outgoing(:friends).depth(42).prune(|path| an_expression_using_path_returning_true_false }
32
- #
33
- # # Find all my friends and work colleges
34
- # me.outgoing(:friends).outgoing(:work).each {...}
35
- #
36
- # Of course all the methods <tt>outgoing</tt>, <tt>incoming</tt>, <tt>both</tt>, <tt>depth</tt>, <tt>include_start_node</tt>, <tt>filter</tt>, and <tt>prune</tt> can be combined.
37
- #
38
- def outgoing(type)
39
- if type
40
- NodeTraverser.new(self).outgoing(type)
41
- else
42
- raise "not implemented yet"
43
- NodeTraverser.new(self)
44
- end
45
- end
46
-
47
-
48
- # Returns the incoming nodes of given type(s).
49
- #
50
- # See #outgoing
51
- #
52
- def incoming(type)
53
- if type
54
- NodeTraverser.new(self).incoming(type)
55
- else
56
- raise "not implemented yet"
57
- NodeTraverser.new(self)
58
- end
59
- end
60
-
61
- # Returns both incoming and outgoing nodes of given types(s)
62
- #
63
- # If a type is not given then it will return all types of relationships.
64
- #
65
- # See #outgoing
66
- #
67
- def both(type=nil)
68
- if type
69
- NodeTraverser.new(self).both(type)
70
- else
71
- NodeTraverser.new(self) # default is both
72
- end
73
- end
74
-
75
-
76
- # Returns an enumeration of relationship objects.
77
- # It always returns relationship of depth one.
78
- #
79
- # See Neo4j::Relationship
80
- #
81
- # ==== Examples
82
- # # Return both incoming and outgoing relationships
83
- # me.rels(:friends, :work).each {|relationship|...}
84
- #
85
- # # Only return outgoing relationship of given type
86
- # me.rels(:friends).outgoing.first.end_node # => my friend node
87
- #
88
- def rels(*type)
89
- RelationshipTraverser.new(self, type, :both)
90
- end
91
-
92
-
93
- # Returns the only relationship of a given type and direction that is attached to this node, or null.
94
- # This is a convenience method that is used in the commonly occuring situation where a node has exactly zero or
95
- # one relationships of a given type and direction to another node.
96
- # Typically this invariant is maintained by the rest of the code: if at any time more than one such relationships
97
- # exist, it is a fatal error that should generate an unchecked exception. This method reflects that semantics and
98
- # returns either:
99
- #
100
- # * nil if there are zero relationships of the given type and direction,
101
- # * the relationship if there's exactly one, or
102
- # * raise an exception in all other cases.
103
- def rel(dir, type)
104
- result = _rel(dir, type)
105
- result && result.wrapper
106
- end
107
-
108
- # Same as rel but does not return a ruby wrapped object but instead returns the Java object.
109
- def _rel(dir, type)
110
- get_single_relationship(type_to_java(type), dir_to_java(dir))
111
- end
112
-
113
- # Returns the raw java neo4j relationship object.
114
- def _rels(dir=:both, *types)
115
- if types.size > 1
116
- java_types = types.inject([]) { |result, type| result << type_to_java(type) }.to_java(:'org.neo4j.graphdb.RelationshipType')
117
- get_relationships(java_types)
118
- elsif types.size == 1
119
- get_relationships(type_to_java(types[0], dir_to_java(dir)))
120
- elsif dir == :both
121
- get_relationships(dir_to_java(dir))
122
- else
123
- raise "illegal argument, does not accept #{dir} #{types.join(',')} - only dir=:both for any relationship types"
124
- end
125
- end
126
-
127
- # Check if the given relationship exists
128
- # Returns true if there are one or more relationships from this node to other nodes
129
- # with the given relationship.
130
- #
131
- # ==== Parameters
132
- # type:: the key and value to be set, default any type
133
- # dir:: optional default :both (either, :outgoing, :incoming, :both)
134
- #
135
- # ==== Returns
136
- # true if one or more relationships exists for the given type and dir
137
- # otherwise false
138
- #
139
- def rel? (type=nil, dir=:both)
140
- if type
141
- hasRelationship(type_to_java(type), dir_to_java(dir))
142
- else
143
- hasRelationship
144
- end
145
- end
146
-
147
- end
148
-
149
- end
@@ -1,157 +0,0 @@
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
@@ -1,111 +0,0 @@
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
@@ -1,121 +0,0 @@
1
- module Neo4j
2
- module Rails
3
- module Finders
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- rule :_all
8
- end
9
-
10
- module ClassMethods
11
- # overwrite the index method to add find_by_xxx class methods
12
- def index(*args)
13
- field = args.first
14
- module_eval <<-RUBY, __FILE__, __LINE__
15
- def self.all_by_#{field}(value)
16
- find_with_indexer("#{field}: \\"\#{value}\\"")
17
- end
18
-
19
- def self.find_by_#{field}(value)
20
- all_by_#{field}(value).first
21
- end
22
- RUBY
23
-
24
- super
25
- end
26
-
27
- # load an id or array of ids from the database
28
- def load(*ids)
29
- result = ids.map { |id| Neo4j::Node.load(id) }
30
- if ids.length == 1
31
- result.first
32
- else
33
- result
34
- end
35
- end
36
-
37
- # Behave like the ActiveRecord query interface
38
-
39
- # Handle Model.find(params[:id])
40
-
41
- # Model.find
42
- # Model.find(:first)
43
-
44
- # Model.find("1")
45
- # Model.find(1)
46
-
47
- # Model.find("name: test")
48
- # Model.find(:name => "test")
49
-
50
- # Model.find(:first, "name: test")
51
- # Model.find(:first, { :name => "test" })
52
-
53
- # Model.find(:first, :conditions => "name: test")
54
- # Model.find(:first, :conditions => { :name => "test" })
55
-
56
- # Model.find(:all, "name: test")
57
- # Model.find(:all, { :name => "test" })
58
-
59
- # Model.find(:all, :conditions => "name: test")
60
- # Model.find(:all, :conditions => { :name => "test" })
61
- def find(*args)
62
- case args.first
63
- when :all, :first
64
- kind = args.shift
65
- send(kind, *args)
66
- else
67
- find_with_ids(*args) or first(*args)
68
- end
69
- end
70
-
71
- def all(*args)
72
- if args.empty?
73
- # use the _all rule to recover all the stored instances of this node
74
- _all
75
- else
76
- args = normalize_args(*args)
77
- # handle the special case of a search by id
78
- if args.first.is_a?(Hash) && args.first[:id]
79
- [find_with_ids(args.first[:id])].flatten
80
- else
81
- find_with_indexer(*args)
82
- end
83
- end
84
- end
85
-
86
- def first(*args)
87
- all(*args).first
88
- end
89
-
90
- protected
91
- def find_with_ids(*args)
92
- if ((args.first.is_a?(String) || args.first.is_a?(Integer)) && args.first.to_i > 0)
93
- load(*args.map { |p| p.to_i })
94
- end
95
- end
96
-
97
- def find_with_indexer(*args)
98
- hits = _indexer.find(*args)
99
- # We need to save this so that the Rack Neo4j::Rails:LuceneConnection::Closer can close it
100
- Thread.current[:neo4j_lucene_connection] ||= []
101
- Thread.current[:neo4j_lucene_connection] << hits
102
- hits
103
- end
104
-
105
- def normalize_args(*args)
106
- options = args.extract_options!
107
-
108
- if options.present?
109
- if options[:conditions]
110
- args << options[:conditions]
111
- else
112
- args << options
113
- end
114
- end
115
- args
116
- end
117
- end
118
- end
119
- end
120
- end
121
-