active-orient 0.79 → 0.80

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.
@@ -0,0 +1,70 @@
1
+ Graphen
2
+ ======
3
+
4
+ Die Felder `in` und `out` bündeln die Verknüpfungen zu anderen Vertices.
5
+
6
+ Die Verknüpfungen erfolgen über `Edges`, die wiederum Eigenschaften haben. Zuerst sind die `Edges` Klassen und
7
+ unterscheiden sich üder den Namen. Zusätzlich besteht Vererbung.
8
+
9
+ Beispielgraph
10
+ @db.create_vertex_class :v1
11
+ @db.create_class( :v2 ){ V1 }
12
+ @db.create_edge_class "e1"
13
+ @db.create_class( :e2 ){ E1 }
14
+ @db.create_class( :e3 ){ E1 }
15
+
16
+ vertices = (1..10).map{|y| V2.create node: y}
17
+ E2.create from: V1.create( item: 1 ), to: vertices
18
+
19
+ v1 = V.first.to_human => "<V1[#25:0]: out: {E2=>10}, item : 1>"
20
+ v2 = V.last.to_human => "<V2[#40:0]: in: {E2=>1}, node : 8>"
21
+
22
+ Boardmittel von ActiveOrient
23
+ ----------------------------
24
+
25
+ ## Edges anlisten
26
+
27
+ #### Nur Links
28
+
29
+ v1.edges => ["#49:0", "#50:0", "#51:0", "#52:0", "#53:0", "#54:0", "#55:0", "#56:0", "#49:1", "#50:1"]
30
+ v2.edges => ["#56:0"]
31
+
32
+
33
+ #### Auflösung der Objekte
34
+
35
+ v2.in.map &:to_human => ["<E2: in : #<V2:0x000000000397fcb8>, out : #<V1:0x0000000002ed0060>>"]
36
+
37
+ #### Verfügbare Methoden
38
+ v2.in v2.in_e v2.in_e2 v2.in_e2= v2.in_edges
39
+
40
+
41
+ ### Selektive Auswahl
42
+
43
+ Beispiel: TimeGrid
44
+
45
+ Der Vertex hat folgende Struktur
46
+
47
+ t.to_human
48
+ => "<Tag[82:8927]: in: {TG::DAY_OF=>1, TG::GRID_OF=>1}, out: {ML::L_OHLC=>1, TG::GRID_OF=>1}, value : 25>"
49
+
50
+ dann listet t.detect_edges :out, /ml/ die Edges der ML-Klassen auf:
51
+
52
+ t.detect_edges( :out , /ml/).to_human
53
+ => ["<L_OHLC[#151:16] -i-> #161:22 { } -o-> #82:8927>"]
54
+
55
+
56
+ #### Node
57
+
58
+ Ein Node ist ein direkt über eine Edge verbundener Vertex
59
+
60
+ Q = OrientSupport::OrientQuery
61
+ s= Q.new projection: "expand( outE('e1').in[node <5])"
62
+ s.from = '#25:0'
63
+ s.to_s => select expand( outE('v1').in[node <5]) from #25:0
64
+
65
+ Aufruf in OrientQuery: Q.node Edge_class, condition
66
+
67
+ Fügt den Node in das Porjections-Array ein.
68
+
69
+
70
+
@@ -31,6 +31,7 @@ require 'active_model'
31
31
  require_relative "support/orientquery.rb"
32
32
  require_relative "support/conversions.rb"
33
33
  #require_relative "support/logging.rb"
34
+ require_relative "support/errors.rb"
34
35
  require_relative "base.rb"
35
36
  require_relative "base_properties.rb"
36
37
  require_relative "support/orient.rb"
@@ -55,6 +56,7 @@ require_relative "railtie" if defined?(Rails)
55
56
 
56
57
  module ActiveOrient
57
58
  mattr_accessor :database
59
+ mattr_accessor :db_pool
58
60
  mattr_accessor :database_classes
59
61
  mattr_accessor :default_server
60
62
 
@@ -29,6 +29,7 @@ module ActiveOrient
29
29
  Any Change of the Object is thus synchonized to any allocated variable.
30
30
  =end
31
31
  @@rid_store = Hash.new
32
+ @@mutex = Mutex.new
32
33
 
