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

rules[R]

@return [Hash] Returns a hash of rules defined by this grammar.

Public Class Methods

customize(customizations = nil, rules = {}) click to toggle source
# 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
new(rules = {}) click to toggle source
# 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
parse(xml) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 82
def self.parse xml
  self.new.parse(xml)
end

Protected Class Methods

deep_copy(rules) click to toggle source

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

==(other)
Alias for: eql?
customize(customizations = nil, &block) click to toggle source

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
customize!(customizations = nil, &block) click to toggle source

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
parse(xml) click to toggle source

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

apply_customizations(customizations) click to toggle source
# 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
blob()
Alias for: blob_value
blob_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 244
def blob_value
  @context[:type] = :blob
end
Also aliased as: blob
boolean()
Alias for: boolean_value
boolean_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 239
def boolean_value
  @context[:type] = :boolean
end
Also aliased as: boolean
collect_values() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 191
def collect_values
  @context[:list] = true
end
construct_value(&block) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 235
def construct_value &block
  raise 'remove the need for this'
end
context_for_child(child_element_name) click to toggle source
# 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
datetime()
Alias for: datetime_value
datetime_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 249
def datetime_value
  @context[:type] = :datetime
end
Also aliased as: datetime
default_value(name, value) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 199
def default_value name, value
  @context[:defaults] ||= {}
  @context[:defaults][name] = value
end
element(element_name) { |parent_element_name| ... } click to toggle source

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
enum(*args;) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 287
def enum *args; end
eql?(other) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 281
def eql? other
  other.is_a?(Grammar) and self.rules == other.rules
end
Also aliased as: ==
float()
Alias for: float_value
float_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 271
def float_value
  @context[:type] = :float
end
Also aliased as: float
force() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 187
def force
  @context[:force] = true
end
http_header(*args;)
Alias for: http_trait
http_payload(*args;)
Alias for: http_trait
http_status(*args;)
Alias for: http_trait
http_trait(*args;) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 289
def http_trait *args; end
http_uri_label(*args;)
Alias for: http_trait
ignore() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 175
def ignore
  @context[:ignore] = true
end
index(index_name, options = {}) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 195
def index index_name, options = {}
  @context[:index] = options.merge(:name => index_name)
end
inflect(value) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 149
def inflect value
  Inflection.ruby_name(value.to_s).to_sym
end
integer()
Alias for: integer_value
integer_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 265
def integer_value
  @context[:type] = :integer
end
Also aliased as: integer, long
list(child_element_name = nil) { || ... } click to toggle source
# 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
long()
Alias for: integer_value
map(map_element_name, key_element_name, value_element_name) click to toggle source
# 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
map_entry(key_element_name, value_element_name) click to toggle source
# 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
parse_customization_item(item) click to toggle source
# 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
position(*args;) click to toggle source
# File lib/mss/core/xml/grammar.rb, line 288
def position *args; end
rename(new_name) click to toggle source
# 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
string()
Alias for: string_value
string_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 260
def string_value
  @context[:type] = :string
end
Also aliased as: string
symbol()
Alias for: symbol_value
symbol_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 276
def symbol_value
  @context[:type] = :symbol
end
Also aliased as: symbol
time()
Alias for: time_value
time_value() click to toggle source
# File lib/mss/core/xml/grammar.rb, line 254
def time_value
  @context[:type] = :time
end
Also aliased as: timestamp, time
timestamp()
Alias for: time_value
validate_args(identifier, args) click to toggle source
# 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
validate_config_method(method) click to toggle source
# 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
wrapper(method_name, options = {}) click to toggle source
# 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