safrano 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e43512da576932288321a8e821e26fa9c70d578f52562f6a343bfe3c3711bae
4
- data.tar.gz: e2c00621b792634355f99d2025fada0d05cd44666516d916aa2546fb72f5157f
3
+ metadata.gz: c341ac75683820fb122f94d0f45abe31258a48e3366db3ed4547c088a2afdab9
4
+ data.tar.gz: 7d0ddebfd2b00738235514e5f1544f22d8a20fa6c2b4cde5b9066af4251e50be
5
5
  SHA512:
6
- metadata.gz: 8ff433c52ec4406198b0988e122213f0af36a8f1a06b2eb1d2ebfc2c3736db5f8c575fa86e04b8ac9801d4d4fb363edc468c3078b3f93c66313497739ffc3c2e
7
- data.tar.gz: 59ebba62c9a7e81496a651473fa9469d843409dab4c1703221f897425136fe02439ea400e17124a910de599378056b7b21758815d734c9807778193c791e3286
6
+ metadata.gz: 220d3948fc7a80c1c3403fa3d98eab40880c2d80dd7745f003ea93b27581641df1cbcec4d7bf6d471b7c18843c6054addabb9635382f86e60531679aa1738c21
7
+ data.tar.gz: 4731134f71abd2f5e4b044ac5853d8f30a951c6c434fd2861fd5f59e3f5cdda1916f5ba5c3ff05030572a2f58c4a46d75c5e8289d1d3d96778d0df8a8f6504c8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Safrano
2
4
  module CoreIncl
3
5
  module REXML
@@ -6,7 +8,7 @@ module Safrano
6
8
  def to_pretty_xml
7
9
  formatter = ::REXML::Formatters::Pretty.new(2)
8
10
  formatter.compact = true
9
- formatter.write(root, strio = '')
11
+ formatter.write(root, strio = ::String.new)
10
12
  strio
11
13
  end
12
14
  end
@@ -1,3 +1,4 @@
1
1
  require_relative 'REXML/Document/output'
2
+ require 'rexml/document'
2
3
 
3
4
  REXML::Document.include Safrano::CoreIncl::REXML::Document::Output
@@ -32,8 +32,7 @@ module Safrano
32
32
  attr_reader :oarg
33
33
 
34
34
  def initialize(ostr, jh)
35
- ostr.strip!
36
- @orderp = ostr
35
+ @orderp = ostr.strip
37
36
  @jh = jh
38
37
  build_oarg if @orderp
39
38
  end
data/lib/odata/expand.rb CHANGED
@@ -82,9 +82,8 @@ module Safrano
82
82
  # Note: if you change this method, please also update arity_full_monkey?
83
83
  # see below
84
84
  def initialize(expandstr, model)
85
- expandstr.strip!
86
85
  @model = model
87
- @expandp = expandstr
86
+ @expandp = expandstr.strip
88
87
 
89
88
  @exstrlist = expandstr.split(COMASPLIT)
90
89
  @exlist = @exstrlist.map { |exstr| Expand.new(exstr) }
@@ -4,69 +4,3 @@ require 'rack'
4
4
  require_relative '../odata/walker'
5
5
  require_relative 'request'
6
6
  require_relative 'response'