33
34
  def self.display_rid
34
35
  @@rid_store
@@ -43,8 +44,14 @@ thus a string or a Model-Object is accepted
43
44
  =end
44
45
 
45
46
  def self.remove_rid obj
46
- @@rid_store.delete obj.rid if obj.rid.present?
47
- end
47
+ if obj &.rid.present?
48
+ @@mutex.synchronize do
49
+ @@rid_store.delete obj.rid
50
+ end
51
+ else
52
+ logger.error "Cache entry not removed: #{obj} "
53
+ end
54
+ end
48
55
 
49
56
  def self.get_rid rid
50
57
  rid = rid[1..-1] if rid[0]=='#'
@@ -63,17 +70,20 @@ and the cached obj is returned
63
70
 
64
71
  =end
65
72
  def self.store_rid obj
66
- if obj.rid.present? && obj.rid.rid?
67
- if @@rid_store[obj.rid].present?
68
- @@rid_store[obj.rid].transfer_content from: obj
69
- else
70
- @@rid_store[obj.rid] = obj
71
- end
72
- @@rid_store[obj.rid]
73
- else
74
- nil
75
- end
76
- end
73
+
74
+ @@mutex.synchronize do
75
+ if obj.rid.present? && obj.rid.rid?
76
+ if @@rid_store[obj.rid].present?
77
+ @@rid_store[obj.rid].transfer_content from: obj
78
+ else
79
+ @@rid_store[obj.rid] = obj
80
+ end
81
+ @@rid_store[obj.rid]
82
+ else
83
+ obj
84
+ end
85
+ end
86
+ end
77
87
 
78
88
 
79
89
  # rails compatibility
@@ -91,7 +101,7 @@ The model instance fields are then set automatically from the opts Hash.
91
101
  def initialize attributes = {}, opts = {}
92
102
  logger.progname = "ActiveOrient::Base#initialize"
93
103
  @metadata = Hash.new # HashWithIndifferentAccess.new
94
- @d = nil
104
+ @d = nil if RUBY_PLATFORM == 'java' && attributes.is_a?( Document )
95
105
  run_callbacks :initialize do
96
106
  if RUBY_PLATFORM == 'java' && attributes.is_a?( Document )
97
107
  @d = attributes
@@ -201,7 +211,17 @@ The model instance fields are then set automatically from the opts Hash.
201
211
 
202
212
  iv = attributes[key]
203
213
  if my_metadata( key: key) == "t"
204
- iv =~ /00:00:00/ ? Date.parse(iv) : DateTime.parse(iv)
214
+ # needed in case of
215
+ # obj.date = {some-date}
216
+ # --> perfrom an action on the date without saving prior
217
+ case iv
218
+ when String
219
+ iv =~ /00:00:00/ ? Date.parse(iv) : DateTime.parse(iv)
220
+ when Date, DateTime
221
+ iv
222
+ else
223
+ raise "incompatable type used: #{iv} (#{iv.class}) -- Date or DateTime required"
224
+ end
205
225
  elsif my_metadata( key: key) == "x"
206
226
  iv = ActiveOrient::Model.autoload_object iv
207
227
  elsif iv.is_a? Array
@@ -227,9 +247,9 @@ The model instance fields are then set automatically from the opts Hash.
227
247
  when Array
228
248
  if val.first.is_a?(Hash)
229
249
  v = val.map{ |x| x }
230
- OrientSupport::Array.new(work_on: self, work_with: v )
250
+ OrientSupport::Array.new(work_on: self, work_with: v ){ key_to_sym }
231
251
  else
232
- OrientSupport::Array.new(work_on: self, work_with: val )
252
+ OrientSupport::Array.new(work_on: self, work_with: val ){ key_to_sym }
233
253
  end
234
254
  when Hash
235
255
  if val.keys.include?("@class" )
@@ -280,6 +300,7 @@ The model instance fields are then set automatically from the opts Hash.
280
300
  # end
281
301
  #
282
302
  =begin
303
+ (Experimental)
283
304
  Exclude some properties from loading via get, reload!, get_document, get_record
284
305
  =end
285
306
  def self.exclude_the_following_properties *args
@@ -8,19 +8,19 @@ module ActiveOrient
8
8
 
