Class: Occi::Core::Parsers::TextParser
- Inherits:
-
BaseParser
- Object
- BaseParser
- Occi::Core::Parsers::TextParser
- Defined in:
- lib/occi/core/parsers/text_parser.rb
Overview
Implementes components necessary to parse all required instance types from ‘text` or `text`-like format.
Constant Summary collapse
- URI_LIST_TYPES =
Media type constants
%w[text/uri-list].freeze
- HEADERS_TEXT_TYPES =
%w[text/occi].freeze
- PLAIN_TEXT_TYPES =
%w[text/plain text/occi+plain].freeze
- OCCI_TEXT_TYPES =
[HEADERS_TEXT_TYPES, PLAIN_TEXT_TYPES].flatten.freeze
- MEDIA_TYPES =
[URI_LIST_TYPES, OCCI_TEXT_TYPES].flatten.freeze
- KEY_NAME_GROUPS =
Constants for OCCI keys
%w[LOCATION_KEYS CATEGORY_KEYS LINK_KEYS ATTRIBUTE_KEYS].freeze
- LOCATION_KEYS =
%w[X-OCCI-Location X_occi_location X-occi-location Location].freeze
- CATEGORY_KEYS =
%w[Category X-OCCI-Category X_occi_category X-occi-category].freeze
- LINK_KEYS =
%w[Link X-OCCI-Link X_occi_link X-occi-link].freeze
- ATTRIBUTE_KEYS =
%w[X-OCCI-Attribute X_occi_attribute X-occi-attribute].freeze
- OCCI_KEYS =
[LOCATION_KEYS, CATEGORY_KEYS, LINK_KEYS, ATTRIBUTE_KEYS].flatten.freeze
- HEADER_HTTP_PREFIX =
Constants for header normalization
'HTTP_'.freeze
Instance Attribute Summary
Attributes inherited from BaseParser
Class Method Summary collapse
-
.canonize_header_value(value) ⇒ Object
Attempts to canonize value from headers by looking for hidden multi-value lines usually separated by commas.
-
.canonize_headers(headers) ⇒ Hash
Canonizes normalized headers by eliminating naming differences in keys.
-
.key_name_groups ⇒ Array
Returns a list of available key name groups accessible as constants by name on this class.
-
.locations(body, headers, media_type) ⇒ Array
Extracts URI-like locations from body and headers.
-
.model(body, headers, media_type, model) ⇒ Occi::Core::Model
Extracts categories from body and headers.
-
.normalize_headers(headers) ⇒ Hash
Normalizes raw headers into a more agreeable form.
-
.transform_body(body) ⇒ Array
Transforms a ‘String`-like body into a series of independent lines.
-
.transform_headers(headers) ⇒ Array
Transforms a widely varied content of headers into a unified body-like format for further processing.
-
.unify_headers(headers) ⇒ Array
Unifies canonized headers by transforming them into a body-like form.
-
.validate_header_keys!(headers_keys) ⇒ Object
Checks for use of multiple keys from a single key name groups.
Instance Method Summary collapse
-
#action_instances(body, headers) ⇒ Set
Parses action instances from the given body/headers.
-
#categories(body, headers, expectation = nil) ⇒ Set
Parses categories from the given body/headers and returns corresponding instances from the known model.
-
#entities(body, headers, expectation = nil) ⇒ Set
Parses entities from the given body/headers.
Methods inherited from BaseParser
#actions, #initialize, #kinds, #links, #lookup, media_types, #mixins, #parses?, parses?, #resources
Methods included from Helpers::ErrorHandler
Constructor Details
This class inherits a constructor from Occi::Core::Parsers::BaseParser
Class Method Details
.canonize_header_value(value) ⇒ Object
Attempts to canonize value from headers by looking for hidden multi-value lines usually separated by commas.
218 219 220 221 222 |
# File 'lib/occi/core/parsers/text_parser.rb', line 218 def canonize_header_value(value) value = value.first if value.is_a?(Array) && value.count == 1 # ary with 1 could be hidden multi-val value = value.split(',').map(&:strip) if value.is_a?(String) # multi-vals can hide as ','-separated String value end |
.canonize_headers(headers) ⇒ Hash
Canonizes normalized headers by eliminating naming differences in keys. Input for this method must be already normalized by ‘normalize_headers`.
200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/occi/core/parsers/text_parser.rb', line 200 def canonize_headers(headers) validate_header_keys! headers.keys canonical = {} headers.each_pair do |key, value| pref = key_name_groups.detect { |ka| ka.include?(key) } canonical[pref.first] = [canonize_header_value(value)].flatten end logger.debug { "Canonized headers #{canonical.inspect}" } canonical end |
.key_name_groups ⇒ Array
Returns a list of available key name groups accessible as constants by name on this class.
254 255 256 |
# File 'lib/occi/core/parsers/text_parser.rb', line 254 def key_name_groups KEY_NAME_GROUPS.map { |kn| const_get kn } end |
.locations(body, headers, media_type) ⇒ Array
Extracts URI-like locations from body and headers. For details, see ‘Occi::Core::Parsers::Text::Location`.
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/occi/core/parsers/text_parser.rb', line 139 def locations(body, headers, media_type) logger.debug { "Parsing locations from #{media_type.inspect} in #{body.inspect} and #{headers.inspect}" } if URI_LIST_TYPES.include? media_type Text::Location.uri_list transform_body(body) elsif HEADERS_TEXT_TYPES.include? media_type Text::Location.plain transform_headers(headers) else Text::Location.plain transform_body(body) end end |
.model(body, headers, media_type, model) ⇒ Occi::Core::Model
Extracts categories from body and headers. For details, see ‘Occi::Core::Parsers::Text::Category`.
121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/occi/core/parsers/text_parser.rb', line 121 def model(body, headers, media_type, model) logger.debug { "Parsing model from #{media_type.inspect} in #{body.inspect} and #{headers.inspect}" } if HEADERS_TEXT_TYPES.include? media_type Text::Category.plain transform_headers(headers), model elsif PLAIN_TEXT_TYPES.include? media_type Text::Category.plain transform_body(body), model else raise Occi::Core::Errors::ParsingError, "Model cannot be parsed from #{media_type.inspect}" end end |
.normalize_headers(headers) ⇒ Hash
Normalizes raw headers into a more agreeable form. This process will remove known prefixes as well as blank lines or non-OCCI keys.
182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/occi/core/parsers/text_parser.rb', line 182 def normalize_headers(headers) return {} unless headers headers = Hash[ headers.map { |k, v| [k.gsub(HEADER_HTTP_PREFIX, '').capitalize, v] } ] # remove 'HTTP_' prefix in keys headers.delete_if { |_k, v| v.blank? } # remove pairs with empty values headers.keep_if { |k, _v| OCCI_KEYS.include?(k) } # drop non-OCCI pairs logger.debug { "Normalized headers #{headers.inspect}" } headers end |
.transform_body(body) ⇒ Array
Transforms a ‘String`-like body into a series of independent lines. Note: Multi-line elements are not supported by this parser.
156 157 158 159 160 |
# File 'lib/occi/core/parsers/text_parser.rb', line 156 def transform_body(body) return [] if body.blank? lines = body.respond_to?(:lines) ? body.lines : body.split("\n") lines.map(&:strip) end |
.transform_headers(headers) ⇒ Array
Transforms a widely varied content of headers into a unified body-like format for further processing. This method and its helpers should hide differences between ‘text/occi` and `text/plain` completely.
168 169 170 171 172 173 174 175 |
# File 'lib/occi/core/parsers/text_parser.rb', line 168 def transform_headers(headers) logger.debug { "Transforming headers #{headers.inspect}" } unify_headers( canonize_headers( normalize_headers(headers) ) ) end |
.unify_headers(headers) ⇒ Array
Unifies canonized headers by transforming them into a body-like form. Output of this method should be directly parsable as ‘text/plain` found in body.
230 231 232 233 234 235 236 237 238 |
# File 'lib/occi/core/parsers/text_parser.rb', line 230 def unify_headers(headers) lines = [] headers.each_pair do |k, v| lines << v.map { |val| "#{k}: #{val}" } end logger.debug { "Unified headers #{lines.inspect}" } lines.flatten.sort end |
.validate_header_keys!(headers_keys) ⇒ Object
Checks for use of multiple keys from a single key name groups. See ‘key_name_groups` for a list of available groups. Mixed key notations will produce an error.
245 246 247 248 249 |
# File 'lib/occi/core/parsers/text_parser.rb', line 245 def validate_header_keys!(headers_keys) return unless key_name_groups.any? { |elm| (headers_keys & elm).count > 1 } raise Occi::Core::Errors::ParsingError, "Headers #{headers_keys.inspect} contain mixed key notations" end |
Instance Method Details
#action_instances(body, headers) ⇒ Set
Parses action instances from the given body/headers. Only actions already declared in the model are allowed.
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/occi/core/parsers/text_parser.rb', line 70 def action_instances(body, headers) logger.debug { "Parsing Occi::Core::ActionInstance from #{body.inspect} and #{headers.inspect}" } entity_parser = Text::Entity.new(model: model) tformed = transform(body, headers) action_instance = Occi::Core::ActionInstance.new( action: action_instance_category(entity_parser, tformed) ) entity_parser.plain_attributes! tformed, action_instance.attributes setify(action_instance) end |
#categories(body, headers, expectation = nil) ⇒ Set
Parses categories from the given body/headers and returns corresponding instances from the known model.
89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/occi/core/parsers/text_parser.rb', line 89 def categories(body, headers, expectation = nil) expectation ||= Occi::Core::Category logger.debug { "Parsing #{expectation} from #{body.inspect} and #{headers.inspect}" } cats = transform(body, headers).map do |line| cat = Text::Category.plain_category(line, false) lookup "#{cat[:scheme]}#{cat[:term]}", expectation end setify(cats) end |
#entities(body, headers, expectation = nil) ⇒ Set
Parses entities from the given body/headers. Only kinds, mixins, and actions already declared in the model are allowed.
51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/occi/core/parsers/text_parser.rb', line 51 def entities(body, headers, expectation = nil) expectation ||= Occi::Core::Entity logger.debug { "Parsing #{expectation} from #{body.inspect} and #{headers.inspect}" } entity_parser = Text::Entity.new(model: model) entity = entity_parser.plain transform(body, headers) unless entity.is_a?(expectation) raise Occi::Core::Errors::ParsingError, "Entity is not of type #{expectation}" end setify(entity) end |