7
-
8
- module Safrano
9
- # Note there is a strong 1 to 1 relation between an app instance
10
- # and a published service. --> actually means also
11
- # we only support one service per App-class because publishing is
12
- # made on app class level
13
- class ServerApp
14
- def initialize
15
- # just get back the service base instance object
16
- # that was saved on class level and save it here
17
- # so it's not needed to call self.class.service
18
- @service_base = self.class.get_service_base
19
- end
20
-
21
- def call(env)
22
- Safrano::Request.new(env, @service_base).process
23
- end
24
-
25
- # needed for testing only ? try to remove this
26
- def self.copy(other)
27
- copy = Class.new(Safrano::ServerApp) # <---- !!!
28
- copy.set_servicebase(other.get_service_base.dup)
29
- copy
30
- end
31
-
32
- # needed for testing only ? try to remove this
33
- def self.enable_batch
34
- @service_base.enable_batch
35
- end
36
-
37
- # needed for testing only ? try to remove this
38
- def self.path_prefix(path_pr)
39
- @service_base.path_prefix path_pr
40
- end
41
-
42
- # needed for testing only ? try to remove this
43
-
44
- def self.response_format_options(*args)
45
- @service_base.response_format_options(*args)
46
- end
47
-
48
- # needed for testing only ? try to remove this
49
- def self.get_service_base
50
- @service_base
51
- end
52
-
53
- # needed for safrano-rack_builder
54
- def get_path_prefix
55
- self.class.get_service_base.xpath_prefix
56
- end
57
-
58
- def self.set_servicebase(sbase)
59
- @service_base = sbase
60
- @service_base.enable_v1_service
61
- @service_base.enable_v2_service
62
- end
63
-
64
- def self.publish_service(&block)
65
- sbase = Safrano::ServiceBase.new
66
- sbase.instance_eval(&block) if block_given?
67
- sbase.finalize_publishing
68
- # save published service base instance on App-Class level
69
- set_servicebase(sbase)
70
- end
71
- end
72
- end
@@ -118,9 +118,10 @@ module Safrano
118
118
  LEADING_SLASH_RGX = %r{\A/}.freeze
119
119
  include XMLNS
120
120
  GENERIC_415_RESP = [415, {}, ['']].freeze
121
- # Base class for service. Subclass will be for V1, V2 etc...
122
- class ServiceBase
121
+
122
+ class ServerApp
123
123
  include Safrano
124
+ include Safrano::Edm
124
125
  include ExpandHandler
125
126
 
126
127
  XML_PREAMBLE = %(<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n)
@@ -132,30 +133,31 @@ module Safrano
132
133
  # end
133
134
  # ---> @cmap ends up as {'books' => Book }
134
135
  attr_reader :cmap
136
+ attr_reader :xbugfix_create_response
137
+ attr_reader :allowed_transitions
135
138
 
136
139
  # this is just the *sorted* list of the entity classes
137
140
  # (ie... @cmap.values.sorted)
138
- attr_accessor :collections
139
-
140
- attr_accessor :xtitle
141
- attr_accessor :xname
142
- attr_accessor :xnamespace
143
- attr_accessor :xpath_prefix
144
- attr_accessor :xserver_url
145
- attr_accessor :uribase
146
- attr_accessor :meta
147
- attr_accessor :batch_handler
148
- attr_accessor :relman
149
- attr_accessor :complex_types
150
- attr_accessor :function_imports
151
- attr_accessor :function_import_keys
152
- attr_accessor :type_mappings
153
- attr_accessor :final_template_func
154
- attr_accessor :response_format_options
141
+ attr_reader :collections
142
+
143
+ attr_reader :xtitle
144
+ attr_reader :xname
145
+ attr_reader :xnamespace
146
+ attr_reader :xpath_prefix
147
+ attr_reader :xserver_url
148
+ attr_reader :uribase
149
+ attr_reader :meta
150
+ attr_reader :batch_handler
151
+ attr_reader :complex_types
152
+ attr_reader :function_imports
153
+ attr_reader :function_import_keys
154
+ attr_reader :type_mappings
155
+ attr_reader :final_template_func
156
+ attr_reader :response_format_options
155
157
 
156
158
  # Instance attributes for specialized Version specific Instances
157
- attr_accessor :v1
158
- attr_accessor :v2
159
+ attr_reader :v1
160
+ attr_reader :v2
159
161
 
160
162
  # TODO: more elegant design
161
163
  attr_reader :data_service_version
@@ -166,14 +168,13 @@ module Safrano
166
168
  FINAL_TEMPLATE_FUNC_SKIP_DEFERR = ->(template) { template.delete(:deferr) }
167
169
  FINAL_TEMPLATE_FUNC_SKIP_META_DEFERR = ->(template) { template.delete(:meta); template.delete(:deferr) }
168
170
 
