apimatic_core 0.2.3 → 0.3.0

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.
@@ -17,7 +17,7 @@ module CoreLibrary
17
17
  hash[key] = {}
18
18
  date_time.each do |k, v|
19
19
  hash[key][k] =
20
- v.is_a?(DateTime) ? DateTimeHelper.to_rfc1123(v) : v
20
+ v.instance_of?(DateTime) ? DateTimeHelper.to_rfc1123(v) : v
21
21
  end
22
22
  hash[key]
23
23
  end
@@ -29,13 +29,13 @@ module CoreLibrary
29
29
  return if date_time.nil?
30
30
 
31
31
  hash[key] = date_time.map do |v|
32
- v.is_a?(DateTime) ? DateTimeHelper.to_rfc1123(v) : v
32
+ v.instance_of?(DateTime) ? DateTimeHelper.to_rfc1123(v) : v
33
33
  end
34
34
  end
35
35
 
36
36
  # Safely converts a DateTime object into a unix format string.
37
37
  # @param [DateTime] date_time The DateTime object.
38
- # @return [String] The unix formatted datetime string.
38
+ # @return [Integer] The unix formatted datetime integer.
39
39
  def self.to_unix(date_time)
40
40
  date_time.to_time.utc.to_i unless date_time.nil?
41
41
  end
@@ -49,7 +49,7 @@ module CoreLibrary
49
49
  hash[key] = {}
50
50
  date_time.each do |k, v|
51
51
  hash[key][k] =
52
- v.is_a?(DateTime) ? DateTimeHelper.to_unix(v) : v
52
+ v.instance_of?(DateTime) ? DateTimeHelper.to_unix(v) : v
53
53
  end
54
54
  hash[key]
55
55
  end
@@ -61,7 +61,7 @@ module CoreLibrary
61
61
  return if date_time.nil?
62
62
 
63
63
  hash[key] = date_time.map do |v|
64
- v.is_a?(DateTime) ? DateTimeHelper.to_unix(v) : v
64
+ v.instance_of?(DateTime) ? DateTimeHelper.to_unix(v) : v
65
65
  end
66
66
  end
67
67
 
@@ -81,7 +81,7 @@ module CoreLibrary
81
81
  hash[key] = {}
82
82
  date_time.each do |k, v|
83
83
  hash[key][k] =
84
- v.is_a?(DateTime) ? DateTimeHelper.to_rfc3339(v) : v
84
+ v.instance_of?(DateTime) ? DateTimeHelper.to_rfc3339(v) : v
85
85
  end
86
86
  hash[key]
87
87
  end
@@ -93,7 +93,7 @@ module CoreLibrary
93
93
  return if date_time.nil?
94
94
 
95
95
  hash[key] = date_time.map do |v|
96
- v.is_a?(DateTime) ? DateTimeHelper.to_rfc3339(v) : v
96
+ v.instance_of?(DateTime) ? DateTimeHelper.to_rfc3339(v) : v
97
97
  end
98
98
  end
99
99
 
@@ -122,5 +122,52 @@ module CoreLibrary
122
122
  DateTime.rfc3339("#{date_time}Z")
123
123
  end
124
124
  end
125
+
126
+ def self.valid_datetime?(dt_format, dt)
127
+ case dt_format
128
+ when DateTimeFormat::HTTP_DATE_TIME
129
+ return DateTimeHelper.rfc_1123?(dt)
130
+ when DateTimeFormat::RFC3339_DATE_TIME
131
+ return DateTimeHelper.rfc_3339?(dt)
132
+ when DateTimeFormat::UNIX_DATE_TIME
133
+ return DateTimeHelper.unix_timestamp?(dt)
134
+ end
135
+
136
+ false
137
+ end
138
+
139
+ def self.valid_date?(date_value)
140
+ if date_value.instance_of?(Date)
141
+ true
142
+ elsif date_value.instance_of?(String) && date_value.match?(/^\d{4}-\d{2}-\d{2}$/)
143
+ DateTime.strptime(date_value, '%Y-%m-%d')
144
+ true
145
+ else
146
+ false
147
+ end
148
+ rescue ArgumentError
149
+ false
150
+ end
151
+
152
+ def self.rfc_1123?(datetime_value)
153
+ DateTime.strptime(datetime_value, '%a, %d %b %Y %H:%M:%S %Z')
154
+ true
155
+ rescue ArgumentError, TypeError
156
+ false
157
+ end
158
+
159
+ def self.rfc_3339?(datetime_value)
160
+ DateTime.strptime(datetime_value, '%Y-%m-%dT%H:%M:%S')
161
+ true
162
+ rescue ArgumentError, TypeError
163
+ false
164
+ end
165
+
166
+ def self.unix_timestamp?(timestamp)
167
+ Time.at(Float(timestamp))
168
+ true
169
+ rescue ArgumentError, TypeError
170
+ false
171
+ end
125
172
  end
