safrano 0.4.3 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/core_ext/Dir/iter.rb +18 -0
- data/lib/core_ext/Hash/transform.rb +21 -0
- data/lib/core_ext/Integer/edm.rb +13 -0
- data/lib/core_ext/REXML/Document/output.rb +16 -0
- data/lib/core_ext/String/convert.rb +25 -0
- data/lib/core_ext/String/edm.rb +13 -0
- data/lib/core_ext/dir.rb +3 -0
- data/lib/core_ext/hash.rb +3 -0
- data/lib/core_ext/integer.rb +3 -0
- data/lib/core_ext/rexml.rb +3 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/odata/attribute.rb +8 -4
- data/lib/odata/batch.rb +9 -7
- data/lib/odata/collection.rb +139 -642
- data/lib/odata/collection_filter.rb +18 -42
- data/lib/odata/collection_media.rb +111 -54
- data/lib/odata/collection_order.rb +5 -2
- data/lib/odata/common_logger.rb +2 -0
- data/lib/odata/complex_type.rb +196 -0
- data/lib/odata/edm/primitive_types.rb +184 -0
- data/lib/odata/entity.rb +78 -123
- data/lib/odata/error.rb +170 -37
- data/lib/odata/expand.rb +20 -17
- data/lib/odata/filter/base.rb +9 -1
- data/lib/odata/filter/error.rb +43 -27
- data/lib/odata/filter/parse.rb +39 -25
- data/lib/odata/filter/sequel.rb +112 -56
- data/lib/odata/filter/sequel_function_adapter.rb +50 -49
- data/lib/odata/filter/token.rb +21 -18
- data/lib/odata/filter/tree.rb +78 -44
- data/lib/odata/function_import.rb +168 -0
- data/lib/odata/model_ext.rb +641 -0
- data/lib/odata/navigation_attribute.rb +9 -24
- data/lib/odata/relations.rb +5 -5
- data/lib/odata/select.rb +17 -5
- data/lib/odata/transition.rb +71 -0
- data/lib/odata/url_parameters.rb +100 -24
- data/lib/odata/walker.rb +18 -10
- data/lib/safrano.rb +18 -38
- data/lib/safrano/contract.rb +141 -0
- data/lib/safrano/core.rb +24 -106
- data/lib/safrano/core_ext.rb +13 -0
- data/lib/safrano/deprecation.rb +73 -0
- data/lib/safrano/multipart.rb +29 -24
- data/lib/safrano/rack_app.rb +62 -63
- data/lib/safrano/{odata_rack_builder.rb → rack_builder.rb} +18 -1
- data/lib/safrano/request.rb +96 -38
- data/lib/safrano/response.rb +4 -2
- data/lib/safrano/sequel_join_by_paths.rb +2 -2
- data/lib/safrano/service.rb +156 -110
- data/lib/safrano/version.rb +3 -1
- data/lib/sequel/plugins/join_by_paths.rb +6 -19
- metadata +30 -11
data/lib/odata/filter/token.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
module OData
|
3
|
+
module Safrano
|
5
4
|
module Filter
|
6
5
|
class Parser
|
7
6
|
# Input tokenizer
|
@@ -10,14 +9,16 @@ module OData
|
|
10
9
|
replace substring trim toupper tolower
|
11
10
|
day hour minute month second year
|
12
11
|
round floor ceiling].freeze
|
13
|
-
FUNCRGX = FUNCNAMES.join('|')
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
FUNCRGX = FUNCNAMES.join('|')
|
13
|
+
NULLRGX = 'null|NULL|Null'
|
14
|
+
QSTRINGRGX = /'((?:[^']|(?:'{2}))*)'/.freeze
|
15
|
+
BINOBOOL = '[eE][qQ]|[LlgGNn][eETt]|[aA][nN][dD]|[oO][rR]'
|
16
|
+
BINOARITHM = '[aA][dD][dD]|[sS][uU][bB]|[mM][uU][lL]|[dD][iI][vV]|[mM][oO][dD]'
|
17
|
+
NOTRGX = 'not|NOT|Not'
|
18
|
+
FPRGX = '\d+(?:\.\d+)?(?:e[+-]?\d+)?'
|
19
|
+
QUALITRGX = '\w+(?:\/\w+)+'
|
20
|
+
RGX = /(#{FUNCRGX})|(#{NULLRGX})|([\(\),])|(#{BINOBOOL})\s+|(#{BINOARITHM})|(#{NOTRGX})|#{QSTRINGRGX}|(#{FPRGX})|(#{QUALITRGX})|(\w+)|(')/.freeze
|
21
|
+
|
21
22
|
def each_typed_token(inp)
|
22
23
|
typ = nil
|
23
24
|
|
@@ -34,27 +35,29 @@ module OData
|
|
34
35
|
when 0
|
35
36
|
:FuncTree
|
36
37
|
when 1
|
38
|
+
:NullLiteral
|
39
|
+
when 2
|
37
40
|
case found
|
38
41
|
when '(', ')'
|
39
42
|
:Delimiter
|
40
43
|
when ','
|
41
44
|
:Separator
|
42
45
|
end
|
43
|
-
when 2
|
44
|
-
:BinopBool
|
45
46
|
when 3
|
46
|
-
:
|
47
|
+
:BinopBool
|
47
48
|
when 4
|
48
|
-
:
|
49
|
+
:BinopArithm
|
49
50
|
when 5
|
50
|
-
:
|
51
|
+
:UnopTree
|
51
52
|
when 6
|
52
|
-
:
|
53
|
+
:QString
|
53
54
|
when 7
|
54
|
-
:
|
55
|
+
:FPNumber
|
55
56
|
when 8
|
56
|
-
:
|
57
|
+
:Qualit
|
57
58
|
when 9
|
59
|
+
:Literal
|
60
|
+
when 10
|
58
61
|
:unmatchedQuote
|
59
62
|
end
|
60
63
|
yield found, typ
|
data/lib/odata/filter/tree.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './base
|
4
|
-
require_relative './error
|
3
|
+
require_relative './base'
|
4
|
+
require_relative './error'
|
5
5
|
|
6
|
-
module
|
6
|
+
module Safrano
|
7
7
|
module Filter
|
8
8
|
# Base class for Leaves, Trees, RootTrees etc
|
9
9
|
class Node
|
10
10
|
attr_reader :value
|
11
|
+
|
11
12
|
def initialize(val, &block)
|
12
13
|
@value = val
|
13
14
|
instance_eval(&block) if block_given?
|
@@ -21,15 +22,16 @@ module OData
|
|
21
22
|
# Leaves are Nodes with a parent but no children
|
22
23
|
class Leave
|
23
24
|
attr_accessor :parent
|
25
|
+
|
26
|
+
# nil is considered as accepted, otherwise non-nil=the error
|
24
27
|
def accept?(tok, typ)
|
25
|
-
|
28
|
+
Parser::ErrorInvalidToken(tok, typ)
|
26
29
|
end
|
27
30
|
|
28
31
|
def check_types; end
|
29
32
|
|
30
|
-
def attach(
|
31
|
-
|
32
|
-
raise ErrorLeaveChild
|
33
|
+
def attach(_child)
|
34
|
+
Safrano::Filter::Parser::ErrorLeaveChild
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
@@ -37,6 +39,7 @@ module OData
|
|
37
39
|
class RootTree
|
38
40
|
attr_reader :children
|
39
41
|
attr_accessor :state
|
42
|
+
|
40
43
|
def initialize(val: :root, &block)
|
41
44
|
@children = []
|
42
45
|
super(val, &block)
|
@@ -45,6 +48,7 @@ module OData
|
|
45
48
|
def attach(child)
|
46
49
|
child.parent = self
|
47
50
|
@children << child
|
51
|
+
Contract::OK
|
48
52
|
end
|
49
53
|
|
50
54
|
def detach(child)
|
@@ -58,23 +62,27 @@ module OData
|
|
58
62
|
|
59
63
|
def update_state(tok, typ) end
|
60
64
|
|
65
|
+
# nil is considered as accepted, otherwise non-nil=the error
|
61
66
|
def accept?(tok, typ)
|
62
67
|
case typ
|
63
|
-
when :Literal, :Qualit, :QString, :FuncTree, :ArgTree,
|
64
|
-
|
68
|
+
when :Literal, :NullLiteral, :Qualit, :QString, :FuncTree, :ArgTree,
|
69
|
+
:UnopTree, :FPNumber
|
70
|
+
nil
|
65
71
|
when :Delimiter
|
66
72
|
if tok == '('
|
67
|
-
|
73
|
+
nil
|
68
74
|
else
|
69
|
-
|
75
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
70
76
|
end
|
71
77
|
else
|
72
|
-
|
78
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
76
82
|
def check_types
|
77
|
-
|
83
|
+
err = nil
|
84
|
+
@children.find { |c| (err = c.check_types) }
|
85
|
+
err
|
78
86
|
end
|
79
87
|
end
|
80
88
|
|
@@ -125,10 +133,11 @@ module OData
|
|
125
133
|
end
|
126
134
|
end
|
127
135
|
|
136
|
+
# nil is considered as accepted, otherwise non-nil=the error
|
128
137
|
def accept?(tok, typ)
|
129
138
|
case typ
|
130
139
|
when :BinopBool, :BinopArithm
|
131
|
-
|
140
|
+
nil
|
132
141
|
else
|
133
142
|
super(tok, typ)
|
134
143
|
end
|
@@ -139,9 +148,9 @@ module OData
|
|
139
148
|
when :length
|
140
149
|
argtyp = args.first.edm_type
|
141
150
|
if (argtyp != :any) && (argtyp != :string)
|
142
|
-
|
143
|
-
|
144
|
-
|
151
|
+
return Parser::ErrorInvalidArgumentType.new(self,
|
152
|
+
expected: :string,
|
153
|
+
actual: argtyp)
|
145
154
|
end
|
146
155
|
end
|
147
156
|
super
|
@@ -158,13 +167,33 @@ module OData
|
|
158
167
|
|
159
168
|
# we can have parenthesis with one expression inside everywhere
|
160
169
|
# only in FuncTree this is redefined for the function's arity
|
170
|
+
# Note: if you change this method, please also update arity_full_monkey?
|
171
|
+
# see below
|
161
172
|
def arity_full?(cursize)
|
162
173
|
cursize >= 1
|
163
174
|
end
|
164
175
|
|
176
|
+
# this is for testing only.
|
177
|
+
# see 99_threadsafe_tc.rb
|
178
|
+
# there we will monkey patch arity_full? by adding some sleeping
|
179
|
+
# to easily slow down a given test-thread (while the other one runs normaly)
|
180
|
+
#
|
181
|
+
# The rule is to keep this method here exactly same as the original
|
182
|
+
# "productive" one
|
183
|
+
#
|
184
|
+
# With this trick we can test threadsafeness without touching
|
185
|
+
# "productive" code
|
186
|
+
def arity_full_monkey?(cursize)
|
187
|
+
cursize >= 1
|
188
|
+
end
|
189
|
+
|
165
190
|
def edm_type
|
166
191
|
@children.first.edm_type
|
167
192
|
end
|
193
|
+
|
194
|
+
def ==(other)
|
195
|
+
@children == other.children
|
196
|
+
end
|
168
197
|
end
|
169
198
|
|
170
199
|
# unary op eg. NOT
|
@@ -203,7 +232,7 @@ module OData
|
|
203
232
|
|
204
233
|
def update_state(_tok, typ)
|
205
234
|
case typ
|
206
|
-
when :Literal, :Qualit, :QString, :FuncTree, :BinopBool, :BinopArithm, :UnopTree, :FPNumber
|
235
|
+
when :Literal, :NullLiteral, :Qualit, :QString, :FuncTree, :BinopBool, :BinopArithm, :UnopTree, :FPNumber
|
207
236
|
@state = :closed
|
208
237
|
end
|
209
238
|
end
|
@@ -255,6 +284,7 @@ module OData
|
|
255
284
|
# Arguments or lists
|
256
285
|
class ArgTree
|
257
286
|
attr_reader :type
|
287
|
+
|
258
288
|
def initialize(val)
|
259
289
|
@type = :expression
|
260
290
|
@state = :open
|
@@ -267,45 +297,48 @@ module OData
|
|
267
297
|
@state = :closed
|
268
298
|
when :Separator
|
269
299
|
@state = :sep
|
270
|
-
when :Literal, :Qualit, :QString, :FuncTree, :FPNumber
|
300
|
+
when :Literal, :NullLiteral, :Qualit, :QString, :FuncTree, :FPNumber
|
271
301
|
@state = :val
|
272
302
|
end
|
273
303
|
end
|
274
304
|
|
305
|
+
# nil is considered as accepted, otherwise non-nil=the error
|
275
306
|
def accept?(tok, typ)
|
276
307
|
case typ
|
277
308
|
when :Delimiter
|
278
309
|
if @value == '(' && tok == ')' && @state != :closed
|
279
|
-
if @parent.
|
280
|
-
|
310
|
+
if (@parent.class == IdentityFuncTree) or
|
311
|
+
(@parent.arity_full?(@children.size))
|
312
|
+
|
313
|
+
nil
|
281
314
|
else
|
282
|
-
|
315
|
+
Parser::ErrorInvalidArity.new(tok, typ, self)
|
283
316
|
end
|
284
317
|
else
|
285
|
-
|
318
|
+
if @value == '(' && tok == '(' && @state == :open
|
319
|
+
nil
|
320
|
+
else
|
321
|
+
Parser::ErrorUnmatchedClose.new(tok, typ, self)
|
322
|
+
end
|
286
323
|
end
|
287
324
|
when :Separator
|
288
325
|
if @value == '(' && tok == ',' && @state == :val
|
289
|
-
|
326
|
+
nil
|
290
327
|
elsif @state == :sep
|
291
|
-
|
292
|
-
else
|
293
|
-
true
|
328
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
294
329
|
end
|
295
|
-
when :Literal, :Qualit, :QString, :FuncTree, :FPNumber
|
330
|
+
when :Literal, :NullLiteral, :Qualit, :QString, :FuncTree, :FPNumber
|
296
331
|
if (@state == :open) || (@state == :sep)
|
297
332
|
if @parent.arity_full?(@children.size)
|
298
|
-
|
299
|
-
else
|
300
|
-
true
|
333
|
+
Parser::ErrorInvalidArity.new(tok, typ, self)
|
301
334
|
end
|
302
335
|
else
|
303
|
-
|
336
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
304
337
|
end
|
305
338
|
when :BinopBool, :BinopArithm
|
306
|
-
|
339
|
+
nil
|
307
340
|
else
|
308
|
-
|
341
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
309
342
|
end
|
310
343
|
end
|
311
344
|
|
@@ -319,9 +352,9 @@ module OData
|
|
319
352
|
def accept?(tok, typ)
|
320
353
|
case typ
|
321
354
|
when :Delimiter, :Separator, :BinopBool, :BinopArithm
|
322
|
-
|
355
|
+
nil
|
323
356
|
else
|
324
|
-
|
357
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
325
358
|
end
|
326
359
|
end
|
327
360
|
|
@@ -336,9 +369,9 @@ module OData
|
|
336
369
|
def accept?(tok, typ)
|
337
370
|
case typ
|
338
371
|
when :Delimiter, :Separator, :BinopBool, :BinopArithm
|
339
|
-
|
372
|
+
nil
|
340
373
|
else
|
341
|
-
|
374
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
342
375
|
end
|
343
376
|
end
|
344
377
|
|
@@ -351,8 +384,8 @@ module OData
|
|
351
384
|
# an attempt to use a unknown function, eg. ceil(Total)
|
352
385
|
# instead of ceiling(Total)
|
353
386
|
def attach(child)
|
354
|
-
if child.
|
355
|
-
|
387
|
+
if child.is_a? Safrano::Filter::IdentityFuncTree
|
388
|
+
Safrano::FilterUnknownFunctionError.new(value)
|
356
389
|
else
|
357
390
|
super
|
358
391
|
end
|
@@ -365,6 +398,7 @@ module OData
|
|
365
398
|
REGEXP = /((?:\w+\/)+)(\w+)/.freeze
|
366
399
|
attr_reader :path
|
367
400
|
attr_reader :attrib
|
401
|
+
|
368
402
|
def initialize(val)
|
369
403
|
super(val)
|
370
404
|
# split into path + attrib
|
@@ -377,8 +411,8 @@ module OData
|
|
377
411
|
|
378
412
|
# Quoted Strings
|
379
413
|
class QString
|
380
|
-
DBL_QO = "''"
|
381
|
-
SI_QO = "'"
|
414
|
+
DBL_QO = "''"
|
415
|
+
SI_QO = "'"
|
382
416
|
def initialize(val)
|
383
417
|
# unescape double quotes
|
384
418
|
super(val.gsub(DBL_QO, SI_QO))
|
@@ -387,9 +421,9 @@ module OData
|
|
387
421
|
def accept?(tok, typ)
|
388
422
|
case typ
|
389
423
|
when :Delimiter, :Separator, :BinopBool, :BinopArithm
|
390
|
-
|
424
|
+
nil
|
391
425
|
else
|
392
|
-
|
426
|
+
Parser::ErrorInvalidToken.new(tok, typ, self)
|
393
427
|
end
|
394
428
|
end
|
395
429
|
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'complex_type'
|
4
|
+
require_relative 'edm/primitive_types'
|
5
|
+
require_relative 'transition'
|
6
|
+
|
7
|
+
module Safrano
|
8
|
+
def self.FunctionImport(name)
|
9
|
+
FunctionImport::Function.new(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
module FunctionImport
|
13
|
+
class Function
|
14
|
+
@allowed_transitions = [Safrano::TransitionEnd]
|
15
|
+
attr_reader :name
|
16
|
+
attr_reader :proc
|
17
|
+
|
18
|
+
def initialize(name)
|
19
|
+
@name = name
|
20
|
+
@http_method = 'GET'
|
21
|
+
end
|
22
|
+
|
23
|
+
def allowed_transitions
|
24
|
+
[Safrano::TransitionEnd]
|
25
|
+
end
|
26
|
+
|
27
|
+
def input(**parmtypes)
|
28
|
+
@input = {}
|
29
|
+
parmtypes.each do |k, t|
|
30
|
+
@input[k] = case t.name
|
31
|
+
when 'Integer'
|
32
|
+
Safrano::Edm::Edm::Int32
|
33
|
+
when 'String'
|
34
|
+
Safrano::Edm::Edm::String
|
35
|
+
when 'Float'
|
36
|
+
Safrano::Edm::Edm::Double
|
37
|
+
when 'DateTime'
|
38
|
+
Safrano::Edm::Edm::DateTime
|
39
|
+
else
|
40
|
+
t
|
41
|
+
end
|
42
|
+
end
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def return(klassmod, &proc)
|
47
|
+
raise('Please provide a code block') unless block_given?
|
48
|
+
|
49
|
+
@returning = if klassmod.respond_to? :return_as_instance_descriptor
|
50
|
+
klassmod.return_as_instance_descriptor
|
51
|
+
else
|
52
|
+
# if it's neither a ComplexType nor a Model-Entity
|
53
|
+
# --> assume it is a Primitive
|
54
|
+
ResultAsPrimitiveType.new(klassmod)
|
55
|
+
end
|
56
|
+
@proc = proc
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def return_collection(klassmod, &proc)
|
61
|
+
raise('Please provide a code block') unless block_given?
|
62
|
+
|
63
|
+
@returning = if klassmod.respond_to? :return_as_collection_descriptor
|
64
|
+
klassmod.return_as_collection_descriptor
|
65
|
+
else
|
66
|
+
# if it's neither a ComplexType nor a Modle-Entity
|
67
|
+
# --> assume it is a Primitive
|
68
|
+
ResultAsPrimitiveTypeColl.new(klassmod)
|
69
|
+
end
|
70
|
+
@proc = proc
|
71
|
+
self
|
72
|
+
end
|
73
|
+
# def initialize_params
|
74
|
+
# @uparms = UrlParameters4Func.new(@model, @params)
|
75
|
+
# end
|
76
|
+
|
77
|
+
def check_missing_params
|
78
|
+
# do we have all parameters provided ? use Set difference to check
|
79
|
+
pkeys = @params.keys.map(&:to_sym).to_set
|
80
|
+
unless (idiff = @input.keys.to_set - pkeys).empty?
|
81
|
+
|
82
|
+
Safrano::ServiceOperationParameterMissing.new(
|
83
|
+
missing: idiff.to_a,
|
84
|
+
sopname: @name
|
85
|
+
)
|
86
|
+
else
|
87
|
+
Contract::OK
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_url_func_params
|
92
|
+
@funcparams = {}
|
93
|
+
return nil unless @input # anything to check ?
|
94
|
+
|
95
|
+
# do we have all parameters provided ?
|
96
|
+
check_missing_params.tap_error { |error| return error }
|
97
|
+
# ==> all params were provided
|
98
|
+
|
99
|
+
# now we shall check the content and type of the parameters
|
100
|
+
@input.each do |ksym, typ|
|
101
|
+
typ.convert_from_urlparam(v = @params[ksym.to_s])
|
102
|
+
.tap_valid do |retval|
|
103
|
+
@funcparams[ksym] = retval
|
104
|
+
end
|
105
|
+
.tap_error do
|
106
|
+
# return is really needed here, or we end up returning nil below
|
107
|
+
return parameter_convertion_error(ksym, typ, v)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
|
113
|
+
def parameter_convertion_error(param, type, val)
|
114
|
+
Safrano::ServiceOperationParameterError.new(type: type,
|
115
|
+
value: val,
|
116
|
+
param: param,
|
117
|
+
sopname: @name)
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_metadata_rexml(ec)
|
121
|
+
## https://services.odata.org/V2/OData/Safrano.svc/$metadata
|
122
|
+
# <FunctionImport Name="GetProductsByRating" EntitySet="Products" ReturnType="Collection(ODataDemo.Product)" m:HttpMethod="GET">
|
123
|
+
# <Parameter Name="rating" Type="Edm.Int32" Mode="In"/>
|
124
|
+
# </FunctionImport>
|
125
|
+
funky = ec.add_element('FunctionImport',
|
126
|
+
'Name' => @name.to_s,
|
127
|
+
# EntitySet= @entity_set ,
|
128
|
+
'ReturnType' => @returning.type_metadata,
|
129
|
+
'm:HttpMethod' => @http_method)
|
130
|
+
@input.each do |iname, type|
|
131
|
+
funky.add_element('Parameter',
|
132
|
+
'Name' => iname.to_s,
|
133
|
+
'Type' => type.type_name,
|
134
|
+
'Mode' => 'In')
|
135
|
+
end if @input
|
136
|
+
funky
|
137
|
+
end
|
138
|
+
|
139
|
+
def with_validated_get(req)
|
140
|
+
# initialize_params
|
141
|
+
return yield unless (@error = check_url_func_params)
|
142
|
+
|
143
|
+
@error.odata_get(req) if @error
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_odata_json(req)
|
147
|
+
result = @proc.call(**@funcparams)
|
148
|
+
@returning.to_odata_json(result, req)
|
149
|
+
end
|
150
|
+
|
151
|
+
def odata_get_output(req)
|
152
|
+
[200, EMPTY_HASH, [to_odata_json(req)]]
|
153
|
+
end
|
154
|
+
|
155
|
+
def odata_get(req)
|
156
|
+
@params = req.params
|
157
|
+
|
158
|
+
with_validated_get(req) do
|
159
|
+
odata_get_output(req)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def transition_end(_match_result)
|
164
|
+
Transition::RESULT_END
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|