class MSS::Core::XML::Grammar
A class that simplifies building XML
{Parser} rules. This is also a compatability layer between the old and new formats of the api config.
Attributes
@return [Hash] Returns a hash of rules defined by this grammar.
Public Class Methods
# File lib/mss/core/xml/grammar.rb, line 75 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/mss/core/xml/grammar.rb, line 22 def initialize rules = {}, options = {} @rules = rules @context = @rules @element_name = 'xml' @inflect_rename = options.key?(:inflect_rename) ? options[:inflect_rename] : true end
# File lib/mss/core/xml/grammar.rb, line 82 def self.parse xml self.new.parse(xml) end
Protected Class Methods
Performs a deep copy of the rules hash so that it can be customized without chaning the parent grammar.
# File lib/mss/core/xml/grammar.rb, line 90 def self.deep_copy rules rules.inject({}) do |copy,(key,value)| copy[key] = value.is_a?(Hash) ? deep_copy(value) : value copy end end
Public Instance Methods
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/mss/core/xml/grammar.rb, line 62 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/mss/core/xml/grammar.rb, line 69 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/mss/core/xml/grammar.rb, line 35 def parse xml Data.new(Parser.parse(xml, rules)) end
Protected Instance Methods
# File lib/mss/core/xml/grammar.rb, line 97 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/mss/core/xml/grammar.rb, line 244 def blob_value @context[:type] = :blob end
# File lib/mss/core/xml/grammar.rb, line 239 def boolean_value @context[:type] = :boolean end
# File lib/mss/core/xml/grammar.rb, line 191 def collect_values @context[:list] = true end
# File lib/mss/core/xml/grammar.rb, line 235 def construct_value &block raise 'remove the need for this' end
# File lib/mss/core/xml/grammar.rb, line 297 def context_for_child child_element_name @context[:children] ||= {} @context[:children][child_element_name] ||= {} @context[:children][child_element_name] end
# File lib/mss/core/xml/grammar.rb, line 249 def datetime_value @context[:type] = :datetime end
# File lib/mss/core/xml/grammar.rb, line 199 def default_value name, value @context[:defaults] ||= {} @context[:defaults][name] = value end
customization methods
# File lib/mss/core/xml/grammar.rb, line 155 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/mss/core/xml/grammar.rb, line 287 def enum *args; end
# File lib/mss/core/xml/grammar.rb, line 281 def eql? other other.is_a?(Grammar) and self.rules == other.rules end
# File lib/mss/core/xml/grammar.rb, line 271 def float_value @context[:type] = :float end
# File lib/mss/core/xml/grammar.rb, line 187 def force @context[:force] = true end
# File lib/mss/core/xml/grammar.rb, line 289 def http_trait *args; end
# File lib/mss/core/xml/grammar.rb, line 175 def ignore @context[:ignore] = true end
# File lib/mss/core/xml/grammar.rb, line 195 def index index_name, options = {} @context[:index] = options.merge(:name => index_name) end
# File lib/mss/core/xml/grammar.rb, line 149 def inflect value Inflection.ruby_name(value.to_s).to_sym end
# File lib/mss/core/xml/grammar.rb, line 265 def integer_value @context[:type] = :integer end
# File lib/mss/core/xml/grammar.rb, line 204 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/mss/core/xml/grammar.rb, line 221 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/mss/core/xml/grammar.rb, line 217 def map_entry key_element_name, value_element_name @context[:map] = [key_element_name, value_element_name] end
# File lib/mss/core/xml/grammar.rb, line 113 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/mss/core/xml/grammar.rb, line 288 def position *args; end
# File lib/mss/core/xml/grammar.rb, line 179 def rename new_name if @inflect_rename @context[:rename] = inflect(new_name) else @context[:rename] = new_name end end
# File lib/mss/core/xml/grammar.rb, line 260 def string_value @context[:type] = :string end
# File lib/mss/core/xml/grammar.rb, line 276 def symbol_value @context[:type] = :symbol end
# File lib/mss/core/xml/grammar.rb, line 254 def time_value @context[:type] = :time end
# File lib/mss/core/xml/grammar.rb, line 138 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/mss/core/xml/grammar.rb, line 127 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 enum position ) unless allow_methods.include?(method.to_s) raise "#{method} cannot be used in configuration" end end
# File lib/mss/core/xml/grammar.rb, line 229 def wrapper method_name, options = {}, &block options[:for].each do |child| context_for_child(child)[:wrap] = method_name end end