Class: CoreLibrary::UnionTypeHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/apimatic-core/utilities/union_type_helper.rb

Overview

Helper methods for handling union types.

Constant Summary collapse

NONE_MATCHED_ERROR_MESSAGE =
'We could not match any acceptable types against the given JSON.'.freeze
MORE_THAN_1_MATCHED_ERROR_MESSAGE =
'There are more than one acceptable type matched against the given JSON.'.freeze

Class Method Summary collapse

Class Method Details

.check_item_validity(is_for_one_of, is_valid, matched_count) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 79

def self.check_item_validity(is_for_one_of, is_valid, matched_count)
  if is_valid && is_for_one_of
    is_valid = matched_count == 1
  elsif is_valid
    is_valid = matched_count >= 1
  end
  is_valid
end

.deserialize_array_case(array_value, collection_cases, should_symbolize: false) ⇒ Object



242
243
244
245
246
247
248
249
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 242

def self.deserialize_array_case(array_value, collection_cases, should_symbolize: false)
  deserialized_value = []
  array_value.each_with_index do |item, index|
    valid_case = collection_cases[index].find(&:is_valid)
    deserialized_value << valid_case.deserialize(item, should_symbolize: should_symbolize)
  end
  deserialized_value
end

.deserialize_array_of_dict_case(array_value, collection_cases, should_symbolize: false) ⇒ Object



213
214
215
216
217
218
219
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 213

def self.deserialize_array_of_dict_case(array_value, collection_cases, should_symbolize: false)
  deserialized_value = []
  array_value.each_with_index do |item, index|
    deserialized_value << deserialize_dict_case(item, collection_cases[index], should_symbolize: should_symbolize)
  end
  deserialized_value
end

.deserialize_dict_case(dict_value, collection_cases, should_symbolize: false) ⇒ Object



233
234
235
236
237
238
239
240
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 233

def self.deserialize_dict_case(dict_value, collection_cases, should_symbolize: false)
  deserialized_value = {}
  dict_value.each do |key, value|
    valid_case = collection_cases[key].find(&:is_valid)
    deserialized_value[key] = valid_case.deserialize(value, should_symbolize: should_symbolize)
  end
  deserialized_value
end

.deserialize_dict_of_array_case(dict_value, collection_cases, should_symbolize: false) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 221

def self.deserialize_dict_of_array_case(dict_value, collection_cases, should_symbolize: false)
  deserialized_value = {}
  dict_value.each do |key, value|
    deserialized_value[key] = deserialize_array_case(
      value,
      collection_cases[key],
      should_symbolize: should_symbolize
    )
  end
  deserialized_value
end

.deserialize_value(value, context, collection_cases, union_types, should_symbolize: false) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 200

def self.deserialize_value(value, context, collection_cases, union_types, should_symbolize: false)
  return deserialize_array_of_dict_case(value, collection_cases, should_symbolize: should_symbolize) if
    context.is_array && context.is_dict && context.is_array_of_dict

  return deserialize_dict_of_array_case(value, collection_cases, should_symbolize: should_symbolize) if
    context.is_array && context.is_dict

  return deserialize_array_case(value, collection_cases, should_symbolize: should_symbolize) if context.is_array
  return deserialize_dict_case(value, collection_cases, should_symbolize: should_symbolize) if context.is_dict

  get_deserialized_value(union_types, value, should_symbolize: should_symbolize)
end

.get_combined_error_messages(union_types) ⇒ Object



270
271
272
273
274
275
276
277
278
279
280
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 270

def self.get_combined_error_messages(union_types)
  combined_error_messages = []
  union_types.each do |union_type|
    if union_type.instance_of?(LeafType)
      combined_error_messages << union_type.type_to_match.name
    elsif union_type.error_messages
      combined_error_messages << union_type.error_messages.to_a.join(', ')
    end
  end
  combined_error_messages
end

.get_deserialized_value(union_types, value, should_symbolize: false) ⇒ Object



251
252
253
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 251

def self.get_deserialized_value(union_types, value, should_symbolize: false)
  union_types.find(&:is_valid).deserialize(value, should_symbolize: should_symbolize)
end

.get_matched_count(value, union_types, is_for_one_of) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 96

