mastercard_api_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,325 @@
1
+ #
2
+ # Copyright (c) 2016 MasterCard International Incorporated
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification, are
6
+ # permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice, this list of
9
+ # conditions and the following disclaimer.
10
+ # Redistributions in binary form must reproduce the above copyright notice, this list of
11
+ # conditions and the following disclaimer in the documentation and/or other materials
12
+ # provided with the distribution.
13
+ # Neither the name of the MasterCard International Incorporated nor the names of its
14
+ # contributors may be used to endorse or promote products derived from this software
15
+ # without specific prior written permission.
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
17
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
+ # SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
+ # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
+ # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ # SUCH DAMAGE.
26
+ #
27
+ module MasterCard
28
+ module Core
29
+ module Exceptions
30
+
31
+ ################################################################################
32
+ # APIException
33
+ ################################################################################
34
+ class APIException < StandardError
35
+ #
36
+ # Base Class for all the API exceptions
37
+ def initialize(message,status=nil, error_data=nil)
38
+ #Call the base class constructor
39
+ super(message)
40
+
41
+ @message = message
42
+ @status = status
43
+ @error_data = error_data
44
+ @error_code = nil
45
+
46
+ #If error_data is not nil set the appropriate message
47
+ unless error_data.nil?
48
+
49
+ error_hash = Hash.new
50
+ # If error_data is of type hash and has Key 'Errors' which has a key 'Error'
51
+ if error_data.is_a?(Hash) && error_data.key?("Errors") && error_data["Errors"].key?("Error")
52
+
53
+ error_hash = error_data["Errors"]["Error"]
54
+
55
+ #Case of multiple errors take the first one
56
+ if error_hash.is_a?(Array)
57
+ error_hash = error_hash[0]
58
+ end
59
+
60
+ initDataFromHash(error_hash)
61
+
62
+ #If error Data is of Type Array
63
+ elsif error_data.is_a?(Array)
64
+ #Take the first error
65
+ error_hash = error_data[0]
66
+ initDataFromHash(error_hash)
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ def getMessage()
73
+ return @message
74
+ end
75
+
76
+ def getStatus()
77
+ return @status
78
+ end
79
+
80
+ def getErrorCode()
81
+ return @error_code
82
+ end
83
+
84
+ def getErrorData()
85
+ return @error_data
86
+ end
87
+
88
+ def describe()
89
+ exception = self.class.name
90
+ exception << ": \""
91
+ exception << getMessage()
92
+ exception << "\" (status: "
93
+ exception << "%s" % getStatus()
94
+ errorCode = getErrorCode()
95
+ unless errorCode.nil?
96
+ exception << ", error code: "
97
+ exception << "%s" % getErrorCode()
98
+ end
99
+ exception << ")"
100
+ return exception
101
+ end
102
+
103
+ def to_s()
104
+ return '%s' % describe()
105
+ end
106
+
107
+ private
108
+
109
+ def initDataFromHash(error_hash)
110
+ @error_code = error_hash.fetch("ReasonCode","")
111
+ @message = error_hash.fetch("Message",@message)
112
+ end
113
+
114
+ end
115
+
116
+ ################################################################################
117
+ # ApiConnectionException
118
+ ################################################################################
119
+
120
+ class APIConnectionException < APIException
121
+ #
122
+ #Exception raised when there are communication problems contacting the API.
123
+ def initialize(message=nil,status=nil,error_data=nil)
124
+
125
+
126
+ if status.nil?
127
+ status = 500
128
+ end
129
+
130
+ #Call the base class constructor
131
+ super(message,status,error_data)
132
+ end
133
+ end
134
+
135
+
136
+ ################################################################################
137
+ # ObjectNotFoundException
138
+ ################################################################################
139
+
140
+ class ObjectNotFoundException < APIException
141
+ #
142
+ #Exception raised when the endpoint does not exist.
143
+ def initialize(message=nil,status=nil,error_data=nil)
144
+
145
+
146
+ if status.nil?
147
+ status = 404
148
+ end
149
+
150
+ #Call the base class constructor
151
+ super(message,status,error_data)
152
+ end
153
+ end
154
+
155
+ ################################################################################
156
+ # AuthenticationException
157
+ ################################################################################
158
+
159
+ class AuthenticationException < APIException
160
+ #
161
+ #Exception raised where there are problems authenticating a request.
162
+ def initialize(message=nil,status=nil,error_data=nil)
163
+
164
+
165
+ if status.nil?
166
+ status = 401
167
+ end
168
+
169
+ #Call the base class constructor
170
+ super(message,status,error_data)
171
+ end
172
+ end
173
+
174
+ ################################################################################
175
+ # InvalidRequestException
176
+ ################################################################################
177
+
178
+ class InvalidRequestException < APIException
179
+ #
180
+ #Exception raised when the API request contains errors.
181
+
182
+ def initialize(message=nil,status=nil,error_data=nil)
183
+
184
+ if status.nil?
185
+ status = 400
186
+ end
187
+
188
+ #Call the base class constructor
189
+ super(message,status,error_data)
190
+
191
+ @fieldErrors = []
192
+
193
+ #If error_data is not nil set the appropriate message
194
+ unless error_data.nil?
195
+
196
+ error_hash = Hash.new
197
+ # If error_data is of type hash and has Key 'Errors' which has a key 'Error'
198
+ if error_data.is_a?(Hash) && error_data.key?("Errors") && error_data["Errors"].key?("Error")
199
+
200
+ error_hash = error_data["Errors"]["Error"]
201
+
202
+ #Case of multiple errors take the first one
203
+ if error_hash.is_a?(Array)
204
+ error_hash = error_hash[0]
205
+ end
206
+
207
+ initFieldDataFromHash(error_hash)
208
+
209
+ #If error Data is of Type Array
210
+ elsif error_data.is_a?(Array)
211
+ #Take the first error
212
+ error_hash = error_data[0]
213
+ initFieldDataFromHash(error_hash)
214
+ end
215
+ end
216
+ end
217
+
218
+
219
+ def hasFieldErrors
220
+ return @fieldErrors.length != 0
221
+ end
222
+
223
+ def getFieldErrors
224
+ return @fieldErrors
225
+ end
226
+
227
+ def describe
228
+ des = super()
229
+ @fieldErrors.each do |field_error|
230
+ des << "\n #{field_error}"
231
+ end
232
+ return des
233
+ end
234
+
235
+ def to_s
236
+ return "%s"%describe()
237
+ end
238
+
239
+ private
240
+
241
+ def initFieldDataFromHash(error_hash)
242
+ if error_hash.key?("FieldErrors")
243
+ error_hash.fetch("FieldErrors").each do |field_error|
244
+ @fieldErrors << "%s"%FieldError.new(field_error)
245
+ end
246
+ end
247
+ end
248
+
249
+
250
+
251
+ end
252
+
253
+ ################################################################################
254
+ # NotAllowedException
255
+ ################################################################################
256
+
257
+ class NotAllowedException < APIException
258
+ #
259
+ #Exception when a request was not allowed.
260
+ def initialize(message=nil,status=nil,error_data=nil)
261
+
262
+
263
+ if status.nil?
264
+ status = 403
265
+ end
266
+
267
+ #Call the base class constructor
268
+ super(message,status,error_data)
269
+
270
+ end
271
+ end
272
+
273
+
274
+ ################################################################################
275
+ # SystemException
276
+ ################################################################################
277
+
278
+ class SystemException < APIException
279
+ #
280
+ #Exception when there was a system error processing a request.
281
+ def initialize(message=nil,status=nil,error_data=nil)
282
+
283
+
284
+ if status.nil?
285
+ status = 500
286
+ end
287
+
288
+ #Call the base class constructor
289
+ super(message,status,error_data)
290
+ end
291
+ end
292
+
293
+ ################################################################################
294
+ # FieldError
295
+ ################################################################################
296
+
297
+ class FieldError
298
+
299
+ def initialize(params)
300
+
301
+ @name = params.fetch("field","")
302
+ @message = params.fetch("message","")
303
+ @code = params.fetch("code")
304
+ end
305
+
306
+ def getFieldName
307
+ return @name
308
+ end
309
+
310
+ def getErrorMessage
311
+ return @message
312
+ end
313
+
314
+ def getErrorCode
315
+ return @code
316
+ end
317
+
318
+ def to_s
319
+ return "Field Error: #{@name} \"#{@message}\" (#{@code})"
320
+ end
321
+ end
322
+
323
+ end
324
+ end
325
+ end
@@ -0,0 +1,467 @@
1
+ #
2
+ # Copyright (c) 2016 MasterCard International Incorporated
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification, are
6
+ # permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice, this list of
9
+ # conditions and the following disclaimer.
10
+ # Redistributions in binary form must reproduce the above copyright notice, this list of
11
+ # conditions and the following disclaimer in the documentation and/or other materials
12
+ # provided with the distribution.
13
+ # Neither the name of the MasterCard International Incorporated nor the names of its
14
+ # contributors may be used to endorse or promote products derived from this software
15
+ # without specific prior written permission.
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
17
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
+ # SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
+ # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
+ # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ # SUCH DAMAGE.
26
+ #
27
+ require "mastercard/core/controller"
28
+
29
+ module MasterCard
30
+ module Core
31
+ module Model
32
+ ################################################################################
33
+ # RequestMap
34
+ ################################################################################
35
+
36
+ class RequestMap
37
+
38
+ KEY_LIST = "list"
39
+
40
+ def initialize
41
+ @properties = Hash.new
42
+ @parentWithSquareBracket = /\[(.*)\]/
43
+ end
44
+
45
+ def set(key,value)
46
+ #Sets the the value of key as value
47
+ #Get the list of keys
48
+ keys = key.split(".")
49
+
50
+ #Number of keys
51
+ keys_len = keys.length
52
+
53
+ #Copy properties in sub properties so we can walk over it
54
+ @subProperty = @properties
55
+
56
+ count = 0
57
+
58
+ keys.each do |part_key|
59
+ count += 1
60
+
61
+ #If we are at the final key, then we need to set this key for subProperty
62
+ if count == keys_len
63
+ match = @parentWithSquareBracket.match(part_key)
64
+ #If match is nil then we can set the value
65
+ if match.nil?
66
+ @subProperty[part_key] = value
67
+ else #if the key is like key[0]
68
+ handleListTypeKeys(part_key,match,value)
69
+ end
70
+ else
71
+ #walk inside subProperty
72
+ createMap(part_key)
73
+ end
74
+
75
+
76
+ end
77
+
78
+ return @properties
79
+
80
+ end
81
+
82
+ def get(key)
83
+ #Gets the value from the map associated with the key
84
+
85
+ #Sets the the value of key as value
86
+ #Get the list of keys
87
+ keys = key.split(".")
88
+
89
+ #Number of keys
90
+ keys_len = keys.length
91
+
92
+ #Copy properties in sub properties so we can walk over it
93
+ @subProperty = @properties
94
+
95
+ count = 0
96
+
97
+ keys.each do |part_key|
98
+ count += 1
99
+ #check if the key is of form key[0]
100
+ match = @parentWithSquareBracket.match(part_key)
101
+
102
+ #if the final key is of form key[0]
103
+ unless match.nil?
104
+ begin
105
+ moveInList(part_key,match)
106
+ rescue
107
+ return nil
108
+ end
109
+ #If this is the last key
110
+ if count == keys_len
111
+ return @subProperty
112
+ end
113
+ else # Move in the map
114
+
115
+ if @subProperty.is_a?(Hash) && @subProperty.key?(part_key)
116
+ if count == keys_len #this is the final key, return the value
117
+ return @subProperty[part_key]
118
+ else #Move in the map
119
+ @subProperty = @subProperty[part_key]
120
+ end
121
+ else
122
+ return nil
123
+ end
124
+
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+
131
+ def setAll(map)
132
+
133
+ # Uses the hash object to create the base map object
134
+
135
+ initialKey = ""
136
+
137
+ #If given object is an array then the created map should have a key called list first
138
+
139
+ if map.is_a?(Array)
140
+ initialKey = KEY_LIST
141
+ end
142
+
143
+ #Iterate over the object and keeps on adding the items to the properties object
144
+ iterateItemsAndAdd(map,initialKey)
145
+
146
+ return @properties
147
+
148
+
149
+ end
150
+
151
+
152
+
153
+ def getObject
154
+ #Returns the basemap internal object
155
+ return @properties
156
+ end
157
+
158
+ def size
159
+ #
160
+ #Returns the number of keys at the first level of the object
161
+ #
162
+ return @properties.length
163
+ end
164
+
165
+ def containsKeys(key)
166
+
167
+ #checks if map contains the key
168
+
169
+ unless get(key).nil?
170
+ return true
171
+ end
172
+
173
+ return false
174
+
175
+ end
176
+
177
+
178
+ private
179
+
180
+ def createMap(key)
181
+
182
+ match = @parentWithSquareBracket.match(key)
183
+ #If it is not a type of key[0]
184
+ if match.nil?
185
+
186
+ unless @subProperty.is_a?(Hash) && @subProperty.key?(key)
187
+
188
+ if @subProperty.is_a?(Hash)
189
+ @subProperty[key] = Hash.new
190
+ else
191
+ raise KeyError.new("Invalid Key String : Cannot override value #{@subProperty}")
192
+ end
193
+ end
194
+ @subProperty = @subProperty[key]
195
+
196
+ else
197
+ handleListTypeKeys(key,match,{})
198
+ end
199
+
200
+ end
201
+
202
+ def iterateItemsAndAdd(map,combKey)
203
+
204
+ #Iterate over the items in the map object and adds them to basemap object
205
+
206
+ #The implementation is more of a depth first search
207
+ #For a given object for eg {"user":"name":{"first":"naman","last":"aggarwal",roll:[4,3,6]}}
208
+ #It reaches to a lowest level and keeps track of the key, in this case user.name.first and then
209
+ #uses set function to set the value set("user.name.first","naman")
210
+ #For list it uses index as keys, for eg user.name.roll[0] = 4
211
+
212
+ #Check if it object is a hash
213
+ if map.is_a?(Hash)
214
+ map.each do |key,value|
215
+ #if last combined is not empty then append current key to it else use current key
216
+ tempKey = if combKey!= "" then "#{combKey}.#{key}" else key end
217
+ #call the function again with one level down and combined key
218
+ iterateItemsAndAdd(map[key],tempKey)
219
+
220
+ end
221
+ #If the object is an Array , for eg roll:[1,2,3] (combKey will be user.name for this case)
222
+ elsif map.is_a?(Array)
223
+ count = 0
224
+ # Iterate over each value
225
+ map.each do |value|
226
+ #create the temp key with the current index
227
+ tempKey = "#{combKey}[#{count.to_s}]"
228
+ #call the function again with one level lower and combined key
229
+ iterateItemsAndAdd(value,tempKey)
230
+ count+=1
231
+ end
232
+ #If its any other object then set the key to that value
233
+ else
234
+
235
+ set(combKey,map)
236
+ end
237
+
238
+ end
239
+
240
+
241
+ def handleListTypeKeys(key,match,value)
242
+ #Handles the keys of type key[0]
243
+
244
+ #Creates a new list if key does not exist else moves to keys
245
+ #Adds the value at the poistion index for key[index]
246
+ #if index == len of list then appends
247
+ #if index > len then throw exception
248
+
249
+ #Get the array index (should be the first matched group)
250
+ arr_key = match[1]
251
+
252
+ #Get the text key
253
+ txt_key = key[0...match.begin(0)]
254
+
255
+ begin
256
+ arr_key = Integer(arr_key)
257
+ rescue ArgumentError
258
+ raise KeyError.new("Key #{arr_key.to_s} is not an integer")
259
+ end
260
+
261
+ #If txt_key not in subProperty
262
+ unless @subProperty.key?(txt_key)
263
+ #If the arr_key is not integer or not zero
264
+ if arr_key != 0
265
+ raise KeyError.new("Key #{match[0]} is invalid")
266
+ end
267
+
268
+ #add key as a list
269
+ @subProperty[txt_key] = Array.new
270
+
271
+ #walk the subProperty into it
272
+ @subProperty = @subProperty[txt_key]
273
+
274
+ #Append the value
275
+ @subProperty.push(value)
276
+
277
+ #move into the array
278
+ @subProperty = @subProperty[arr_key]
279
+
280
+ else #If the text key exist in the map
281
+
282
+ #move in the map
283
+ @subProperty = @subProperty[txt_key]
284
+
285
+ if arr_key < @subProperty.length
286
+ if value == {} #If the value is {} then we just want to move in the hash
287
+ @subProperty = @subProperty[arr_key]
288
+ else # This means that this is the last key and value need to be set
289
+ @subProperty[arr_key] = value
290
+ end
291
+ #This means that index arr_key does not exist in the list
292
+ #If the index is same as length then append
293
+ elsif @subProperty.length == arr_key
294
+
295
+ @subProperty.push(value)
296
+
297
+ #move inside the array
298
+ @subProperty = @subProperty[arr_key]
299
+
300
+ else
301
+ raise KeyError.new("Key #{match[0]} is invalid")
302
+ end
303
+
304
+ end
305
+
306
+ end
307
+
308
+ def moveInList(key, match)
309
+ #Moves in the subMap, if key is of type for eg key[1] and match matches [1]
310
+ #Raises exception if either key is not in map or map.key is not a list or map.key[1] does not exist
311
+
312
+ #Get the array index (should be the first matched group)
313
+ arr_key = match[1]
314
+
315
+ #Get the text key
316
+ txt_key = key[0...match.begin(0)]
317
+
318
+ begin
319
+ arr_key = Integer(arr_key)
320
+ rescue ArgumentError
321
+ raise KeyError.new("Key #{arr_key.to_s} is not an integer")
322
+ end
323
+
324
+ unless @subProperty.key?(txt_key)
325
+ raise KeyError.new("Key #{match[0]} is not valid")
326
+ end
327
+
328
+ #move inside
329
+ @subProperty = @subProperty[txt_key]
330
+
331
+ if @subProperty.is_a?(Array) && arr_key < @subProperty.length
332
+ #If list and list index exists then move to the index
333
+ @subProperty = @subProperty[arr_key]
334
+ else
335
+ raise KeyError.new("Invalid key index #{arr_key.to_s}")
336
+ end
337
+
338
+ end
339
+
340
+
341
+
342
+ end
343
+
344
+
345
+ ################################################################################
346
+ # BaseObject
347
+ ################################################################################
348
+
349
+ class BaseObject < RequestMap
350
+ include MasterCard::Core::Controller
351
+
352
+ def initialize(requestMap = nil)
353
+
354
+ #call the base class constructor
355
+ super()
356
+
357
+ unless requestMap.nil?
358
+ setAll(requestMap.getObject())
359
+ end
360
+
361
+ end
362
+
363
+
364
+ def getResourcePath(action)
365
+ raise NotImplementedError.new("Child class must define getResourcePath method to use this class")
366
+ end
367
+
368
+ def getHeaderParams(action)
369
+ raise NotImplementedError.new("Child class must define getHeaderParams method to use this class")
370
+ end
371
+
372
+ def getQueryParams(action)
373
+ raise NotImplementedError.new("Child class must define getQueryParams method to use this class")
374
+ end
375
+
376
+ def self.getApiVersion()
377
+ raise NotImplementedError.new("Child class must define getApiVersion method to use this class")
378
+ end
379
+
380
+ def self.readObject(inputObject,criteria=nil)
381
+
382
+ unless criteria.nil?
383
+
384
+ if criteria.is_a?(RequestMap)
385
+ inputObject.setAll(criteria.getObject())
386
+ else
387
+ inputObject.setAll(criteria)
388
+ end
389
+
390
+ end
391
+
392
+ return self.execute(APIController::ACTION_READ,inputObject)
393
+
394
+ end
395
+
396
+ def self.listObjects(inputObject)
397
+ return self.execute(APIController::ACTION_LIST,inputObject)
398
+ end
399
+
400
+ def self.createObject(inputObject)
401
+ return self.execute(APIController::ACTION_CREATE,inputObject)
402
+ end
403
+
404
+ def self.queryObject(inputObject)
405
+ return self.execute(APIController::ACTION_QUERY,inputObject)
406
+ end
407
+
408
+ def self.deleteObject(inputObject)
409
+ return self.execute(APIController::ACTION_DELETE,inputObject)
410
+ end
411
+
412
+ def self.updateObject(inputObject)
413
+ return self.execute(APIController::ACTION_UPDATE,inputObject)
414
+ end
415
+
416
+ private
417
+
418
+ def self.execute(action,inputObject)
419
+
420
+ controller = APIController.new(self.getApiVersion)
421
+ response = controller.execute(action,inputObject.getResourcePath(action),inputObject.getHeaderParams(action),inputObject.getQueryParams(action),inputObject.getObject())
422
+ returnObjClass = inputObject.class
423
+
424
+ if action == APIController::ACTION_LIST
425
+ returnObj = []
426
+
427
+ if response.key?(RequestMap::KEY_LIST)
428
+ response = response[RequestMap::KEY_LIST]
429
+ end
430
+
431
+ if response.is_a?(Hash)
432
+
433
+ response.each do |key,value|
434
+
435
+ requestMap = RequestMap.new
436
+ requestMap.setAll(value)
437
+ returnObj.push(returnObjClass.new(requestMap))
438
+
439
+ end
440
+
441
+ elsif response.is_a(Array)
442
+
443
+ response.each do |value|
444
+ requestMap = RequestMap.new
445
+ requestMap.setAll(value)
446
+ returnObj.push(returnObjClass.new(requestMap))
447
+
448
+ end
449
+
450
+ end
451
+ return returnObj
452
+ else
453
+
454
+ requestMap = RequestMap.new
455
+ requestMap.setAll(response)
456
+ return returnObjClass.new(requestMap)
457
+
458
+ end
459
+
460
+ end
461
+
462
+ end
463
+
464
+
465
+ end
466
+ end
467
+ end