Class: Occi::Core::RendererFactory

Inherits:
Object
  • Object
show all
Includes:
Helpers::ArgumentValidator, Singleton, Yell::Loggable
Defined in:
lib/occi/core/renderer_factory.rb

Overview

A singleton factory class offering convenient access to all available renderer classes. Factory can be customized using the ‘required_methods` and `namespace` attributes.

Author:

Constant Summary collapse

REQUIRED_METHODS =

Methods expected on supported renderer classes

%i[renderer? formats render].freeze
NAMESPACE =

Parent namespace of all supported renderer classes

Occi::Core::Renderers

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ RendererFactory

Constructs an instance of the ‘RendererFactory` class. Since this class is a singleton, `new` (or `initialize`) are not supposed to be called directly. Use attribute accessors to change settings on existing factories.

Parameters:

  • args (Hash) (defaults to: {})

    hash with factory settings

Options Hash (args):

  • :required_methods (Array) — default: `REQUIRED_METHODS`

    list of required renderer methods

  • :namespace (Module) — default: `NAMESPACE`

    module containing renderer candidates



31
32
33
34
35
36
37
38
39
# File 'lib/occi/core/renderer_factory.rb', line 31

def initialize(args = {})
  default_args! args

  logger.debug { "Initializing RendererFactory with #{args.inspect}" }
  @required_methods = args.fetch(:required_methods)
  @namespace = args.fetch(:namespace)

  reload!
end

Instance Attribute Details

#namespaceModule

module containing renderer candidates

Returns:

  • (Module)

    the current value of namespace



11
12
13
# File 'lib/occi/core/renderer_factory.rb', line 11

def namespace
  @namespace
end

#required_methodsArray

list of required renderer methods

Returns:

  • (Array)

    the current value of required_methods



11
12
13
# File 'lib/occi/core/renderer_factory.rb', line 11

def required_methods
  @required_methods
end

Class Method Details

.classes_from(namespace) ⇒ Array

Returns all classes from the given namespace.

Parameters:

  • namespace (Module)

    base namespace

Returns:

  • (Array)

    list of classes



187
188
189
# File 'lib/occi/core/renderer_factory.rb', line 187

def classes_from(namespace)
  constants_from(namespace).select { |const| const.is_a? Class }
end

.constants_from(namespace) ⇒ Array

Returns all constants from the given namespace. The list may contain constants other than classes, from the given namespace and needs to be refined further.

Parameters:

  • namespace (Module)

    base namespace

Returns:

  • (Array)

    list of constants



174
175
176
177
178
179
180
181
# File 'lib/occi/core/renderer_factory.rb', line 174

def constants_from(namespace)
  unless namespace.is_a? Module
    raise Occi::Core::Errors::RendererError, "#{namespace.inspect} " \
          'is not a Module'
  end
  logger.debug { "RendererFactory looking for renderers in #{namespace}" }
  namespace.constants.collect { |const| namespace.const_get(const) }
end

.namespaceModule

Returns the default renderer namespace.

Returns:

  • (Module)

    base namespace



164
165
166
# File 'lib/occi/core/renderer_factory.rb', line 164

def namespace
  NAMESPACE
end

.required_methodsArray

Lists default methods required from any supported renderer.

Returns:

  • (Array)

    list of method symbols



157
158
159
# File 'lib/occi/core/renderer_factory.rb', line 157

def required_methods
  REQUIRED_METHODS
end

Instance Method Details

#formatsArray

