Class: Occi::Core::Parsers::Text::Entity
- Inherits:
-
Object
- Object
- Occi::Core::Parsers::Text::Entity
- Includes:
- Helpers::ArgumentValidator, Helpers::ErrorHandler, Yell::Loggable
- Defined in:
- lib/occi/core/parsers/text/entity.rb
Overview
Static parsing class responsible for extracting entities from plain text. Class supports ‘text/plain’ via ‘plain`. No other formats are supported.
Constant Summary collapse
- ATTRIBUTE_REGEXP =
Regexp constants
/#{Constants::REGEXP_ATTRIBUTE}/
- LINK_REGEXP =
/#{Constants::REGEXP_LINK}/
- DEFAULT_LAMBDA =
Typecasting lambdas
->(val) { raise "#{self} -> Cannot typecast #{val.inspect} to an unknown type" }
- FLOAT_LAMBDA =
->(val) { Float(val) rescue raise(Occi::Core::Errors::ParsingError, "Wrong value #{val}") }
- JSON_LAMBDA =
->(val) { JSON.parse(val.gsub('\"', '"'), symbolize_names: true) }
- TYPECASTER_HASH =
{ IPAddr => ->(val) { IPAddr.new val }, URI => ->(val) { URI.parse val }, String => ->(val) { val }, Float => FLOAT_LAMBDA, Numeric => FLOAT_LAMBDA, Integer => ->(val) { Integer(val) rescue raise(Occi::Core::Errors::ParsingError, "Wrong value #{val}") }, Boolean => ->(val) { val.casecmp('true') || val.casecmp('yes') }, Array => JSON_LAMBDA, Hash => JSON_LAMBDA }.freeze
Instance Attribute Summary collapse
-
#model ⇒ Occi::Core::Model, Occi::Infrastructure::Model
model to use as a primary reference point.
Class Method Summary collapse
-
.typecaster ⇒ Hash
Constructs a map pointing from expected attribute types to conversion lambdas.
Instance Method Summary collapse
-
#initialize(args = {}) ⇒ Entity
constructor
Constructs an instance of the entity parser.
-
#plain(lines) ⇒ Occi::Core::Entity
Builds an entity instances from the lines provided as input.
-
#plain_action!(md, entity) ⇒ Object
Looks up the action mentioned in the given action “link” and assigns it to the given partially constructed entity instance.
-
#plain_attributes!(lines, attributes) ⇒ Hash
Parses attributes from entity lines.
-
#plain_categories(lines) ⇒ Array
Parses categories from entity lines.
-
#plain_link!(md, entity) ⇒ Object
Constructs a single link instance.
-
#plain_links!(lines, entity) ⇒ Occi::Core::Entity
Parses links attached to the entity instance.
-
#plain_oglink!(md, entity) ⇒ Object
Constructs a single link instance.
-
#plain_oglink_attributes!(md, link) ⇒ Object
Attaches attributes to an existing link instance.
-
#plain_oglink_instance(md) ⇒ Occi::Core::Link
Constructs a single link instance based on the provided data.
-
#raw_attribute(line) ⇒ Array
Parses a single attribute line to identify name and value.
-
#typecast(value, type) ⇒ Object
Typecasts attribute values from String to the desired type.
Methods included from Helpers::ErrorHandler
Constructor Details
#initialize(args = {}) ⇒ Entity
Constructs an instance of the entity parser. Only entities (their kinds) defined by the model are allowed.
44 45 46 47 48 49 50 51 |
# File 'lib/occi/core/parsers/text/entity.rb', line 44 def initialize(args = {}) pre_initialize(args) default_args! args @model = args.fetch(:model) post_initialize(args) end |
Instance Attribute Details
#model ⇒ Occi::Core::Model, Occi::Infrastructure::Model
model to use as a primary reference point
11 12 13 |
# File 'lib/occi/core/parsers/text/entity.rb', line 11 def model @model end |
Class Method Details
.typecaster ⇒ Hash
Constructs a map pointing from expected attribute types to conversion lambdas.
241 242 243 |
# File 'lib/occi/core/parsers/text/entity.rb', line 241 def typecaster Hash.new(DEFAULT_LAMBDA).merge(TYPECASTER_HASH) end |
Instance Method Details
#plain(lines) ⇒ Occi::Core::Entity
Builds an entity instances from the lines provided as input.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/occi/core/parsers/text/entity.rb', line 57 def plain(lines) cats = plain_categories(lines) kind = cats.detect { |c| c.is_a?(Occi::Core::Kind) } raise Occi::Core::Errors::ParsingError, 'Entity does not specify its kind' unless kind logger.debug { "Identified entity kind #{kind.inspect}" } entity = @_ib.build(kind.identifier) cats.each { |cat| cat.is_a?(Occi::Core::Mixin) && entity << cat } plain_attributes! lines, entity.attributes plain_links! lines, entity logger.debug { "Created instance #{entity.inspect}" } entity end |
#plain_action!(md, entity) ⇒ Object
Looks up the action mentioned in the given action “link” and assigns it to the given partially constructed entity instance.
158 159 160 |
# File 'lib/occi/core/parsers/text/entity.rb', line 158 def plain_action!(md, entity) entity << handle(Occi::Core::Errors::ParsingError) { model.find_by_identifier!(md[:rel]) } end |
#plain_attributes!(lines, attributes) ⇒ Hash
Parses attributes from entity lines. Every attribute value is typed according to the attribute specification provided by the model (in the defined kind).
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/occi/core/parsers/text/entity.rb', line 92 def plain_attributes!(lines, attributes) lines.each do |line| next unless line.start_with?(TextParser::ATTRIBUTE_KEYS.first) name, value = raw_attribute(line) unless attributes[name] raise Occi::Core::Errors::ParsingError, "Attribute #{name.inspect} is not allowed for this entity" end attributes[name].value = handle(Occi::Core::Errors::ParsingError) do typecast value, attributes[name].attribute_definition.type end end attributes end |
#plain_categories(lines) ⇒ Array
Parses categories from entity lines. Every category is looked up in the model.
77 78 79 80 81 82 83 84 |
# File 'lib/occi/core/parsers/text/entity.rb', line 77 def plain_categories(lines) categories = lines.map do |line| next unless line.start_with?(TextParser::CATEGORY_KEYS.first) cat = Category.plain_category(line, false) handle(Occi::Core::Errors::ParsingError) { model.find_by_identifier!("#{cat[:scheme]}#{cat[:term]}") } end categories.compact end |
#plain_link!(md, entity) ⇒ Object
Constructs a single link instance. This includes both action “links” and ordinary OCCI links.
149 150 151 |
# File 'lib/occi/core/parsers/text/entity.rb', line 149 def plain_link!(md, entity) md[:uri].include?('?action=') ? plain_action!(md, entity) : plain_oglink!(md, entity) end |
#plain_links!(lines, entity) ⇒ Occi::Core::Entity
Parses links attached to the entity instance. This includes both action “links” and ordinary OCCI links between resources.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/occi/core/parsers/text/entity.rb', line 129 def plain_links!(lines, entity) lines.each do |line| next unless line.start_with?(TextParser::LINK_KEYS.first) logger.debug { "Parsing link line #{line.inspect}" } matched = line.match(LINK_REGEXP) unless matched raise Occi::Core::Errors::ParsingError, "#{line.inspect} does not match expectations for Link" end plain_link! matched, entity end entity end |
#plain_oglink!(md, entity) ⇒ Object
Constructs a single link instance. Supports only ordinary OCCI links between resources.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/occi/core/parsers/text/entity.rb', line 166 def plain_oglink!(md, entity) unless entity.respond_to?(:links) raise Occi::Core::Errors::ParsingError, "Cannot assign links to entity #{entity.id} which does not support them" end link = plain_oglink_instance(md) link.location = handle(Occi::Core::Errors::ParsingError) { URI.parse md[:self] } entity.add_link link plain_oglink_attributes! md, link entity end |
#plain_oglink_attributes!(md, link) ⇒ Object
Attaches attributes to an existing link instance.
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/occi/core/parsers/text/entity.rb', line 207 def plain_oglink_attributes!(md, link) if md[:attributes].blank? raise Occi::Core::Errors::ParsingError, "Link #{link.id} is missing attribute information" end logger.debug { "Parsing inline link attributes from line #{md[:attributes].inspect}" } regexp = Regexp.new "(\\s*#{Constants::REGEXP_ATTRIBUTE_REPR})" line = md[:attributes].strip.gsub(/^;\s*/, '') plain_attributes!( line.scan(regexp).map { |attrb| "#{TextParser::ATTRIBUTE_KEYS.first}: #{attrb.first}" }, link.attributes ) link end |
#plain_oglink_instance(md) ⇒ Occi::Core::Link
Constructs a single link instance based on the provided data. The returned instance does include action instance attributes!
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/occi/core/parsers/text/entity.rb', line 186 def plain_oglink_instance(md) if md[:category].blank? || md[:self].blank? raise Occi::Core::Errors::ParsingError, "Link #{md[:uri].inspect} missing type and location information" end categories = md[:category].split target_kind = handle(Occi::Core::Errors::ParsingError) { model.find_by_identifier!(md[:rel]) } link = @_ib.build(categories.shift, target_kind: target_kind) categories.each do |mxn| logger.debug { "Adding mixin #{mxn.inspect} to link instance" } link << handle(Occi::Core::Errors::ParsingError) { model.find_by_identifier!(mxn) } end logger.debug { "Created link instance #{link.inspect} from #{md.inspect}" } link end |
#raw_attribute(line) ⇒ Array
Parses a single attribute line to identify name and value.
114 115 116 117 118 119 120 121 |
# File 'lib/occi/core/parsers/text/entity.rb', line 114 def raw_attribute(line) logger.debug { "Parsing attribute line #{line.inspect}" } matched = line.match(ATTRIBUTE_REGEXP) unless matched raise Occi::Core::Errors::ParsingError, "#{line.inspect} does not match expectations for Attribute" end [matched[:name], matched[:string] || matched[:number] || matched[:bool]] end |
#typecast(value, type) ⇒ Object
Typecasts attribute values from String to the desired type.
228 229 230 231 232 233 234 235 |
# File 'lib/occi/core/parsers/text/entity.rb', line 228 def typecast(value, type) if value.nil? || type.nil? raise Occi::Core::Errors::ParsingError, 'Cannot typecast (un)set value to (un)set type' end logger.debug { "Typecasting value #{value.inspect} to #{type}" } self.class.typecaster[type].call(value) end |