class Occi::Core::Parsers::Text::Category

Static parsing class responsible for extracting categories from plain text. Class supports 'text/plain' via `plain`. No other formats are supported.

@author Boris Parak <parak@cesnet.cz>

Constants

APPLIES_KEY
ATTRIBUTE_REGEXP
CATEGORY_REGEXP

Regexp constants

DELEGATED

Shortcuts to interesting methods on logger

DEPENDS_KEY
PARENT_KEY

Hash constants for ParserDereferencer

Public Class Methods

construct_instance(parsed) click to toggle source

Constructs an instance of `parsed` with given arguments. All classes must be located in the `Occi::Core` namespace.

@param parsed [Hash] arguments for instance construction @return [Object] constructed instance

# File lib/occi/core/parsers/text/category.rb, line 161
def construct_instance(parsed)
  all = {
    term: parsed[:term], schema: parsed[:scheme], title: parsed[:title],
    attributes: parsed[:attributes] ? parsed[:attributes] : {}
  }

  klass = parsed[:class].capitalize
  klass = Occi::Core.const_get(klass)
  all[:location] = parsed[:location] if klass.instance_methods.include?(:location)

  klass.new(all)
end
matchdata_to_hash(md) click to toggle source

@param md [MatchData] `MatchData` instance to be converted @return [Hash] converted hash

# File lib/occi/core/parsers/text/category.rb, line 192
def matchdata_to_hash(md)
  hash = {}
  md.names.each { |group| md[group] && hash[group.to_sym] = md[group] }
  hash
end
plain(lines, model) click to toggle source

Parses category lines into instances of subtypes of `Occi::Core::Category`. Internal references between objects are converted from strings to actual objects. Categories provided in the model will be reused but have to be declared in the parsed model as well. This mechanism can be used to introduce properly typed attribute definitions to 'plain/text'-based models.

@param lines [Array] list of single-category lines @param model [Occi::Core::Model] model with existing categories @return [Occi::Core::Model] model with all known category instances

# File lib/occi/core/parsers/text/category.rb, line 35
def plain(lines, model)
  raw_categories = []

  lines.each do |line|
    raw_categories << plain_category(line)
    model << construct_instance(raw_categories.last)
  end
  dereference_identifiers! model.categories, raw_categories

  logger.debug "Returning (updated) model #{model.inspect}" if logger_debug?
  model
end
plain_attribute(line) click to toggle source

Parses an attribute line into an attribute hash. The resulting hash has the attribute name pointing to the attribute definition.

@example

plain_attribute 'occi.core.id{required immutable}' # => {...}

@param line [String] single-attribute line from a category definition @return [Hash] hash with attribute name pointing to attribute definition

# File lib/occi/core/parsers/text/category.rb, line 112
def plain_attribute(line)
  # TODO: find a better approach to fixing split
  line.gsub!(/\{(immutable|required)_(required|immutable)\}/, '{\1 \2}')
  logger.debug "Parsing attribute line #{line.inspect}" if logger_debug?

  matched = line.match(ATTRIBUTE_REGEXP)
  unless matched && matched[1]
    raise Occi::Core::Errors::ParsingError,
          "#{line.inspect} does not match expectations for Attribute"
  end

  { matched[1] => plain_attribute_definition(matched[-2]) }
end
plain_attribute_definition(line) click to toggle source

Parses a line with attribute definitions into an `Occi::Core::AttributeDefinition` instance.

@example

plain_attribute_definition '{required immutable}'
   # => Occi::Core::AttributeDefinition

@param line [String] line with plain text attribute definition(s) @return [Occi::Core::AttributeDefinition] constructed instance

# File lib/occi/core/parsers/text/category.rb, line 134
def plain_attribute_definition(line)
  attr_def = Occi::Core::AttributeDefinition.new
  return attr_def if line.blank?

  attr_def.required! if line.include?('required')
  attr_def.immutable! if line.include?('immutable')

  attr_def
end
plain_attributes(line) click to toggle source