9
9
  # Default presentation of ActiveOrient::Model-Objects
10
10
 
11
- def to_human
12
- "<#{self.class.to_s.demodulize}: " + content_attributes.map do |attr, value|
13
- v= case value
14
- when ActiveOrient::Model
15
- "< #{self.class.to_.demodulize} : #{value.rrid} >"
16
- when OrientSupport::Array
17
- value.rrid #.to_human #.map(&:to_human).join("::")
18
- else
19
- value.from_orient
20
- end
21
- "%s : %s" % [ attr, v] unless v.nil?
22
- end.compact.sort.join(', ') + ">".gsub('"' , ' ')
23
- end
11
+ def to_human
12
+ "<#{self.class.to_s.demodulize}: " + content_attributes.map do |attr, value|
13
+ v= case value
14
+ when ActiveOrient::Model
15
+ "< #{self.class.to_.demodulize} : #{value.rrid} >"
16
+ when OrientSupport::Array
17
+ value.rrid #.to_human #.map(&:to_human).join("::")
18
+ else
19
+ value.from_orient
20
+ end
21
+ "%s : %s" % [ attr, v] unless v.nil?
22
+ end.compact.sort.join(', ') + ">".gsub('"' , ' ')
23
+ end
24
24
 
25
25
  # Comparison support
26
26
 
@@ -30,8 +30,9 @@ module ActiveOrient
30
30
  attr.to_s =~ /(_count)\z/ || attr.to_s =~ /^in_/ || attr.to_s =~ /^out_/ || [:created_at, :updated_at, :type, :id, :order_id, :contract_id].include?(attr.to_sym)
31
31
  end]
32
32
  end
33
-
34
33
  # return a string ready to include as embedded document
34
+ # used by Model.to_or
35
+ #
35
36
  def embedded
36
37
  { "@type" => 'd', "@class" => self.class.ref_name }
37
38
  .merge(content_attributes)
@@ -3,6 +3,8 @@ module ClassUtils
3
3
 
4
4
  =begin
5
5
  Returns a valid database-class name, nil if the class does not exists
6
+
7
+ works on the cached hash (ActiveOrient.database_classes)
6
8
  =end
7
9
 
8
10
  def classname name_or_class # :nodoc:
@@ -21,9 +23,11 @@ module ClassUtils
21
23
  end
22
24
  end
23
25
  end
24
- def allocate_class_in_ruby db_classname, &b
25
- # retrieve the superclass recursively
26
26
 
27
+ # Updates ActiveOrient.database_classes
28
+ def allocate_class_in_ruby db_classname, &b
29
+
30
+ # first retrieve the superclass recursively
27
31
  unless ActiveOrient.database_classes[ db_classname ].is_a? Class
28
32
 
29
33
  s = get_db_superclass( db_classname )
@@ -46,10 +50,9 @@ module ClassUtils
46
50
  elsif ActiveOrient::Model.namespace.send( :const_get, classname).ancestors.include?( ActiveOrient::Model )
47
51
  ActiveOrient::Model.namespace.send( :const_get, classname)
48
52
  else
49
- t= ActiveOrient::Model.send :const_set, classname, Class.new( superclass )
50
- logger.warn{ "Unable to allocate class #{classname} in Namespace #{ActiveOrient::Model.namespace}"}
51
- logger.warn{ "Allocation took place with namespace ActiveOrient::Model" }
52
- t
53
+ logger.error{ "Unable to allocate class #{classname} in Namespace #{ActiveOrient::Model.namespace}"}
54
+ logger.error{ "Allocation took place with namespace ActiveOrient::Model" }
55
+ ActiveOrient::Model.send :const_set, classname, Class.new( superclass )
53
56
  end
54
57
  the_class.ref_name = db_classname
55
58
  keep_the_dataset = block_given? ? yield( the_class ) : true
@@ -70,7 +73,7 @@ module ClassUtils
70
73
  nil # return-value
71
74
  end
72
75
  else
73
- # return previosly allocated ruby-class
76
+ # return previously allocated ruby-class
74
77
  ActiveOrient.database_classes[db_classname]
75
78
  end
76
79
  end
