|
19 | 19 | # |
20 | 20 | # This class validates input parameters before passing them to Savon. |
21 | 21 |
|
| 22 | +require 'ads_common/utils' |
| 23 | + |
22 | 24 | module AdsCommon |
23 | 25 | class ParametersValidator |
24 | 26 | # Savon special keys. |
@@ -71,12 +73,49 @@ def validate_arguments(args_hash, fields_list, type_ns = nil) |
71 | 73 | item_type = get_full_type_signature(field[:type]) |
72 | 74 | item_ns = field[:ns] || type_ns |
73 | 75 | key = handle_namespace_override(args_hash, key, item_ns) if item_ns |
74 | | - validate_arg(item, args_hash, key, item_type) |
| 76 | + |
| 77 | + # Separate validation for choice types as we need to inject nodes into |
| 78 | + # the tree. Validate as usual if not a choice type. |
| 79 | + unless validate_choice_argument(item, args_hash, key, item_type) |
| 80 | + validate_arg(item, args_hash, key, item_type) |
| 81 | + end |
75 | 82 | end |
76 | 83 | end |
77 | 84 | return args_hash |
78 | 85 | end |
79 | 86 |
|
| 87 | + # Special handling for choice types. Goes over each item, checks xsi_type |
| 88 | + # is set and correct and injects new node for it into the tree. After that, |
| 89 | + # recurces with the correct item type. |
| 90 | + def validate_choice_argument(item, parent, key, item_type) |
| 91 | + result = false |
| 92 | + if item_type.kind_of?(Hash) && item_type.include?(:choices) |
| 93 | + new_root = {} |
| 94 | + choice_items = arrayize(item) |
| 95 | + choice_items.each do |choice_item| |
| 96 | + choice_type = choice_item.delete(:xsi_type) |
| 97 | + choice_item_type = |
| 98 | + find_choice_by_xsi_type(choice_type, item_type[:choices]) |
| 99 | + if choice_type.nil? || choice_item_type.nil? |
| 100 | + raise AdsCommon::Errors::TypeMismatchError.new( |
| 101 | + 'choice subtype', choice_type, choice_item.to_s()) |
| 102 | + end |
| 103 | + new_root[choice_type] ||= [] |
| 104 | + new_root[choice_type] << choice_item |
| 105 | + type_signature = get_full_type_signature(choice_type) |
| 106 | + validate_arg(choice_item, new_root, choice_type, type_signature) |
| 107 | + end |
| 108 | + parent[key] = new_root |
| 109 | + result = true |
| 110 | + end |
| 111 | + return result |
| 112 | + end |
| 113 | + |
| 114 | + def find_choice_by_xsi_type(xsi_type, item_def) |
| 115 | + index = item_def.index {|item| xsi_type.eql?(item[:original_name])} |
| 116 | + return index.nil? ? nil : item_def[index] |
| 117 | + end |
| 118 | + |
80 | 119 | # Checks if no extra fields provided outside of known ones. |
81 | 120 | def check_extra_fields(args_hash, known_fields) |
82 | 121 | extra_fields = args_hash.keys - known_fields - IGNORED_HASH_KEYS |
|
0 commit comments