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

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.
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
-