169
- def initialize(&block)
170
- # Warning: if you add attributes here, you shall need add them
171
- # in copy_attribs_to as well
172
- # because of the version subclasses that dont use "super" initialise
173
- # (todo: why not??)
171
+ def self.app_setup_singleton
172
+ @app_setup_singleton
173
+ end
174
+
175
+ def initialize(template_instance: nil)
174
176
  @meta = ServiceMeta.new(self)
175
177
  @batch_handler = Safrano::Batch::DisabledHandler.new
176
- @relman = Safrano::RelationManager.new
177
178
  @complex_types = Set.new
178
179
  @function_imports = {}
179
180
  @function_import_keys = []
@@ -182,8 +183,61 @@ module Safrano
182
183
  @response_format_options = []
183
184
  @final_template_func = FINAL_TEMPLATE_FUNC_DEFAULT
184
185
  # enabled per default starting from 0.6
185
- @bugfix_create_response = true
186
- instance_eval(&block) if block_given?
186
+ @xbugfix_create_response = true
187
+ klass = self.class
188
+ # TODO better error
189
+ raise StandardError unless (klass.publish_proc or template_instance)
190
+
191
+ tmpli = if template_instance
192
+ template_instance
193
+ elsif klass.app_setup_singleton
194
+ klass.app_setup_singleton
195
+ end
196
+ initialize_fork(tmpli) if tmpli
197
+ end
198
+
199
+ def initialize_fork(template_instance)
200
+ @batch_handler = template_instance.batch_handler.dup
201
+ @complex_types = template_instance.complex_types.dup
202
+ @function_imports = template_instance.function_imports.dup
203
+ @function_import_keys = template_instance.function_import_keys.dup
204
+ @cmap = template_instance.cmap.dup
205
+ @type_mappings = template_instance.type_mappings.dup
206
+ @response_format_options = template_instance.response_format_options.dup
207
+ @final_template_func = template_instance.final_template_func.dup
208
+ @xbugfix_create_response = template_instance.xbugfix_create_response.dup
209
+ @xpath_prefix = template_instance.xpath_prefix.dup
210
+ @collections = template_instance.collections.dup
211
+ @xname = template_instance.xname.dup
212
+ @xserver_url = template_instance.xserver_url.dup
213
+ @uribase = template_instance.uribase.dup
214
+ @xtitle = template_instance.xtitle.dup
215
+ @xnamespace = template_instance.xnamespace.dup
216
+ @v1 = template_instance.v1.dup
217
+ @v2 = template_instance.v2.dup
218
+ @data_service_version = template_instance.data_service_version.dup
219
+ @allowed_transitions = template_instance.allowed_transitions.dup
220
+ end
221
+
222
+ def call(env)
223
+ Safrano::Request.new(env, self).process
224
+ end
225
+
226
+ def process_publish_service(&block)
227
+ instance_eval(&block)
228
+ finalize_publishing
229
+ enable_v1_service
230
+ enable_v2_service
231
+ end
232
+
233
+ def self.publish_service(&block)
234
+ @publish_proc = block
235
+ @app_setup_singleton = self.new
236
+ @app_setup_singleton.process_publish_service(&block)
237
+ end
238
+
239
+ def self.publish_proc
240
+ @publish_proc
187
241
  end
188
242
 
189
243
  DEFAULT_PATH_PREFIX = '/'
@@ -191,18 +245,17 @@ module Safrano
191
245
 
192
246
  def enable_batch
193
247
  @batch_handler = Safrano::Batch::EnabledHandler.new
194
- (@v1.batch_handler = @batch_handler) if @v1
195
- (@v2.batch_handler = @batch_handler) if @v2
248
+ (@v1.enable_batch) if @v1
249
+ (@v2.enable_batch) if @v2
250
+ self
196
251
  end
197
252
 
198
253
  def enable_v1_service
199
- @v1 = Safrano::ServiceV1.new
200
- copy_attribs_to @v1
254
+ @v1 = Safrano::ServiceV1.new(template_instance: self)
201
255
  end
202
256
 
203
257
  def enable_v2_service