126
173
  end
@@ -0,0 +1,298 @@
1
+ module CoreLibrary
2
+ # Helper methods for handling union types.
3
+ class UnionTypeHelper
4
+ NONE_MATCHED_ERROR_MESSAGE = 'We could not match any acceptable types against the given JSON.'.freeze
5
+ MORE_THAN_1_MATCHED_ERROR_MESSAGE = 'There are more than one acceptable type matched against the given JSON.'.freeze
6
+
7
+ def self.validate_array_of_dict_case(union_types, array_value, is_for_one_of)
8
+ return [false, []] if invalid_array_value?(array_value)
9
+
10
+ collection_cases = []
11
+ valid_cases = []
12
+ array_value.each do |item|
13
+ case_validity, inner_dictionary = validate_dict_case(union_types, item, is_for_one_of)
14
+ collection_cases << inner_dictionary
15
+ valid_cases << case_validity
16
+ end
17
+ is_valid = valid_cases.count(true) == array_value.size
18
+ [is_valid, collection_cases]
19
+ end
20
+
21
+ def self.validate_dict_of_array_case(union_types, dict_value, is_for_one_of)
22
+ return [false, []] if invalid_dict_value?(dict_value)
23
+
24
+ collection_cases = {}
25
+ valid_cases = []
26
+ dict_value.each do |key, item|
27
+ case_validity, inner_array = validate_array_case(union_types, item, is_for_one_of)
28
+ collection_cases[key] = inner_array
29
+ valid_cases << case_validity
30
+ end
31
+ is_valid = valid_cases.count(true) == dict_value.size
32
+ [is_valid, collection_cases]
33
+ end
34
+
35
+ def self.validate_dict_case(union_types, dict_value, is_for_one_of)
36
+ return [false, []] if invalid_dict_value?(dict_value)
37
+
38
+ is_valid, collection_cases = process_dict_items(union_types, dict_value, is_for_one_of)
39
+
40
+ [is_valid, collection_cases]
41
+ end
42
+
43
+ def self.process_dict_items(union_types, dict_value, is_for_one_of)
44
+ is_valid = true
45
+ collection_cases = {}
46
+
47
+ dict_value.each do |key, value|
48
+ union_type_cases = make_deep_copies(union_types)
49
+ matched_count = get_matched_count(value, union_type_cases, is_for_one_of)
50
+ is_valid = check_item_validity(is_for_one_of, is_valid, matched_count)
51
+ collection_cases[key] = union_type_cases
52
+ end
53
+
54
+ [is_valid, collection_cases]
55
+ end
56
+
57
+ def self.validate_array_case(union_types, array_value, is_for_one_of)
58
+ return [false, []] if invalid_array_value?(array_value)
59
+
60
+ is_valid, collection_cases = process_array_items(union_types, array_value, is_for_one_of)
61
+
62
+ [is_valid, collection_cases]
63
+ end
64
+
65
+ def self.process_array_items(union_types, array_value, is_for_one_of)
66
+ is_valid = true
67
+ collection_cases = []
68
+
69
+ array_value.each do |item|
70
+ union_type_cases = make_deep_copies(union_types)
71
+ matched_count = get_matched_count(item, union_type_cases, is_for_one_of)
72
+ is_valid = check_item_validity(is_for_one_of, is_valid, matched_count)
73
+ collection_cases << union_type_cases
74
+ end
75
+
76
+ [is_valid, collection_cases]
77
+ end
78
+
79
+ def self.check_item_validity(is_for_one_of, is_valid, matched_count)
80
+ if is_valid && is_for_one_of
81
+ is_valid = matched_count == 1
82
+ elsif is_valid
83
+ is_valid = matched_count >= 1
84
+ end
85
+ is_valid
86
+ end
87
+
88
+ def self.make_deep_copies(union_types)
89
+ nested_cases = []
90
+ union_types.each do |union_type|
91
+ nested_cases << union_type.dup
92
+ end
93
+ nested_cases
94
+ end
95
+
96
+ def self.get_matched_count(value, union_types, is_for_one_of)
97
+ matched_count = get_valid_cases_count(value, union_types)
98
+
99
+ if is_for_one_of && matched_count == 1
100
+ return matched_count
101
+ elsif !is_for_one_of && matched_count.positive?
102
+ return matched_count
103
+ end
104
+
105
+ matched_count = handle_discriminator_cases(value, union_types)
106
+ matched_count
107
+ end
108
+
109
+ def self.get_valid_cases_count(value, union_types)
110
+ union_types.count { |union_type| union_type.validate(value).is_valid }
111
+ end
112
+
113
+ def self.handle_discriminator_cases(value, union_types)
114
+ has_discriminator_cases = union_types.all? do |union_type|
115
+ union_type.union_type_context.discriminator && union_type.union_type_context.discriminator_value
116
+ end
117
+
118
+ if has_discriminator_cases
119
+ union_types.each do |union_type|
120
+ union_type.union_type_context.discriminator = nil
121
+ union_type.union_type_context.discriminator_value = nil
122
+ end
123
+
124
+ get_valid_cases_count(value, union_types)
125
+ else
126
+ 0
127
+ end
128
+ end
129
+
130
+ def self.optional_or_nullable_case?(current_context, inner_contexts)
131
+ current_context.nullable_or_optional? || inner_contexts.any?(&:nullable_or_optional?)
132
+ end
133
+
134
+ def self.update_nested_flag_for_union_types(nested_union_types)
135
+ nested_union_types.each do |union_type|
136
+ union_type.union_type_context.is_nested = true
137
+ end
138
+ end
139
+
140
+ def self.invalid_array_value?(value)
141
+ value.nil? || !value.instance_of?(Array)
142
+ end
143
+
144
+ def self.invalid_dict_value?(value)
145
+ value.nil? || !value.instance_of?(Hash)
146
+ end
147
+
148
+ def self.serialize_value(value, context, collection_cases, union_types)
149
+ return serialize_array_of_dict_case(value, collection_cases) if
150
+ context.is_array && context.is_dict && context.is_array_of_dict
151
+
152
+ return serialize_dict_of_array_case(value, collection_cases) if
153
+ context.is_array && context.is_dict
154
+
155
+ return serialize_array_case(value, collection_cases) if context.is_array
156
+
157
+ return serialize_dict_case(value, collection_cases) if context.is_dict
158
+
159
+ get_serialized_value(union_types, value)
160
+ end
161
+
162
+ def self.serialize_array_of_dict_case(array_value, collection_cases)
163
+ serialized_value = []
164
+ array_value.each_with_index do |item, index|
165
+ serialized_value << serialize_dict_case(item, collection_cases[index])
166
+ end
167
+ serialized_value
168
+ end
169
+
170
+ def self.serialize_dict_of_array_case(dict_value, collection_cases)
171
+ serialized_value = {}
172
+ dict_value.each do |key, value|
173
+ serialized_value[key] = serialize_array_case(value, collection_cases[key])
174
+ end
175
+ serialized_value
176
+ end
177
+
178
+ def self.serialize_dict_case(dict_value, collection_cases)
179
+ serialized_value = {}
180
+ dict_value.each do |key, value|
181
+ valid_case = collection_cases[key].find(&:is_valid)
182
+ serialized_value[key] = valid_case.serialize(value)
183
+ end
184
+ serialized_value
185
+ end
186
+
187
+ def self.serialize_array_case(array_value, collection_cases)
188
+ serialized_value = []
189
+ array_value.each_with_index do |item, index|
190
+ valid_case = collection_cases[index].find(&:is_valid)
191
+ serialized_value << valid_case.serialize(item)
192
+ end
193
+ serialized_value
194
+ end
195
+
196
+ def self.get_serialized_value(union_types, value)
197
+ union_types.find(&:is_valid).serialize(value)
198
+ end
199
+
200
+ def self.deserialize_value(value, context, collection_cases, union_types, should_symbolize: false)
201
+ return deserialize_array_of_dict_case(value, collection_cases, should_symbolize: should_symbolize) if
202
+ context.is_array && context.is_dict && context.is_array_of_dict
203
+
204
+ return deserialize_dict_of_array_case(value, collection_cases, should_symbolize: should_symbolize) if
205
+ context.is_array && context.is_dict
206
+
207
+ return deserialize_array_case(value, collection_cases, should_symbolize: should_symbolize) if context.is_array
208
+ return deserialize_dict_case(value, collection_cases, should_symbolize: should_symbolize) if context.is_dict
209
+
210
+ get_deserialized_value(union_types, value, should_symbolize: should_symbolize)
211
+ end
212
+
213
+ def self.deserialize_array_of_dict_case(array_value, collection_cases, should_symbolize: false)
214
+ deserialized_value = []
215
+ array_value.each_with_index do |item, index|
216
+ deserialized_value << deserialize_dict_case(item, collection_cases[index], should_symbolize: should_symbolize)
217
+ end
218
+ deserialized_value
219
+ end
220
+
221
+ def self.deserialize_dict_of_array_case(dict_value, collection_cases, should_symbolize: false)
222
+ deserialized_value = {}
223
+ dict_value.each do |key, value|
224
+ deserialized_value[key] = deserialize_array_case(
225
+ value,
226
+ collection_cases[key],
227
+ should_symbolize: should_symbolize
228
+ )
229
+ end
230
+ deserialized_value
231
+ end
232
+
233
+ def self.deserialize_dict_case(dict_value, collection_cases, should_symbolize: false)
234
+ deserialized_value = {}
235
+ dict_value.each do |key, value|
236
+ valid_case = collection_cases[key].find(&:is_valid)
237
+ deserialized_value[key] = valid_case.deserialize(value, should_symbolize: should_symbolize)
238
+ end
239
+ deserialized_value
240
+ end
241
+
242
+ def self.deserialize_array_case(array_value, collection_cases, should_symbolize: false)
243
+ deserialized_value = []
244
+ array_value.each_with_index do |item, index|
245
+ valid_case = collection_cases[index].find(&:is_valid)
246
+ deserialized_value << valid_case.deserialize(item, should_symbolize: should_symbolize)
247
+ end
248
+ deserialized_value
249
+ end
250
+
251
+ def self.get_deserialized_value(union_types, value, should_symbolize: false)
252
+ union_types.find(&:is_valid).deserialize(value, should_symbolize: should_symbolize)
253
+ end
254
+
255
+ def self.process_errors(value, union_types, error_messages, is_nested, is_for_one_of)
256
+ error_messages << UnionTypeHelper.get_combined_error_messages(union_types).join(', ')
257
+
258
+ unless is_nested
259
+ UnionTypeHelper.raise_validation_exception(
260
+ value,
261
+ union_types,
262
+ error_messages.to_a.join(', '),
263
+ is_for_one_of
264
+ )
265
+ end
266
+
267
+ error_messages
268
+ end
269
+
270
+ def self.get_combined_error_messages(union_types)
271
+ combined_error_messages = []
272
+ union_types.each do |union_type|
273
+ if union_type.instance_of?(LeafType)
274
+ combined_error_messages << union_type.type_to_match.name
275
+ elsif union_type.error_messages
276
+ combined_error_messages << union_type.error_messages.to_a.join(', ')
277
+ end
278
+ end
279
+ combined_error_messages
280
+ end
281
+
282
+ def self.raise_validation_exception(value, union_types, error_message, is_for_one_of)
283
+ unless is_for_one_of
284
+ raise AnyOfValidationException,
285
+ "#{UnionTypeHelper::NONE_MATCHED_ERROR_MESSAGE}" \
286
+ "\nActual Value: #{ApiHelper.json_serialize(value)}\nExpected Type: Any Of #{error_message}."
287
+
288
+ end
289
+
290
+ matched_count = union_types.count(&:is_valid)
291
+ message = matched_count > 0 ?
292
+ UnionTypeHelper::MORE_THAN_1_MATCHED_ERROR_MESSAGE : UnionTypeHelper::NONE_MATCHED_ERROR_MESSAGE
293
+
294
+ raise OneOfValidationException,
295
+ "#{message}\nActual Value: #{ApiHelper.json_serialize(value)}\nExpected Type: One Of #{error_message}."
296
+ end
297
+ end
298
+ end
data/lib/apimatic_core.rb CHANGED
@@ -14,6 +14,8 @@ require_relative 'apimatic-core/factories/http_response_factory'
14
14
  require_relative 'apimatic-core/configurations/global_configuration'
