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
DELEGATED =

Shortcuts to interesting methods on logger

%i[debug? info? warn? error? fatal?].freeze

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


161
162
163
164
165
166
167
168
169
170
171
172
# 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

.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


177
178
179
180
# 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) ⇒ 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


185
186
187
188
# 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

.matchdata_to_hash(md) ⇒ Hash

Returns converted hash.

Parameters:

  • md (MatchData)

    `MatchData` instance to be converted

Returns:

  • (Hash)

    converted hash


192
193
194
195
196
# 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) ⇒ 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:


35
36
37
38
39
40
41
42
43
44
45
46
# 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) ⇒ 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


112
113
114
115
116
117
118
119
120
121
122
123
124
# 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) ⇒ 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:


134
135
136
137
138
139
140
141
142
# 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) ⇒ 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


93
94
95
96
97
98
99
100
101
102
# 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) ⇒ 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


54
55
56
57
58
59
60
61
62
63
# 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) ⇒ Hash

Finishes parsing of attributes, actions, and referenced categories.

Parameters:

  • cat (Hash)

    partially parsed hash

Returns:

  • (Hash)

    fully parsed hash


78
79
80
81
82
83
# 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) ⇒ 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


69
70
71
72
# File 'lib/occi/core/parsers/text/category.rb', line 69

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


152
153
154
# File 'lib/occi/core/parsers/text/category.rb', line 152

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