204
- @v2 = Safrano::ServiceV2.new
205
- copy_attribs_to @v2
258
+ @v2 = Safrano::ServiceV2.new(template_instance: self)
206
259
  end
207
260
 
208
261
  # public API
@@ -221,14 +274,21 @@ module Safrano
221
274
  def path_prefix(path_pr)
222
275
  @xpath_prefix = path_pr.sub(TRAILING_SLASH_RGX, '')
223
276
  @xpath_prefix.freeze
224
- (@v1.xpath_prefix = @xpath_prefix) if @v1
225
- (@v2.xpath_prefix = @xpath_prefix) if @v2
277
+ (@v1.path_prefix(path_pr)) if @v1
278
+ (@v2.path_prefix(path_pr)) if @v2
279
+ self
280
+ end
281
+
282
+ # needed for safrano-rack_builder
283
+ def get_path_prefix
284
+ @xpath_prefix
226
285
  end
227
286
 
228
287
  def server_url(surl)
229
288
  @xserver_url = surl.sub(TRAILING_SLASH_RGX, '')
230
- (@v1.xserver_url = @xserver_url) if @v1
231
- (@v2.xserver_url = @xserver_url) if @v2
289
+ @xserver_url.freeze
290
+ (@v1.server_url(surl)) if @v1
291
+ (@v2.server_url(surl)) if @v2
232
292
  end
233
293
 
234
294
  VALID_RESP_FORMAT_OPTS = [:skip_deferred, :skip_metadata]
@@ -247,11 +307,12 @@ module Safrano
247
307
  @v1.response_format_options(*vargs) if @v1
248
308
  @v2.response_format_options(*vargs) if @v2
249
309
  end
310
+ self
250
311
  end
251
312
 
252
313
  # keep the bug active for now, but allow to de-activate the fix
253
314
  def bugfix_create_response(bool)
254
- @bugfix_create_response = bool
315
+ @xbugfix_create_response = bool
255
316
  end
256
317
 
257
318
  # end public API
@@ -280,29 +341,6 @@ module Safrano
280
341
  (@v2.uribase = @uribase) if @v2
281
342
  end
282
343
 
283
- def copy_attribs_to(other)
284
- other.cmap = @cmap
285
- other.collections = @collections
286
- other.allowed_transitions = @allowed_transitions
287
- other.xtitle = @xtitle
288
- other.xname = @xname
289
- other.xnamespace = @xnamespace
290
- other.xpath_prefix = @xpath_prefix
291
- other.xserver_url = @xserver_url
292
- other.uribase = @uribase
293
- other.meta = ServiceMeta.new(other) # hum ... #todo: versions as well ?
294
- other.relman = @relman
295
- other.batch_handler = @batch_handler
296
- other.complex_types = @complex_types
297
- other.function_imports = @function_imports
298
- other.function_import_keys = @function_import_keys
299
- other.type_mappings = @type_mappings
300
- other.response_format_options = @response_format_options
301
- other.final_template_func = @final_template_func
302
- other.bugfix_create_response(@bugfix_create_response)
303
- other
304
- end
305
-
306
344
  # this is a central place. We extend Sequel models with OData functionality
307
345
  # The included/extended modules depends on the properties(eg, pks, field types) of the model
308
346
  # we differentiate
@@ -451,7 +489,7 @@ module Safrano
451
489
  klass.build_uri(@uribase)
452
490
 
453
491
  # Output create (POST) as single entity (Standard) or as array (non-standard buggy)
454
- klass.include(@bugfix_create_response ? Safrano::EntityCreateStandardOutput : Safrano::EntityCreateArrayOutput)
492
+ klass.include(@xbugfix_create_response ? Safrano::EntityCreateStandardOutput : Safrano::EntityCreateArrayOutput)
455
493
 
456
494
  # define the most optimal casted_values method for the given model(klass)
457
495
  if klass.casted_cols.empty?
@@ -557,10 +595,13 @@ module Safrano
557
595
  end
558
596
 
559
597
  def add_metadata_xml_entity_type(schema)
598
+ relman = Safrano::RelationManager.new
560
599
  @collections.each do |klass|