15
15
 
16
16
  require_relative 'apimatic-core/exceptions/invalid_auth_credential'
17
+ require_relative 'apimatic-core/exceptions/any_of_validation_exception'
18
+ require_relative 'apimatic-core/exceptions/one_of_validation_exception'
17
19
 
18
20
  require_relative 'apimatic-core/logger/endpoint_logger'
19
21
 
@@ -30,12 +32,18 @@ require_relative 'apimatic-core/types/sdk/validation_exception'
30
32
  require_relative 'apimatic-core/types/sdk/api_exception'
31
33
  require_relative 'apimatic-core/types/xml_attributes'
32
34
 
35
+ require_relative 'apimatic-core/types/union_types/leaf_type'
36
+ require_relative 'apimatic-core/types/union_types/any_of'
37
+ require_relative 'apimatic-core/types/union_types/one_of'
38
+ require_relative 'apimatic-core/types/union_types/union_type_context'
39
+
33
40
  require_relative 'apimatic-core/utilities/api_helper'
34
41
  require_relative 'apimatic-core/utilities/date_time_helper'
35
42
  require_relative 'apimatic-core/utilities/comparison_helper'
36
43
  require_relative 'apimatic-core/utilities/file_helper'
37
44
  require_relative 'apimatic-core/utilities/xml_helper'