def self.get_matched_count(value, union_types, is_for_one_of)
  matched_count = get_valid_cases_count(value, union_types)

  if is_for_one_of && matched_count == 1
    return matched_count
  elsif !is_for_one_of && matched_count.positive?
    return matched_count
  end

  matched_count = handle_discriminator_cases(value, union_types)
  matched_count
end

.get_serialized_value(union_types, value) ⇒ Object



196
197
198
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 196

def self.get_serialized_value(union_types, value)
  union_types.find(&:is_valid).serialize(value)
end

.get_valid_cases_count(value, union_types) ⇒ Object



109
110
111
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 109

def self.get_valid_cases_count(value, union_types)
  union_types.count { |union_type| union_type.validate(value).is_valid }
end

.handle_discriminator_cases(value, union_types) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 113

def self.handle_discriminator_cases(value, union_types)
  has_discriminator_cases = union_types.all? do |union_type|
    union_type.union_type_context.discriminator && union_type.union_type_context.discriminator_value
  end

  if has_discriminator_cases
    union_types.each do |union_type|
      union_type.union_type_context.discriminator = nil
      union_type.union_type_context.discriminator_value = nil
    end

    get_valid_cases_count(value, union_types)
  else
    0
  end
end

.invalid_array_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


140
141
142
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 140

def self.invalid_array_value?(value)
  value.nil? || !value.instance_of?(Array)
end

.invalid_dict_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 144

def self.invalid_dict_value?(value)
  value.nil? || !value.instance_of?(Hash)
end

.make_deep_copies(union_types) ⇒ Object



88
89
90
91
92
93
94
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 88

def self.make_deep_copies(union_types)
  nested_cases = []
  union_types.each do |union_type|
    nested_cases << union_type.dup
  end
  nested_cases
end

.optional_or_nullable_case?(current_context, inner_contexts) ⇒ Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 130

def self.optional_or_nullable_case?(current_context, inner_contexts)
  current_context.nullable_or_optional? || inner_contexts.any?(&:nullable_or_optional?)
end

.process_array_items(union_types, array_value, is_for_one_of) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 65

def self.process_array_items(union_types, array_value, is_for_one_of)
  is_valid = true
  collection_cases = []

  array_value.each do |item|
    union_type_cases = make_deep_copies(union_types)
    matched_count = get_matched_count(item, union_type_cases, is_for_one_of)
    is_valid = check_item_validity(is_for_one_of, is_valid, matched_count)
    collection_cases << union_type_cases
  end

  [is_valid, collection_cases]
end

.process_dict_items(union_types, dict_value, is_for_one_of) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 43

def self.process_dict_items(union_types, dict_value, is_for_one_of)
  is_valid = true
  collection_cases = {}

  dict_value.each do |key, value|
    union_type_cases = make_deep_copies(union_types)
    matched_count = get_matched_count(value, union_type_cases, is_for_one_of)
    is_valid = check_item_validity(is_for_one_of, is_valid, matched_count)
    collection_cases[key] = union_type_cases
  end

  [is_valid, collection_cases]
end

.process_errors(value, union_types, error_messages, is_nested, is_for_one_of) ⇒ Object



255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 255

def self.process_errors(value, union_types, error_messages, is_nested, is_for_one_of)
  error_messages << UnionTypeHelper.get_combined_error_messages(union_types).join(', ')

  unless is_nested
    UnionTypeHelper.raise_validation_exception(
      value,
      union_types,
      error_messages.to_a.join(', '),
      is_for_one_of
    )
  end

  error_messages
end

.raise_validation_exception(value, union_types, error_message, is_for_one_of) ⇒ Object



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 282

def self.raise_validation_exception(value, union_types, error_message, is_for_one_of)
  unless is_for_one_of
    raise AnyOfValidationException,
          "#{UnionTypeHelper::NONE_MATCHED_ERROR_MESSAGE}" \
          "\nActual Value: #{ApiHelper.json_serialize(value)}\nExpected Type: Any Of #{error_message}."

  end

  matched_count = union_types.count(&:is_valid)
  message = matched_count > 0 ?
              UnionTypeHelper::MORE_THAN_1_MATCHED_ERROR_MESSAGE : UnionTypeHelper::NONE_MATCHED_ERROR_MESSAGE

  raise OneOfValidationException,
        "#{message}\nActual Value: #{ApiHelper.json_serialize(value)}\nExpected Type: One Of #{error_message}."
