47colborne/cloud-sesame

View on GitHub
lib/cloud_sesame/query/ast/range_value.rb

Summary

Maintainability
A
45 mins
Test Coverage
module CloudSesame
  module Query
    module AST
      class RangeValue < Abstract::Value

        STRING_NUMBER = Regexp.new(/^\d+(.\d+?)$/)

        def initialize(value = nil, type = nil)
          self.value =  RangeValue.range?(value) ? build_from_range(value) :
                        RangeValue.string_range?(value) ? build_from_string(value) :
                        initialize_value
          self.parse type
        end

        def parse(type)
          if type && type.respond_to?(:parse)
            @changed = true
            value[1] = type.parse(self.begin) unless self.begin.to_s.empty?
            value[2] = type.parse(self.end) unless self.end.to_s.empty?
          end
          return self
        end

        def begin
          value[1]
        end

        def end
          value[2]
        end

        def lower_bound
          value[0]
        end

        def upper_bound
          value[3]
        end

        def gt(value)
          set_begin(value) if value
          return self
        end

        def gte(value)
          set_begin(value, '[') if value
          return self
        end

        def lt(value)
          set_end(value) if value
          return self
        end

        def lte(value)
          set_end(value, ']') if value
          return self
        end

        def to_s
          compile
        end

        def ==(object)
          value == (object.is_a?(RangeValue) ? object : RangeValue.new(object, Value)).value
        end

        private

        def recompile(value)
          super "#{ value[0] }#{ value[1] },#{ value[2] }#{ value[3] }"
        end

        def set_begin(value, included = '{')
          @changed = true
          self.value[0, 2] = [included, value]
        end

        def set_end(value, included = '}')
          @changed = true
          self.value[2, 2] = [value, included]
        end

        def build_from_range(range)
          initialize_value('[', range.begin, range.end, range.exclude_end? ? '}' : ']')
        end

        def build_from_string(string)
          matches = RANGE_FORMAT.match(string.strip).captures
          matches[1,2] = matches[1,2].map { |i| i unless i.empty? }
          initialize_value(*matches)
        end

        def initialize_value(lb = '{', bv = nil, ev = nil, up = '}')
          [lb, bv, ev, up]
        end

      end
    end
  end
end