561
600
  enty = klass.add_metadata_rexml(schema)
562
- klass.add_metadata_navs_rexml(enty, @relman)
601
+ klass.add_metadata_navs_rexml(enty, relman)
563
602
  end
603
+ # return the collected rels needed later
604
+ relman
564
605
  end
565
606
 
566
607
  def add_metadata_xml_complex_types(schema)
@@ -571,8 +612,8 @@ module Safrano
571
612
  @function_imports.each_value { |func| func.add_metadata_rexml(ec) }
572
613
  end
573
614
 
574
- def add_metadata_xml_associations(schema)
575
- @relman.each_rel do |rel|
615
+ def add_metadata_xml_associations(schema, relman)
616
+ relman.each_rel do |rel|
576
617
  rel.with_metadata_info(@xnamespace) do |name, bdinfo|
577
618
  assoc = schema.add_element('Association', 'Name' => name)
578
619
  bdinfo.each do |bdi|
@@ -585,7 +626,7 @@ module Safrano
585
626
  end
586
627
  end
587
628
 
588
- def add_metadata_xml_entity_container(schema)
629
+ def add_metadata_xml_entity_container(schema, relman)
589
630
  ec = schema.add_element('EntityContainer',
590
631
  'Name' => @xname,
591
632
  'm:IsDefaultEntityContainer' => 'true')
@@ -595,8 +636,9 @@ module Safrano
595
636
  'Name' => klass.entity_set_name,
596
637
  'EntityType' => klass.type_name)
597
638
  end
639
+
598
640
  # 3.b Association set's
599
- @relman.each_rel do |rel|
641
+ relman.each_rel do |rel|
600
642
  assoc = ec.add_element('AssociationSet',
601
643
  'Name' => rel.name,
602
644
  'Association' => "#{@xnamespace}.#{rel.name}")
@@ -645,17 +687,18 @@ module Safrano
645
687
  schema = serv.add_element('Schema',
646
688
  'Namespace' => @xnamespace,
647
689
  'xmlns' => XMLNS::MSFT_ADO_2009_EDM)
648
- # 1. a. all EntityType
649
- add_metadata_xml_entity_type(schema)
690
+
691
+ # 1. a. all EntityType (and get the collected rels metadata)
692
+ relman = add_metadata_xml_entity_type(schema)
650
693
 
651
694
  # 1. b. all ComplexType
652
695
  add_metadata_xml_complex_types(schema)
653
696
 
654
697
  # 2. Associations
655
- add_metadata_xml_associations(schema)
698
+ add_metadata_xml_associations(schema, relman)
656
699
 
657
700
  # 3. Enty container
658
- add_metadata_xml_entity_container(schema)
701
+ add_metadata_xml_entity_container(schema, relman)
659
702
 
660
703
  XML_PREAMBLE + doc.to_pretty_xml
661
704
  end
@@ -737,8 +780,9 @@ module Safrano
737
780
  end
738
781
 
739
782
  # for OData V1
740
- class ServiceV1 < ServiceBase
741
- def initialize
783
+ class ServiceV1 < ServerApp
784
+ def initialize(template_instance: nil)
785
+ super
742
786
  @data_service_version = '1.0'
743
787
  end
744
788
 
@@ -762,8 +806,9 @@ module Safrano
762
806
  end
763
807
 
764
808
  # for OData V2
765
- class ServiceV2 < ServiceBase
766
- def initialize
809
+ class ServiceV2 < ServerApp
810
+ def initialize(template_instance: nil)
811
+ super
767
812
  @data_service_version = '2.0'
768
813
  end
769
814
 
@@ -785,7 +830,7 @@ module Safrano
785
830
 
786
831
  # a virtual entity for the service metadata
787
832
  class ServiceMeta
788
- attr_accessor :service
833
+ attr_reader :service
789
834
 
790
835
  def initialize(service)
791
836
  @service = service
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Safrano
4
- VERSION = '0.8.2'
4
+ VERSION = '0.8.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safrano
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - oz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-09 00:00:00.000000000 Z
11
+ date: 2024-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack