safrano 0.8.2 → 0.8.3

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