Parses a multi-attribute line into a multi-attribute hash. The resulting hash has attribute names pointing to attribute definitions.

@example

plain_attributes 'occi.core.id{required immutable} occi.storage.size' # => {...}

@param line [String] multi-attribute line from a category definition @return [Hash] hash with attribute names pointing to attribute definitions

# File lib/occi/core/parsers/text/category.rb, line 93
def plain_attributes(line)
  # TODO: find a better approach to fixing split
  line.gsub!(/\{(immutable|required)\s+(required|immutable)\}/, '{\1_\2}')

  attributes = {}
  line.split.each { |attribute| attributes.merge! plain_attribute(attribute) }
  logger.debug "Matched attributes as #{attributes.inspect}" if logger_debug?

  attributes
end
plain_category(line, full = true) click to toggle source

Parses a single-category line into a raw category hash containing all the necessary information for creating an instance.

@param line [String] single-category line containing the definition @param full [TrueClass, FalseClass] parse full definition, defaults to `true` @return [Hash] raw category hash for further processing

# File lib/occi/core/parsers/text/category.rb, line 54
def plain_category(line, full = true)
  logger.debug "Parsing line #{line.inspect}" if logger_debug?
  matched = line.match(CATEGORY_REGEXP)
  unless matched
    raise Occi::Core::Errors::ParsingError, "#{line.inspect} does not match expectations for Category"
  end

  cat = matchdata_to_hash(matched)
  full ? plain_category_extended(cat) : plain_category_partial(cat)
end
plain_category_extended(cat) click to toggle source

Finishes parsing of attributes, actions, and referenced categories.

@param cat [Hash] partially parsed hash @return [Hash] fully parsed hash

# File lib/occi/core/parsers/text/category.rb, line 78
def plain_category_extended(cat)
  cat[:attributes] = plain_attributes(cat[:attributes]) if cat[:attributes]
  cat[:rel] = plain_identifiers(cat[:rel]) if cat[:rel]
  cat[:actions] = plain_identifiers(cat[:actions]) if cat[:actions]
  cat
end
plain_category_partial(cat) click to toggle source

Cleans up partially parsed hash. Removes all potentially inconsitent or unfinished data structures.

@param cat [Hash] partially parsed hash @return [Hash] clean partially parsed hash

# File lib/occi/core/parsers/text/category.rb, line 69
def plain_category_partial(cat)
  %[attributes rel actions].each { |el| cat[el] = nil }
  cat
end
plain_identifiers(line) click to toggle source

Separates category identifiers from a single-line notation to an array.

@example

plain_identifiers 'http://l/b/c#a http://a/a/b#r' # => [...]

@param line [String] line with space-separated category identifiers @return [Array] list of separated category identifiers

# File lib/occi/core/parsers/text/category.rb, line 152
def plain_identifiers(line)
  line.split.map(&:strip)
end

Private Class Methods

lookup_applies_references!(mixin, derefd, parsed_rel) click to toggle source

@param mixin [Occi::Core::Mixin] mixin instance needing applicability dereferencing @param derefd [Array] list of all available category instances @param parsed_rel [Array] textual representations of needed applicability targets

# File lib/occi/core/parsers/text/category.rb, line 177
def lookup_applies_references!(mixin, derefd, parsed_rel)
  return if parsed_rel.blank? || parsed_rel.count == 1 # only depends here
  parsed_rel.drop(1).each { |kind| mixin.applies << first_or_die(derefd, kind) }
end
lookup_depends_references!(mixin, derefd, parsed_rel) click to toggle source

@param mixin [Occi::Core::Mixin] mixin instance needing dependency dereferencing @param derefd [Array] list of all available category instances @param parsed_rel [Array] textual representations of needed dependencies

# File lib/occi/core/parsers/text/category.rb, line 185
def lookup_depends_references!(mixin, derefd, parsed_rel)
  return if parsed_rel.blank?
  mixin.depends << first_or_die(derefd, parsed_rel.first)
end