A class that simplifies building XML {Parser} rules. This is also a compatability layer between the old and new formats of the api config.
@return [Hash] Returns a hash of rules defined by this grammar.
# File lib/aws/core/xml/grammar.rb, line 76 def self.customize customizations = nil, rules = {}, opts = {}, &block grammar = self.new(deep_copy(rules), opts) grammar.send(:apply_customizations, customizations) if customizations grammar.instance_eval(&block) if block_given? grammar end
# File lib/aws/core/xml/grammar.rb, line 23 def initialize rules = {}, options = {} @rules = rules @context = @rules @element_name = 'xml' @inflect_rename = options.key?(:inflect_rename) ? options[:inflect_rename] : true end
# File lib/aws/core/xml/grammar.rb, line 83 def self.parse xml self.new.parse(xml) end
Performs a deep copy of the rules hash so that it can be customized without chaning the parent grammar.
# File lib/aws/core/xml/grammar.rb, line 91 def self.deep_copy rules rules.inject({}) do |copy,(key,value)| copy[key] = value.is_a?(Hash) ? deep_copy(value) : value copy end end
Returns a new grammar (leaving the current one un-modified) with the given customizations applied. Customizations can be given in a hash-form or in a block form.
@example Block-form customizations
grammar.customize do element "EnumElement" do symbol_value list end end
@example Hash-form customizations
grammar.customize "EnumElement" => [:symbol_value, :list]
@return [Grammar] Returns a grammar with the given customizations
applied.
# File lib/aws/core/xml/grammar.rb, line 63 def customize customizations = nil, &block opts = { :inflect_rename => @inflect_rename } self.class.customize(customizations, @rules, opts, &block) end
Applies customizations to the current grammar, not returning a new grammar.
# File lib/aws/core/xml/grammar.rb, line 70 def customize! customizations = nil, &block apply_customizations(customizations) if customizations instance_eval(&block) if block_given? self end
Parses the XML with the rules provided by the current grammar. This method is meant to provide backwards compatability with the old XmlGrammar class that handled rules and parsing. @param [String] xml @return [Data] Returns a hash-like parsed response.
# File lib/aws/core/xml/grammar.rb, line 36 def parse xml Data.new(Parser.parse(xml, rules)) end
# File lib/aws/core/xml/grammar.rb, line 98 def apply_customizations customizations customizations.each do |item| (type, identifier, args) = parse_customization_item(item) case type when :method validate_config_method(identifier) validate_args(identifier, args) send(identifier, *args) when :element element(identifier) do apply_customizations(args) end end end end
# File lib/aws/core/xml/grammar.rb, line 247 def blob_value @context[:type] = :blob end
# File lib/aws/core/xml/grammar.rb, line 242 def boolean_value @context[:type] = :boolean end
# File lib/aws/core/xml/grammar.rb, line 194 def collect_values @context[:list] = true end
# File lib/aws/core/xml/grammar.rb, line 238 def construct_value &block raise 'remove the need for this' end
# File lib/aws/core/xml/grammar.rb, line 298 def context_for_child child_element_name @context[:children] ||= {} @context[:children][child_element_name] ||= {} @context[:children][child_element_name] end
# File lib/aws/core/xml/grammar.rb, line 252 def datetime_value @context[:type] = :datetime end
# File lib/aws/core/xml/grammar.rb, line 202 def default_value name, value @context[:defaults] ||= {} @context[:defaults][name] = value end
customization methods
# File lib/aws/core/xml/grammar.rb, line 158 def element element_name, &block parent_context = @context parent_element_name = @element_name @context = context_for_child(element_name) @element_name = element_name begin if block_given? block.arity == 1 ? yield(parent_element_name) : yield end ensure @context = parent_context @element_name = parent_element_name end end
# File lib/aws/core/xml/grammar.rb, line 284 def eql? other other.is_a?(Grammar) and self.rules == other.rules end
# File lib/aws/core/xml/grammar.rb, line 274 def float_value @context[:type] = :float end
# File lib/aws/core/xml/grammar.rb, line 190 def force @context[:force] = true end
# File lib/aws/core/xml/grammar.rb, line 290 def http_trait *args; end
# File lib/aws/core/xml/grammar.rb, line 178 def ignore @context[:ignore] = true end
# File lib/aws/core/xml/grammar.rb, line 198 def index index_name, options = {} @context[:index] = options.merge(:name => index_name) end
# File lib/aws/core/xml/grammar.rb, line 150 def inflect value Inflection.ruby_name(value.to_s).to_sym end
# File lib/aws/core/xml/grammar.rb, line 268 def integer_value @context[:type] = :integer end
# File lib/aws/core/xml/grammar.rb, line 207 def list child_element_name = nil, &block if child_element_name ignore element(child_element_name) do |parent_element_name| rename(parent_element_name) collect_values yield if block_given? end else collect_values end end
# File lib/aws/core/xml/grammar.rb, line 224 def map map_element_name, key_element_name, value_element_name ignore element(map_element_name) do |parent_element_name| rename(parent_element_name) map_entry(key_element_name, value_element_name) end end
# File lib/aws/core/xml/grammar.rb, line 220 def map_entry key_element_name, value_element_name @context[:map] = [key_element_name, value_element_name] end
# File lib/aws/core/xml/grammar.rb, line 114 def parse_customization_item item case item when Symbol [:method, item, []] when Hash (method, arg) = item.to_a.first if method.kind_of?(Symbol) [:method, method, [arg].flatten] else [:element, method, arg] end end end
# File lib/aws/core/xml/grammar.rb, line 289 def position *args; end
# File lib/aws/core/xml/grammar.rb, line 182 def rename new_name if @inflect_rename @context[:rename] = inflect(new_name) else @context[:rename] = new_name end end
# File lib/aws/core/xml/grammar.rb, line 263 def string_value @context[:type] = :string end
# File lib/aws/core/xml/grammar.rb, line 279 def symbol_value @context[:type] = :symbol end
# File lib/aws/core/xml/grammar.rb, line 257 def time_value @context[:type] = :time end
# File lib/aws/core/xml/grammar.rb, line 139 def validate_args(identifier, args) arity = method(identifier).arity if args.length > 0 raise "#{identifier} does not accept an argument" if arity == 0 else raise "#{identifier} requires an argument" unless arity == 0 || arity == -1 end end
# File lib/aws/core/xml/grammar.rb, line 128 def validate_config_method(method) allow_methods = %w( rename attribute_name boolean integer long float list force string ignore collect_values symbol_value timestamp map_entry map blob position ) unless allow_methods.include?(method.to_s) raise "#{method} cannot be used in configuration" end end
# File lib/aws/core/xml/grammar.rb, line 232 def wrapper method_name, options = {}, &block options[:for].each do |child| context_for_child(child)[:wrap] = method_name end end