38
45
  require_relative 'apimatic-core/utilities/auth_helper'
46
+ require_relative 'apimatic-core/utilities/union_type_helper'
39
47
 
40
48
  require_relative 'apimatic-core/authentication/header_auth'
41
49
  require_relative 'apimatic-core/authentication/query_auth'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apimatic_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - APIMatic Ltd.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-04 00:00:00.000000000 Z
11
+ date: 2023-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: apimatic_core_interfaces
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.0
19
+ version: 0.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.0
26
+ version: 0.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -179,7 +179,9 @@ files:
179
179
  - lib/apimatic-core/authentication/multiple/single_auth.rb
180
180
  - lib/apimatic-core/authentication/query_auth.rb
181
181
  - lib/apimatic-core/configurations/global_configuration.rb
182
+ - lib/apimatic-core/exceptions/any_of_validation_exception.rb
182
183
  - lib/apimatic-core/exceptions/invalid_auth_credential.rb
184
+ - lib/apimatic-core/exceptions/one_of_validation_exception.rb
183
185
  - lib/apimatic-core/factories/http_response_factory.rb
184
186
  - lib/apimatic-core/http/configurations/http_client_configuration.rb
185
187
  - lib/apimatic-core/http/request/http_request.rb
@@ -194,12 +196,17 @@ files:
194
196
  - lib/apimatic-core/types/sdk/base_model.rb
195
197
  - lib/apimatic-core/types/sdk/file_wrapper.rb
196
198
  - lib/apimatic-core/types/sdk/validation_exception.rb
199
+ - lib/apimatic-core/types/union_types/any_of.rb
200
+ - lib/apimatic-core/types/union_types/leaf_type.rb
201
+ - lib/apimatic-core/types/union_types/one_of.rb
202
+ - lib/apimatic-core/types/union_types/union_type_context.rb
197
203
  - lib/apimatic-core/types/xml_attributes.rb
198
204
  - lib/apimatic-core/utilities/api_helper.rb
199
205
  - lib/apimatic-core/utilities/auth_helper.rb
200
206
  - lib/apimatic-core/utilities/comparison_helper.rb
201
207
  - lib/apimatic-core/utilities/date_time_helper.rb
202
208
  - lib/apimatic-core/utilities/file_helper.rb
209
+ - lib/apimatic-core/utilities/union_type_helper.rb
203
210
  - lib/apimatic-core/utilities/xml_helper.rb
204
211
  - lib/apimatic_core.rb
205
212
  homepage: https://apimatic.io