Class: Occi::Core::Parsers::Text::Category

Inherits:
Object
  • Object
show all
Extended by:
Helpers::ParserDereferencer
Includes:
Yell::Loggable
Defined in:
lib/occi/core/parsers/text/category.rb

Overview

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

Author:

Constant Summary collapse

CATEGORY_REGEXP =

Regexp constants

/#{Constants::REGEXP_CATEGORY}/
ATTRIBUTE_REGEXP =
/^#{Constants::REGEXP_ATTRIBUTE_DEF}$/
PARENT_KEY =

Hash constants for ParserDereferencer

:rel
APPLIES_KEY =
:rel
DEPENDS_KEY =
:rel

Class Method Summary collapse

Methods included from Helpers::ParserDereferencer

dereference_identifiers!, first_or_die, lookup_action_references!, lookup_applies_references!, lookup_depends_references!, lookup_parent_references!, lookup_references!

Class Method Details

.construct_instance(parsed) ⇒ Object

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

Parameters:

  • parsed (Hash)

    arguments for instance construction

Returns:

  • (Object)

    constructed instance



157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/occi/core/parsers/text/category.rb', line 157

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

.lookup_applies_references!(mixin, derefd, parsed_rel) ⇒ Object

Parameters:

  • mixin (Occi::Core::Mixin)

    mixin instance needing applicability dereferencing

  • derefd (Array)

    list of all available category instances

  • parsed_rel (Array)

    textual representations of needed applicability targets



173
174
175
176
# File 'lib/occi/core/parsers/text/category.rb', line 173

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) ⇒ Object

Parameters:

  • mixin (Occi::Core::Mixin)

    mixin instance needing dependency dereferencing

  • derefd (Array)

    list of all available category instances

  • parsed_rel (Array)

    textual representations of needed dependencies



181
182
183
184
# File 'lib/occi/core/parsers/text/category.rb', line 181

def lookup_depends_references!(mixin, derefd, parsed_rel)
  return if parsed_rel.blank?
  mixin.depends << first_or_die(derefd, parsed_rel.first)
end

.matchdata_to_hash(md) ⇒ Hash

Returns converted hash.

Parameters:

  • md (MatchData)

    ‘MatchData` instance to be converted

Returns:

  • (Hash)

    converted hash



188
189
190
191
192
# File 'lib/occi/core/parsers/text/category.rb', line 188

def matchdata_to_hash(md)
  hash = {}
  md.names.each { |group| md[group] && hash[group.to_sym] = md[group] }
  hash
end

.plain(lines, model) ⇒ Occi::Core::Model

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.

Parameters:

  • lines (Array)

    list of single-category lines

  • model (Occi::Core::Model)

    model with existing categories

Returns:



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/occi/core/parsers/text/category.rb', line 31

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}" }
  model
end

.plain_attribute(line) ⇒ Hash

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

Examples:

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

Parameters:

  • line (String)

    single-attribute line from a category definition

Returns:

  • (Hash)

    hash with attribute name pointing to attribute definition



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/occi/core/parsers/text/category.rb', line 108

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}" }

  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) ⇒ Occi::Core::AttributeDefinition

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

Examples:

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

Parameters:

  • line (String)

    line with plain text attribute definition(s)

Returns:



130
131
132
133
134
135
136
137
138
# File 'lib/occi/core/parsers/text/category.rb', line 130

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) ⇒ Hash

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

Examples:

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

Parameters:

  • line (String)

    multi-attribute line from a category definition

Returns:

  • (Hash)

    hash with attribute names pointing to attribute definitions



89
90
91
92
93
94
95
96
97
98
# File 'lib/occi/core/parsers/text/category.rb', line 89

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}" }

  attributes
end

.plain_category(line, full = true) ⇒ Hash

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

Parameters:

  • line (String)

    single-category line containing the definition

  • full (TrueClass, FalseClass) (defaults to: true)

    parse full definition, defaults to ‘true`

Returns:

  • (Hash)

    raw category hash for further processing



50
51
52
53
54
55
56
57
58
59
# File 'lib/occi/core/parsers/text/category.rb', line 50

def plain_category(line, full = true)
  logger.debug { "Parsing line #{line.inspect}" }
  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) ⇒ Hash

Finishes parsing of attributes, actions, and referenced categories.

Parameters:

  • cat (Hash)

    partially parsed hash

Returns:

  • (Hash)

    fully parsed hash



74
75
76
77
78
79
# File 'lib/occi/core/parsers/text/category.rb', line 74

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) ⇒ Hash

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

Parameters:

  • cat (Hash)

    partially parsed hash

Returns:

  • (Hash)

    clean partially parsed hash



65
66
67
68
# File 'lib/occi/core/parsers/text/category.rb', line 65

def plain_category_partial(cat)
  %i[attributes rel actions].each { |el| cat[el] = nil }
  cat
end

.plain_identifiers(line) ⇒ Array

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

Examples:

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

Parameters:

  • line (String)

    line with space-separated category identifiers

Returns:

  • (Array)

    list of separated category identifiers



148
149
150
# File 'lib/occi/core/parsers/text/category.rb', line 148

def plain_identifiers(line)
  line.split.map(&:strip)
end