neo4j-core 3.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +22 -0
  3. data/README.md +332 -0
  4. data/lib/neo4j-core.rb +27 -0
  5. data/lib/neo4j-core/cypher_translator.rb +34 -0
  6. data/lib/neo4j-core/hash_with_indifferent_access.rb +165 -0
  7. data/lib/neo4j-core/helpers.rb +25 -0
  8. data/lib/neo4j-core/label.rb +8 -0
  9. data/lib/neo4j-core/version.rb +5 -0
  10. data/lib/neo4j-embedded.rb +18 -0
  11. data/lib/neo4j-embedded/embedded_database.rb +29 -0
  12. data/lib/neo4j-embedded/embedded_label.rb +80 -0
  13. data/lib/neo4j-embedded/embedded_node.rb +163 -0
  14. data/lib/neo4j-embedded/embedded_relationship.rb +44 -0
  15. data/lib/neo4j-embedded/embedded_session.rb +151 -0
  16. data/lib/neo4j-embedded/property.rb +43 -0
  17. data/lib/neo4j-embedded/to_java.rb +49 -0
  18. data/lib/neo4j-server.rb +10 -0
  19. data/lib/neo4j-server/cypher_label.rb +28 -0
  20. data/lib/neo4j-server/cypher_node.rb +140 -0
  21. data/lib/neo4j-server/cypher_node_uncommited.rb +12 -0
  22. data/lib/neo4j-server/cypher_relationship.rb +82 -0
  23. data/lib/neo4j-server/cypher_response.rb +113 -0
  24. data/lib/neo4j-server/cypher_session.rb +156 -0
  25. data/lib/neo4j-server/cypher_transaction.rb +81 -0
  26. data/lib/neo4j-server/resource.rb +73 -0
  27. data/lib/neo4j/entity_equality.rb +9 -0
  28. data/lib/neo4j/jars/concurrentlinkedhashmap-lru-1.3.1.jar +0 -0
  29. data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  30. data/lib/neo4j/jars/lucene-core-3.6.2.jar +0 -0
  31. data/lib/neo4j/jars/neo4j-cypher-2.0.0-M06.jar +0 -0
  32. data/lib/neo4j/jars/neo4j-kernel-2.0-SNAPSHOT-tests.jar +0 -0
  33. data/lib/neo4j/jars/neo4j-kernel-2.0.0-M06.jar +0 -0
  34. data/lib/neo4j/jars/neo4j-lucene-index-2.0.0-M06.jar +0 -0
  35. data/lib/neo4j/jars/neo4j-management-2.0.0-M06.jar +0 -0
  36. data/lib/neo4j/jars/org.apache.servicemix.bundles.jline-0.9.94_1.jar +0 -0
  37. data/lib/neo4j/jars/parboiled-core-1.1.6.jar +0 -0
  38. data/lib/neo4j/jars/parboiled-scala_2.10-1.1.6.jar +0 -0
  39. data/lib/neo4j/jars/scala-library-2.10.2.jar +0 -0
  40. data/lib/neo4j/label.rb +88 -0
  41. data/lib/neo4j/node.rb +185 -0
  42. data/lib/neo4j/property_container.rb +22 -0
  43. data/lib/neo4j/property_validator.rb +23 -0
  44. data/lib/neo4j/relationship.rb +84 -0
  45. data/lib/neo4j/session.rb +124 -0
  46. data/lib/neo4j/tasks/neo4j_server.rb +131 -0
  47. data/lib/neo4j/transaction.rb +52 -0
  48. data/neo4j-core.gemspec +35 -0
  49. metadata +144 -0