end

.serialize_array_case(array_value, collection_cases) ⇒ Object



187
188
189
190
191
192
193
194
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 187

def self.serialize_array_case(array_value, collection_cases)
  serialized_value = []
  array_value.each_with_index do |item, index|
    valid_case = collection_cases[index].find(&:is_valid)
    serialized_value << valid_case.serialize(item)
  end
  serialized_value
end

.serialize_array_of_dict_case(array_value, collection_cases) ⇒ Object



162
163
164
165
166
167
168
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 162

def self.serialize_array_of_dict_case(array_value, collection_cases)
  serialized_value = []
  array_value.each_with_index do |item, index|
    serialized_value << serialize_dict_case(item, collection_cases[index])
  end
  serialized_value
end

.serialize_dict_case(dict_value, collection_cases) ⇒ Object



178
179
180
181
182
183
184
185
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 178

def self.serialize_dict_case(dict_value, collection_cases)
  serialized_value = {}
  dict_value.each do |key, value|
    valid_case = collection_cases[key].find(&:is_valid)
    serialized_value[key] = valid_case.serialize(value)
  end
  serialized_value
end

.serialize_dict_of_array_case(dict_value, collection_cases) ⇒ Object



170
171
172
173
174
175
176
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 170

def self.serialize_dict_of_array_case(dict_value, collection_cases)
  serialized_value = {}
  dict_value.each do |key, value|
    serialized_value[key] = serialize_array_case(value, collection_cases[key])
  end
  serialized_value
end

.serialize_value(value, context, collection_cases, union_types) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 148

def self.serialize_value(value, context, collection_cases, union_types)
  return serialize_array_of_dict_case(value, collection_cases) if
    context.is_array && context.is_dict && context.is_array_of_dict

  return serialize_dict_of_array_case(value, collection_cases) if
    context.is_array && context.is_dict

  return serialize_array_case(value, collection_cases) if context.is_array

  return serialize_dict_case(value, collection_cases) if context.is_dict

  get_serialized_value(union_types, value)
end

.update_nested_flag_for_union_types(nested_union_types) ⇒ Object



134
135
136
137
138
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 134

def self.update_nested_flag_for_union_types(nested_union_types)
  nested_union_types.each do |union_type|
    union_type.union_type_context.is_nested = true
  end
end

.validate_array_case(union_types, array_value, is_for_one_of) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 57

def self.validate_array_case(union_types, array_value, is_for_one_of)
  return [false, []] if invalid_array_value?(array_value)

  is_valid, collection_cases = process_array_items(union_types, array_value, is_for_one_of)

  [is_valid, collection_cases]
end

.validate_array_of_dict_case(union_types, array_value, is_for_one_of) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 7

def self.validate_array_of_dict_case(union_types, array_value, is_for_one_of)
  return [false, []] if invalid_array_value?(array_value)

  collection_cases = []
  valid_cases = []
  array_value.each do |item|
    case_validity, inner_dictionary = validate_dict_case(union_types, item, is_for_one_of)
    collection_cases << inner_dictionary
    valid_cases << case_validity
  end
  is_valid = valid_cases.count(true) == array_value.size
  [is_valid, collection_cases]
end

.validate_dict_case(union_types, dict_value, is_for_one_of) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 35

def self.validate_dict_case(union_types, dict_value, is_for_one_of)
  return [false, []] if invalid_dict_value?(dict_value)

  is_valid, collection_cases = process_dict_items(union_types, dict_value, is_for_one_of)

  [is_valid, collection_cases]
end

.validate_dict_of_array_case(union_types, dict_value, is_for_one_of) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/apimatic-core/utilities/union_type_helper.rb', line 21

def self.validate_dict_of_array_case(union_types, dict_value, is_for_one_of)
  return [false, []] if invalid_dict_value?(dict_value)

  collection_cases = {}
  valid_cases = []
  dict_value.each do |key, item|
    case_validity, inner_array = validate_array_case(union_types, item, is_for_one_of)
    collection_cases[key] = inner_array
    valid_cases << case_validity
  end
  is_valid = valid_cases.count(true) == dict_value.size
  [is_valid, collection_cases]
end