@@ -161,60 +164,18 @@ Creates one or more edge-classes and allocates the provided properties to each c
161
164
  r = name.map{|n| create_class( n.to_s, properties: properties){ E } }
162
165
  r.size == 1 ? r.pop : r # returns the created classes as array if multible classes are provided
163
166
  end
164
- =begin
165
-
166
- creates a vertex
167
-
168
- =end
169
- def create_vertex( o_class, attributes:{} )
170
-
171
- begin
172
- response = execute(transaction: false, tolerated_error_code: /found duplicated key/) do
173
- "CREATE VERTEX #{classname(o_class)} CONTENT #{attributes.to_orient.to_json}"
174
- end
175
- if response.is_a?(Array) && response.size == 1
176
- response.pop # RETURN_VALUE
177
- else
178
- response # return value (the normal case)
179
- end
180
- rescue ArgumentError => e
181
- puts "CreateVertex:ArgumentError "
182
- puts e.inspect
183
- end # begin
184
-
185
- end
186
167
 
187
- =begin
188
- Deletes the specified vertices and unloads referenced edges from the cache
189
- =end
190
- def delete_vertex *vertex
191
- create_command = -> do
192
- { type: "cmd",
193
- language: 'sql',
194
- command: "DELETE VERTEX #{vertex.map{|x| x.to_orient }.join(',')} "
195
- }
196
- end
197
-
198
- vertex.each{|v| v.edges.each{| e | remove_record_from_hash e} }
199
- execute{ create_command[] }
200
- end
201
168
 
202
169
  =begin
203
170
  Deletes the specified edges and unloads referenced vertices from the cache
204
171
  =end
205
172
  def delete_edge *edge
206
- create_command = -> do
207
- { type: "cmd",
208
- language: 'sql',
209
- command: "DELETE EDGE #{edge.map{|x| x.to_orient }.join(',')} "
210
- }
211
- end
212
173
 
213
174
  edge.each do |r|
214
175
  [r.in, r.out].each{| e | remove_record_from_hash e}
215
176
  remove_record_from_hash r
216
177
  end
217
- execute{ create_command[] }
178
+ execute{ "DELETE EDGE #{edge.map{|x| x.to_orient }.join(',')} "}
218
179
  end
219
180
 
220
181
  private
@@ -13,7 +13,7 @@ if abstract: true is given, only basic classes (Abstact-Classes) are returend
13
13
  ## "ORid" dropped in V2.2
14
14
  extended = ["OIdentity","ORole", "OUser", "OFunction", "_studio"]
15
15
  v3 = ["OGeometryCollection", "OLineString", "OMultiLineString", "OMultiPoint", "OMultiPolygon",
16
- "OPoint", "OPolygon", "ORectangle", "OShape"] ## added in Orentdb 3.0
16
+ "OPoint", "OPolygon", "ORectangle", "OShape", 'OSecurityPolicy'] ## added in Orentdb 3.0 and 3.1
17
17
  if abstract
18
18
  basic
19
19
  else
@@ -33,7 +33,7 @@ To retrieve the class hierarchy from Objects avoid calling `ORD.classname (obj)`
33
33
  =end
34
34
 
35
35
  def class_hierarchy base_class: '', system_classes: nil
36
- @actual_class_hash = get_classes('name', 'superClass') #if requery || @all_classes.blank?
36
+ # @actual_class_hash = get_classes('name', 'superClass') #if requery || @all_classes.blank?
37
37
  fv = ->( s ) { @actual_class_hash.find_all{|x| x['superClass']== s}.map{|v| v['name']} }
38
38
  fx = ->( v ) { fv[v.strip].map{|x| ar = fx[x]; ar.empty? ? x : [x, ar]} }
39
39
  if system_classes.present?
@@ -45,13 +45,15 @@ To retrieve the class hierarchy from Objects avoid calling `ORD.classname (obj)`
45
45
 
46
46
 
47
47
  =begin
48
- Returns an array with all names of the classes of the database. Uses a cached version if possible.
48
+
49
+ Returns an array with all names of the classes of the database.
50
+
51
+ Reads the database-structure and updates the @actual_class_hash (used by class_hierachy and get_db_superclass )
49
52
 
50
- Parameters: system_classes: false|true, requery: false|true
51
53
  =end
52
54
 
