EGI-FCTF/rOCCI-core

View on GitHub
lib/occi/core/attribute.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Occi
  module Core
    # Represents an attribute commonly used in instances based on
    # `Entity` or `ActionInstance`. In most cases, instances of this
    # class will carry the attribute `value` and the `attribute_definition`
    # used for validation purposes. Attributes without `value` will default
    # to the value specified by `attribute_definition.default`, if present.
    # Attributes without `attribute_definition` are considered invalid.
    #
    # @attr value [Object] value of this attribute instance
    # @attr attribute_definition [AttributeDefinition] definition of this attribute instance
    #
    # @author Boris Parak <parak@cesnet.cz>
    class Attribute < Struct.new(:value, :attribute_definition)
      include Yell::Loggable

      # Checks whether the `value` assigned to this instance
      # does not violate restrictions defined in `attribute_definition`.
      # Attributes without `attribute_definition` are considered
      # invalid. Attributes without `value` may be considered valid
      # depending on the content on `attribute_definition`.
      #
      # @return [TrueClass, FalseClass] validation result
      def valid?
        begin
          valid!
        rescue Occi::Core::Errors::AttributeValidationError, Occi::Core::Errors::AttributeDefinitionError => ex
          logger.warn "Attribute invalid: #{ex.message}"
          return false
        end

        true
      end

      # Checks whether the `value` assigned to this instance
      # does not violate restrictions defined in `attribute_definition`.
      # Attributes without `attribute_definition` are considered
      # invalid. Attributes without `value` may be considered valid
      # depending on the content on `attribute_definition`.
      # This method will raise an `Occi::Core::Errors::AttributeValidationError`
      # error on failure.
      #
      # @raise [Occi::Core::Errors::AttributeDefinitionError] if there are problems with the definition
      # @raise [Occi::Core::Errors::AttributeValidationError] if this instance is not valid
      def valid!
        unless definition?
          raise Occi::Core::Errors::AttributeValidationError,
                'Attribute is missing a definition'
        end
        unless attribute_definition.respond_to?(:valid!)
          raise Occi::Core::Errors::AttributeDefinitionError,
                'Attribute definition is not capable of validation'
        end

        attribute_definition.valid! value
      end

      # Checks whether this instance has `attribute_definition` assigned.
      #
      # @return [TrueClass, FalseClass] flag indicating the presence of `attribute_definition`
      def definition?
        !attribute_definition.nil?
      end
      alias attribute_definition? definition?

      # Checks whether this instance has `value` assigned. Attributes in which
      # `nil` is an acceptable value will still be considered valueless, although
      # the validation may pass, see `#valid?` or `#valid!`.
      #
      # @return [TrueClass, FalseClass] flag indicating the presence of `value`
      def value?
        !value.nil?
      end

      # Checks whether this instance has both `value` and `attribute_definition` assigned.
      # For details, see `#definition?` and `#value?`.
      #
      # @return [TrueClass, FalseClass] flag indicating the presence of `attribute_definition` and `value`
      def full?
        definition? && value?
      end

      # Checks whether this instance is missing both `value` and `attribute_definition`.
      #
      # @return [TrueClass, FalseClass] flag indicating emptiness
      def empty?
        !(definition? || value?)
      end

      # Gracefully sets `value` for this instance from the default value specified
      # in `attribute_definition`. Only `value` set to `nil` will be replaced, other
      # values will be kept. In case `nil` is the default value, it will be set
      # and reported as a new value. An attempt to change the value will be made only
      # if there is no current value (instance with a `value` but no `attribute_definition`
      # will pass this method without raising an error).
      #
      # @raise [Occi::Core::Errors::AttributeDefinitionError] if there is no `attribute_definition`
      # @return [Object] new value, if changed
      # @return [NilClass] if nothing changed
      def default
        value? ? nil : default!
      end

      # Sets `value` for this instance from the default value specified
      # in `attribute_definition`. This method will OVERWRITE any previous
      # `value` present in this instance. See `#default` for the graceful
      # version.
      #
      # @raise [Occi::Core::Errors::AttributeDefinitionError] if there is no `attribute_definition`
      # @return [Object] new value
      def default!
        unless definition?
          raise Occi::Core::Errors::AttributeDefinitionError,
                'There is no definition for this attribute'
        end
        self.value = attribute_definition.default
      end

      # Resets the value of this attribute instance to `nil`.
      #
      # @return [NilClass] always `nil`
      def reset!
        self.value = nil
      end

      # Reports whether attribute value is absent (`nil`) but the attribute is
      # optional and this fact can be safely ignored. Helps with rendering
      # decisions.
      #
      # @return [TrueClass, FalseClass] flag indicating "safe" valuelessness
      def optionally_valueless?
        !value? && definition? && attribute_definition.optional?
      end
    end
  end
end