@@ -0,0 +1,25 @@
1
+ module Neo4j::Core
2
+ # wrapps Neo4j ResourceIterator, automatically close it
3
+
4
+ module ArgumentHelper
5
+
6
+ def self.session(args)
7
+ args.last.kind_of?(Neo4j::Session) ? args.pop : Neo4j::Session.current
8
+ end
9
+ end
10
+
11
+ module TxMethods
12
+ def tx_methods(*methods)
13
+ methods.each do |method|
14
+ tx_method = "#{method}_in_tx"
15
+ send(:alias_method, tx_method, method)
16
+ send(:define_method, method) do |*args, &block|
17
+ session = ArgumentHelper.session(args)
18
+ Neo4j::Transaction.run(session.auto_commit?) { send(tx_method, *args, &block) }
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ end
@@ -0,0 +1,8 @@
1
+ module Neo4j::Core
2
+ class Label
3
+ def labels
4
+ get_labels.map{|x| Label.new(x.name) }
5
+ end
6
+ end
7
+
8
+ end
@@ -0,0 +1,5 @@
1
+ module Neo4j
2
+ module Core
3
+ VERSION = "3.0.0.alpha.1"
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ require 'java'
2
+
3
+ # TODO: release neo4j-community jar 2.0
4
+ # Load Neo4j Jars for the jars folder
5
+ jar_folder = File.expand_path('../neo4j/jars', __FILE__)
6
+ jars = Dir.new(jar_folder).entries.find_all { |x| x =~ /\.jar$/ }
7
+ jars.each { |jar| require File.expand_path(jar, jar_folder) }
8
+
9
+ require 'neo4j-embedded/to_java'
10
+ require 'neo4j-embedded/property'
11
+ require 'neo4j-embedded/embedded_session'
12
+ require 'neo4j-embedded/embedded_label'
13
+ require 'neo4j-embedded/embedded_node'
14
+ require 'neo4j-embedded/embedded_relationship'
15
+ require 'neo4j-embedded/embedded_label'
16
+
17
+ # TODO replace this with https://github.com/intridea/hashie gem
18
+ require 'neo4j-core/hash_with_indifferent_access'
@@ -0,0 +1,29 @@
1
+ module Neo4j::Embedded
2
+ class EmbeddedDatabase
3
+
4
+ class Error < StandardError
5
+ end
6
+
7
+ class << self
8
+ def connect(db_location, config={})
9
+ if Neo4j::Session.current.respond_to?(:db_location) && Neo4j::Session.current.db_location == db_location
10
+ return Neo4j::Session.current
11
+ else
12
+ EmbeddedSession.new(db_location, config)
13
+ end
14
+ end
15
+
16
+ def create_db(db_location)
17
+ puts "Start embedded Neo4j db at #{db_location}"
18
+ factory = Java::OrgNeo4jGraphdbFactory::GraphDatabaseFactory.new
19
+ factory.newEmbeddedDatabase(db_location)
20
+ end
21
+
22
+ def factory_class
23
+ Java::OrgNeo4jGraphdbFactory::GraphDatabaseFactory
24
+ Java::OrgNeo4jTest::ImpermanentGraphDatabase
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,80 @@
1
+ module Neo4j::Embedded
2
+ class EmbeddedLabel
3
+ extend Neo4j::Core::TxMethods
4
+ attr_reader :name
5
+ JAVA_CLASS = Java::OrgNeo4jGraphdb::DynamicLabel
6
+
7
+ def initialize(session, name)
8
+ @name = name.to_sym
9
+ @session = session
10
+ end
11
+
12
+ def to_s
13
+ @name
14
+ end
15
+
16
+ def find_nodes(key=nil, value=nil)
17
+ begin
18
+ iterator = _find_nodes(key,value)
19
+ iterator.to_a.map{|n| n.wrapper}
20
+ ensure
21
+ iterator && iterator.close
22
+ end
23
+ end
24
+ tx_methods :find_nodes
25
+
26
+ def _find_nodes(key=nil, value=nil)
27
+ if (key)
28
+ @session.graph_db.find_nodes_by_label_and_property(as_java, key, value).iterator
29
+ else
30
+ ggo = Java::OrgNeo4jTooling::GlobalGraphOperations.at(@session.graph_db)
31
+ ggo.getAllNodesWithLabel(as_java).iterator
32
+ end
33
+
34
+ end
35
+
36
+ def as_java
37
+ self.class.as_java(@name.to_s)
38
+ end
39
+
40
+ def create_index(*properties)
41
+ index_creator = @session.graph_db.schema.index_for(as_java)
42
+ # we can also use the PropertyConstraintCreator here
43
+ properties.inject(index_creator) {|creator, key| creator.on(key.to_s)}.create
44
+ end
45
+ tx_methods :create_index
46
+
47
+ def indexes()
48
+ {
49
+ property_keys: @session.graph_db.schema.indexes(as_java).map do |index_def|
50
+ index_def.property_keys.map{|x| x.to_sym}
51
+ end
52
+ }
53
+ end
54
+ tx_methods :indexes
55
+
56
+ def drop_index(*properties)
57
+ @session.graph_db.schema.indexes(as_java).each do |index_def|
58
+ # at least one match, TODO
59
+ keys = index_def.property_keys.map{|x| x.to_sym}
60
+ index_def.drop if (properties - keys).count < properties.count
61
+ end
62
+
63
+ end
64
+ tx_methods :drop_index
65
+
66
+ class << self
67
+
68
+ def as_java(labels)
69
+ if labels.is_a?(Array)
70
+ return nil if labels.empty?
71
+ labels.inject([]) { |result, label| result << JAVA_CLASS.label(label.to_s) }.to_java(JAVA_CLASS)
72
+ else
73
+ JAVA_CLASS.label(labels.to_s)
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ end
80
+
@@ -0,0 +1,163 @@
1
+ module Neo4j::Embedded
2
+ class RelsIterator
3
+ include Enumerable
4
+ extend Neo4j::Core::TxMethods
5
+
6
+ def initialize(node, match)
7
+ @node = node
8
+ @match = match
9
+ end
10
+
11
+ def each(&block)
12
+ @node._rels(@match).each {|r| block.call(r)}
13
+ end
14
+ tx_methods :each
15
+
16
+ def empty?
17
+ first == nil
18
+ end
19
+
20
+ end
21
+
22
+ class NodesIterator
23
+ include Enumerable
24
+ extend Neo4j::Core::TxMethods
25
+
26
+ def initialize(node, match)
27
+ @node = node
28
+ @match = match
29
+ end
30
+
31
+ def each(&block)
32
+ @node._rels(@match).each {|r| block.call(r.other_node(@node))}
33
+ end
34
+ tx_methods :each
35
+
36
+ def empty?
37
+ first == nil
38
+ end
39
+
40
+ end
41
+
42
+ class EmbeddedNode
43
+ class << self
44
+ # This method is used to extend a Java Neo4j class so that it includes the same mixins as this class.
45
+ def extend_java_class(java_clazz)
46
+ java_clazz.class_eval do
47
+ include Neo4j::Embedded::Property
48
+ include Neo4j::EntityEquality
49
+ extend Neo4j::Core::TxMethods
50
+
51
+ def exist?
52
+ !!graph_database.get_node_by_id(neo_id)
53
+ rescue Java::OrgNeo4jGraphdb.NotFoundException
54
+ nil
55
+ end
56
+ tx_methods :exist?
57
+
58
+ def labels
59
+ iterator = _labels.iterator
60
+ iterator.to_a.map{|x| x.name.to_sym}
61
+ ensure
62
+ iterator && iterator.close
63
+ end
64
+ tx_methods :labels
65
+
66
+ alias_method :_labels, :getLabels
67
+
68
+ def del
69
+ _rels.each { |r| r.del }
70
+ delete
71
+ nil
72
+ end
73
+ tx_methods :del
74
+
75
+ def create_rel(type, other_node, props = nil)
76
+ rel = create_relationship_to(other_node, ToJava.type_to_java(type))
77
+ props.each_pair { |k, v| rel[k] = v } if props
78
+ rel
79
+ end
80
+ tx_methods :create_rel
81
+
82
+
83
+ def rels(match={})
84
+ RelsIterator.new(self, match)
85
+ end
86
+
87
+ def nodes(match={})
88
+ NodesIterator.new(self, match)
89
+ end
90
+
91
+ def node(match={})
92
+ rel = _rel(match)
93
+ rel && rel.other_node(self)
94
+ end
95
+ tx_methods :node
96
+
97
+ def rel?(match={})
98
+ _rels(match).has_next
99
+ end
100
+ tx_methods :rel?
101
+
102
+ def rel(match={})
103
+ _rel(match)
104
+ end
105
+ tx_methods :rel
106
+
107
+ def _rel(match={})
108
+ dir = match[:dir] || :both
109
+ rel_type = match[:type]
110
+
111
+ rel = if rel_type
112
+ get_single_relationship(ToJava.type_to_java(rel_type), ToJava.dir_to_java(dir))
113
+ else
114
+ iter = get_relationships(ToJava.dir_to_java(dir)).iterator
115
+ if (iter.has_next)
116
+ first = iter.next
117
+ raise "Expected to only find one relationship from node #{neo_id} matching #{match.inspect}" if iter.has_next
118
+ first
119
+ end
120
+ end
121
+
122
+ between_id = match[:between] && match[:between].neo_id
123
+
124
+ if (rel && between_id)
125
+ rel.other_node(self).neo_id == between_id ? rel : nil
126
+ else
127
+ rel
128
+ end
129
+ end
130
+
131
+ def _rels(match={})
132
+ dir = match[:dir] || :both
133
+ rel_type = match[:type]
134
+
135
+ rels = if rel_type
136
+ get_relationships(ToJava.type_to_java(rel_type), ToJava.dir_to_java(dir)).iterator
137
+ else
138
+ get_relationships(ToJava.dir_to_java(dir)).iterator
139
+ end
140
+
141
+ between_id = match[:between] && match[:between].neo_id
142
+
143
+ if (between_id)
144
+ rels.find_all{|r| r.end_node.neo_id == between_id || r.start_node.neo_id == between_id}
145
+ else
146
+ rels
147
+ end
148
+
149
+ end
150
+
151
+ def class
152
+ Neo4j::Node
153
+ end
154
+ #include Neo4j::Core::Label
155
+ include Neo4j::Wrapper
156
+ end
157
+ end
158
+ end
159
+
160
+ extend_java_class(Java::OrgNeo4jKernelImplCore::NodeProxy)
161
+ end
162
+
163
+ end
@@ -0,0 +1,44 @@
1
+ module Neo4j::Embedded
2
+ class EmbeddedRelationship
3
+ class << self
4
+ # This method is used to extend a Java Neo4j class so that it includes the same mixins as this class.
5
+ def extend_java_class(java_clazz)
6
+ java_clazz.class_eval do
7
+ include Neo4j::Embedded::Property
8
+ include Neo4j::EntityEquality
9
+ extend Neo4j::Core::TxMethods
10
+
11
+ alias_method :other_node, :getOtherNode
12
+
13
+ def exist?
14
+ !!graph_database.get_relationship_by_id(neo_id)
15
+ rescue Java::OrgNeo4jGraphdb.NotFoundException
16
+ nil
17
+ end
18
+ tx_methods :exist?
19
+
20
+ def start_node
21
+ getStartNode
22
+ end
23
+ tx_methods :start_node
24
+
25
+ def del
26
+ delete
27
+ end
28
+ tx_methods :del
29
+
30
+ def end_node
31
+ getEndNode
32
+ end
33
+ tx_methods :end_node
34
+
35
+ end
36
+ end
37
+ end
38
+
39
+ extend_java_class(Java::OrgNeo4jKernelImplCore::RelationshipProxy)
40
+
41
+ end
42
+
43
+
44
+ end
@@ -0,0 +1,151 @@
1
+ # Plugin
2
+
3
+ Neo4j::Session.register_db(:embedded_db) do |*args|
4
+ Neo4j::Embedded::EmbeddedSession.new(*args)
5
+ end
6
+
7
+ Neo4j::Session.register_db(:impermanent_db) do |*args|
8
+ Neo4j::Embedded::EmbeddedImpermanentSession.new(*args)
9
+ end
10
+
11
+ module Neo4j::Embedded
12
+ class EmbeddedSession < Neo4j::Session
13
+
14
+ class Error < StandardError
15
+ end
16
+
17
+ attr_reader :graph_db, :db_location
18
+ extend Forwardable
19
+ extend Neo4j::Core::TxMethods
20
+ def_delegator :@graph_db, :begin_tx
21
+
22
+
23
+ def initialize(db_location, config={})
24
+ @db_location = db_location
25
+ @auto_commit = !!config[:auto_commit]
26
+ Neo4j::Session.register(self)
27
+ end
28
+
29
+ def start
30
+ raise Error.new("Embedded Neo4j db is already running") if running?
31
+ puts "Start embedded Neo4j db at #{db_location}"
32
+ factory = Java::OrgNeo4jGraphdbFactory::GraphDatabaseFactory.new
33
+ @graph_db = factory.newEmbeddedDatabase(db_location)
34
+ end
35
+
36
+ def factory_class
37
+ Java::OrgNeo4jGraphdbFactory::GraphDatabaseFactory
38
+ Java::OrgNeo4jTest::ImpermanentGraphDatabase
39
+ end
40
+
41
+ def close
42
+ super
43
+ shutdown
44
+ end
45
+
46
+ def shutdown
47
+ graph_db && graph_db.shutdown
48
+ @graph_db = nil
49
+ end
50
+
51
+ def running?
52
+ !!graph_db
53
+ end
54
+
55
+ def create_label(name)
56
+ EmbeddedLabel.new(self, name)
57
+ end
58
+
59
+ def load_node(neo_id)
60
+ _load_node(neo_id)
61
+ end
62
+ tx_methods :load_node
63
+
64
+ # Same as load but does not return the node as a wrapped Ruby object.
65
+ #
66
+ def _load_node(neo_id)
67
+ return nil if neo_id.nil?
68
+ @graph_db.get_node_by_id(neo_id.to_i)
69
+ rescue Java::OrgNeo4jGraphdb.NotFoundException
70
+ nil
71
+ end
72
+
73
+ def load_relationship(neo_id)
74
+ _load_relationship(neo_id)
75
+ end
76
+ tx_methods :load_relationship
77
+
78
+ def _load_relationship(neo_id)
79
+ return nil if neo_id.nil?
80
+ @graph_db.get_relationship_by_id(neo_id.to_i)
81
+ rescue Java::OrgNeo4jGraphdb.NotFoundException
82
+ nil
83
+ end
84
+
85
+ def query(*params, &query_dsl)
86
+ begin
87
+ result = super
88
+ raise CypherError.new(result.error_msg, result.error_code, result.error_status) if result.respond_to?(:error?) && result.error?
89
+ # TODO ugly, the server database must convert the result
90
+ result.respond_to?(:to_hash_enumeration) ? result.to_hash_enumeration : result.to_a
91
+ rescue Exception => e
92
+ raise CypherError.new(e,nil,nil)
93
+ end
94
+ end
95
+
96
+ def find_all_nodes(label)
97
+ EmbeddedLabel.new(self, label).find_nodes
98
+ end
99
+
100
+ def find_nodes(label, key, value)
101
+ EmbeddedLabel.new(self, label).find_nodes(key,value)
102
+ end
103
+
104
+ # Performs a cypher query with given string.
105
+ # Remember that you should close the resource iterator.
106
+ # @param [String] q the cypher query as a String
107
+ # @return (see #query)
108
+ def _query(q, params={})
109
+ engine = Java::OrgNeo4jCypherJavacompat::ExecutionEngine.new(@graph_db)
110
+ result = engine.execute(q, Neo4j::Core::HashWithIndifferentAccess.new(params))
111
+ Neo4j::Cypher::ResultWrapper.new(result)
112
+ end
113
+
114
+ def query_default_return
115
+ " RETURN n"
116
+ end
117
+
118
+ def _query_or_fail(q)
119
+ engine = Java::OrgNeo4jCypherJavacompat::ExecutionEngine.new(@graph_db)
120
+ engine.execute(q)
121
+ end
122
+
123
+ def search_result_to_enumerable(result)
124
+ result.map {|column| column['n']}
125
+ end
126
+
127
+ def create_node(properties = nil, labels=[])
128
+ if labels.empty?
129
+ _java_node = graph_db.create_node
130
+ else
131
+ labels = EmbeddedLabel.as_java(labels)
132
+ _java_node = graph_db.create_node(labels)
133
+ end
134
+ properties.each_pair { |k, v| _java_node[k]=v } if properties
135
+ _java_node
136
+ end
137
+ tx_methods :create_node
138
+
139
+ end
140
+
141
+ class EmbeddedImpermanentSession < EmbeddedSession
142
+ def start
143
+ raise Error.new("Embedded Neo4j db is already running") if running?
144
+ #puts "Start test impermanent embedded Neo4j db at #{db_location}"
145
+ @graph_db = Java::OrgNeo4jTest::TestGraphDatabaseFactory.new.newImpermanentDatabase()
146
+ end
147
+ end
148
+
149
+
150
+
151
+ end