53
- def database_classes system_classes: nil, requery: false
54
- class_hierarchy system_classes: system_classes #requery: true
55
+ def database_classes system_classes: nil
56
+ @actual_class_hash = get_classes('name', 'superClass')
55
57
  all_classes = get_classes('name').map(&:values).sort.flatten
56
58
  all_user_classes = all_classes - system_classes()
57
59
 
@@ -65,8 +67,8 @@ Service-Method for Model#OrientdbClass
65
67
  =end
66
68
 
67
69
  def get_db_superclass name #:nodoc:
68
- @actual_class_hash = get_classes( 'name', 'superClass') if @actual_class_hash.nil?
69
- z= @actual_class_hash.find{|x,y| x['name'] == name.to_s }
70
+ # @actual_class_hash = get_classes( 'name', 'superClass') if @actual_class_hash.nil?
71
+ z= @actual_class_hash.find{|x,y| x['name'] == name.to_s }
70
72
  z['superClass'] unless z.nil?
71
73
  end
72
74
 
@@ -74,24 +76,23 @@ Service-Method for Model#OrientdbClass
74
76
  preallocate classes reads any class from the @classes-Array and allocates adequat Ruby-Objects
75
77
  =end
76
78
  def preallocate_classes from_model_dir= nil # :nodoc:
77
- # always scan for E+V model-file and include
79
+ # always scan for E+V model-files and include
78
80
  [E,V].each{|y| y.require_model_file(from_model_dir) }
79
81
 
80
82
  ActiveOrient.database_classes.each do | db_name, the_class |
81
83
  allocate_class_in_ruby( db_name ) do |detected_class|
82
- keep_the_dataset = true
83
- # keep the class if it is already noted in database_classes
84
- if ![E,V].include?(detected_class) &&
85
- !ActiveOrient.database_classes.key( detected_class) &&
86
- !detected_class.require_model_file(from_model_dir) &&
87
- !ActiveOrient::Model.keep_models_without_file
88
-
89
- logger.info{ "#{detected_class.name} --> Class NOT allocated"}
90
- ActiveOrient.database_classes[ detected_class.ref_name ] = "no model file"
91
- keep_the_dataset = false
92
- end
93
- keep_the_dataset # return_value
94
- end # block
84
+ # keep the class if it is already noted in database_classes
85
+ if [E,V].include?(detected_class) ||
86
+ ActiveOrient.database_classes.key( detected_class) ||
87
+ detected_class.require_model_file(from_model_dir) ||
88
+ ActiveOrient::Model.keep_models_without_file
89
+ true # return_value
90
+ else
91
+ logger.info{ "#{detected_class.name} --> Class NOT allocated"}
92
+ ActiveOrient.database_classes[ detected_class.ref_name ] = "no model file"
93
+ false # return_value
94
+ end
95
+ end # block
95
96
  end # each iteration
96
97
  end # def
97
98
 
@@ -37,7 +37,7 @@ returns the active OrientDB-Instance
37
37
  def self.connect **defaults
38
38
  define_namespace namespace: :object
39
39
  ActiveOrient::OrientDB.configure_logger defaults[:logger]
40
- ao = ActiveOrient::OrientDB.new defaults.merge preallocate: false
40
+ ao = ActiveOrient::OrientDB.new **(defaults.merge( preallocate: false))
41
41
  ao.create_class 'E'
42
42
  ao.create_class 'V'
43
43
  ao # return client instance
@@ -45,7 +45,8 @@ returns the active OrientDB-Instance
45
45
  =begin
46
46
  Parameters:
47
47
  yml: hash from config.yml ,
48
- namespace: Class to use as Namespace
48
+ namespace: Class to use as Namespace, one of [ :self, :object, :active_orient ]
49
+
49
50
 
50
51
  A custom Constant can be provided via Block
51
52
 
@@ -55,7 +56,7 @@ i.e.
55
56
  #or
56
57
  ActiveOrient.Init.define_namespace namespace: :self | :object | :active_orient
57
58
  #or
58
- module IBi; end # first declare the Module-Const
59
+ module IB; end # first declare the Module-Const
59
60
  # then assign to the namespace
60
61
  ActiveOrient.Init.define_namespace { IB }
61
62