Lists available rendering ‘format`s.

Examples:

formats # => ['text', 'json', 'headers']

Returns:

  • (Array)

    list of formats, as Strings



53
54
55
# File 'lib/occi/core/renderer_factory.rb', line 53

def formats
  renderers.keys
end

#reload!Object



42
43
44
45
# File 'lib/occi/core/renderer_factory.rb', line 42

def reload!
  logger.debug { 'Clearing RendererFactory cache for renderer reload' }
  @ravail_cache = nil
end

#renderer?(candidate) ⇒ TrueClass, FalseClass

Checks whether the given object can act as a renderer.

Examples:

renderer? TextRenderer # => true
renderer? NilClass     # => false

Parameters:

  • candidate (Object, Class)

    object or class to check

Returns:



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/occi/core/renderer_factory.rb', line 111

def renderer?(candidate)
  begin
    renderer_with_methods! candidate
    renderer_with_formats! candidate
  rescue Occi::Core::Errors::RendererError => ex
    logger.debug { "Renderer validation failed with #{ex.message}" }
    return false
  end

  candidate.renderer?
end

#renderer_classesArray

Lists available renderers as an Array of renderer classes.

Examples:

renderer_classes #=> [Occi::Core::Renderers::TextRenderer]

Returns:

  • (Array)

    list of renderer classes



99
100
101
# File 'lib/occi/core/renderer_factory.rb', line 99

def renderer_classes
  self.class.classes_from(namespace).select { |cand| renderer? cand }
end

#renderer_for(format) ⇒ Class

Returns a renderer corresponding with the given ‘format`. If no such renderer exists, `Occi::Core::Errors::RenderingError` error is raised.

Examples:

renderer_for 'text'   # => Occi::Core::Renderers::TextRenderer
renderer_for 'tewat?' # => !Error: Occi::Core::Errors::RenderingError!

Parameters:

  • format (String)

    over-the-wire format

Returns:

  • (Class)

    factory renderer corresponding to ‘format`



85
86
87
88
89
90
91
# File 'lib/occi/core/renderer_factory.rb', line 85

def renderer_for(format)
  if format.blank?
    raise Occi::Core::Errors::RenderingError,
          'Cannot return a renderer for an unspecified format'
  end
  renderers[format] || raise(Occi::Core::Errors::RenderingError, "No renderer for #{format.inspect}")
end

#renderer_with_formats!(candidate) ⇒ Object

Ensures that the renderer candidate passed as an argument exposes supported formats. If that is not the case, an ‘Occi::Core::Errors::RendererError` error is raised.

Parameters:

  • candidate (Object, Class)

    object or class to check

Raises:



142
143
144
145
146
147
148
149
150
151
# File 'lib/occi/core/renderer_factory.rb', line 142

def renderer_with_formats!(candidate)
  unless candidate.respond_to?(:formats)
    raise Occi::Core::Errors::RendererError, "#{candidate.inspect} " \
          "does not respond to 'formats'"
  end

  return unless candidate.formats.blank?
  raise Occi::Core::Errors::RendererError, "#{candidate.inspect} " \
        'does not expose any supported formats'
end

#renderer_with_methods!(candidate) ⇒ Object

Ensures that the renderer candidate passed as an argument exposes all required methods. If that is not the case, an ‘Occi::Core::Errors::RendererError` error is raised.

Parameters:

  • candidate (Object, Class)

    object or class to check



128
129
130
131
132
133
134
135
# File 'lib/occi/core/renderer_factory.rb', line 128

def renderer_with_methods!(candidate)
  required_methods.each do |method|
    unless candidate.respond_to?(method)
      raise Occi::Core::Errors::RendererError, "#{candidate.inspect} " \
            "does not respond to #{method.inspect}"
    end
  end
end

#renderersHash

Lists available renderers as a Hash mapping ‘format` to `Renderer` class.

Examples:

renderers # => { 'text' => TextRenderer }

Returns:

  • (Hash)

    map of available renderers, keyed by ‘format`



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/occi/core/renderer_factory.rb', line 63

def renderers
  return @ravail_cache if @ravail_cache
  @ravail_cache = {}

  renderer_classes.each do |rndr_klass|
    logger.debug { "RendererFactory registering #{rndr_klass} for #{rndr_klass.formats}" }
    rndr_klass.formats.each { |rndr_klass_f| @ravail_cache[rndr_klass_f] = rndr_klass }
  end

  @ravail_cache
end