riboseinc/ruby-vobject

View on GitHub
lib/vobject/vcard/v3_0/propertyvalue.rb

Summary

Maintainability
C
1 day
Test Coverage
require "vobject"
require "vobject/propertyvalue"

module Vcard::V3_0
  module PropertyValue
    class Text < Vobject::PropertyValue
      class << self
        def escape(x)
          # temporarily escape \\ as \u007f, which is banned from text
          x.tr("\\", "\u007f").gsub(/\n/, "\\n").gsub(/,/, "\\,").gsub(/;/, "\\;").gsub(/\u007f/, "\\\\")
        end

        def listencode(x)
          ret = if x.is_a?(Array)
                  x.map { |m| Text.escape m }.join(",")
                elsif x.nil? || x.empty?
                  ""
                else
                  Text.escape x
                end
          ret
        end
      end

      def initialize(val)
        self.value = val
        self.type = "text"
      end

      def to_s
        Text.escape value
      end

      def to_hash
        value
      end
    end

    class ClassValue < Text
      def initialize(val)
        self.value = val
        self.type = "classvalue"
      end

      def to_hash
        value
      end
    end

    class Profilevalue < Text
      def initialize(val)
        self.value = val
        self.type = "profilevalue"
      end

      def to_hash
        value
      end
    end

    class Kindvalue < Text
      def initialize(val)
        self.value = val
        self.type = "kindvalue"
      end

      def to_hash
        value
      end
    end

    class Ianatoken < Text
      def initialize(val)
        self.value = val
        self.type = "ianatoken"
      end

      def to_hash
        value
      end
    end

    class Binary < Text
      def initialize(val)
        self.value = val
        self.type = "binary"
      end

      def to_hash
        value
      end
    end

    class Phonenumber < Text
      def initialize(val)
        self.value = val
        self.type = "phonenumber"
      end

      def to_hash
        value
      end
    end

    class Uri < Text
      def initialize(val)
        self.value = val
        self.type = "uri"
      end

      def to_hash
        value
      end

      def to_s
        value
      end
    end

    class Float < Vobject::PropertyValue
      include Comparable
      def <=>(another)
        value <=> another.value
      end

      def initialize(val)
        self.value = val
        self.type = "float"
      end

      def to_s
        value
      end

      def to_hash
        value
      end
    end

    class Integer < Vobject::PropertyValue
      include Comparable
      def <=>(another)
        value <=> another.value
      end

      def initialize(val)
        self.value = val
        self.type = "integer"
      end

      def to_s
        value.to_s
      end

      def to_hash
        value
      end
    end

    class Date < Vobject::PropertyValue
      include Comparable
      def <=>(another)
        value <=> another.value
      end

      def initialize(val)
        self.value = val
        self.type = "date"
      end

      def to_s
        sprintf("%04d-%02d-%02d", value[:year].to_i, value[:month].to_i, value[:day].to_i)
      end

      def to_hash
        value
      end
    end

    class DateTimeLocal < Vobject::PropertyValue
      include Comparable
      def <=>(another)
        value[:time] <=> another.value[:time]
      end

      def initialize(val)
        self.value = val.clone
        # val consists of :time && :zone values. If :zone is empty, floating local time (i.e. system local time) is assumed
        self.type = "datetimelocal"
        val[:sec] += (val[:secfrac].to_f / (10**val[:secfrac].length)) if !val[:secfrac].nil? && !val[:secfrac].empty?
        value[:time] = if val[:zone].nil? || val[:zone].empty?
                         ::Time.local(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
                       else
                         ::Time.utc(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
                       end
        value[:origtime] = value[:time]
        if val[:zone] && val[:zone] != "Z"
          offset = val[:zone][:hour].to_i * 3600 + val[:zone][:min].to_i * 60
          offset += val[:zone][:sec].to_i if val[:zone][:sec]
          offset = -offset if val[:sign] == "-"
          value[:time] += offset.to_i
        end
      end

      def to_s
        # ret = sprintf("%04d-%02d-%02dT%02d:%02d:%02d", value[:year], value[:month], value[:day], value[:hour], value[:min], value[:sec])
        ret = sprintf("%s-%s-%sT%s:%s:%s", value[:year], value[:month], value[:day], value[:hour], value[:min], value[:sec])
        ret = ret + ",#{value[:secfrac]}" if value[:secfrac]
        zone = "Z" if value[:zone] && value[:zone] == "Z"
        zone = "#{value[:zone][:sign]}#{value[:zone][:hour]}:#{value[:zone][:min]}" if value[:zone] && value[:zone].is_a?(Hash)
        ret = ret + zone
        ret
      end

      def to_hash
        ret = {
          year: value[:year],
          month: value[:month],
          day: value[:day],
          hour: value[:hour],
          min: value[:min],
          sec: value[:sec],
        }
        ret[:zone] = value[:zone] if value[:zone]
        ret
      end
    end

    class Time < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "time"
      end

      def to_s
        ret = "#{value[:hour]}:#{value[:min]}:#{value[:sec]}"
        ret = ret + ".#{value[:secfrac]}" if value[:secfrac]
        zone = ""
        zone = "Z" if value[:zone] && value[:zone] == "Z"
        zone = "#{value[:zone][:sign]}#{value[:zone][:hour]}:#{value[:zone][:min]}" if value[:zone] && value[:zone].is_a?(Hash)
        ret = ret + zone
        ret
      end

      def to_hash
        value
      end
    end

    class Utcoffset < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "utcoffset"
      end

      def to_s
        ret = "#{value[:sign]}#{value[:hour]}:#{value[:min]}"
        # ret += self.value[:sec] if self.value[:sec]
        ret
      end

      def to_hash
        value
      end
    end

    class Geovalue < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "geovalue"
      end

      def to_s
        ret = "#{value[:lat]};#{value[:long]}"
        ret
      end

      def to_hash
        value
      end
    end

    class Version < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "version"
      end

      def to_s
        value
      end

      def to_hash
        value
      end
    end

    class Org < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "org"
      end

      def to_s
        value.map { |m| Text.escape m }.join(";")
      end

      def to_hash
        value
      end
    end

    class Fivepartname < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "fivepartname"
      end

      def to_s
        ret = Text.listencode value[:surname]
        ret += ";#{Text.listencode value[:givenname]}" if !value[:givenname].empty? || !value[:middlename].empty? || !value[:honprefix].empty? || !value[:honsuffix].empty?
        ret += ";#{Text.listencode value[:middlename]}" if !value[:middlename].empty? || !value[:honprefix].empty?
        ret += ";#{Text.listencode value[:honprefix]}" if !value[:honprefix].empty? || !value[:honsuffix].empty?
        ret += ";#{Text.listencode value[:honsuffix]}" if !value[:honsuffix].empty?
        ret
      end

      def to_hash
        value
      end
    end

    class Address < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "address"
      end

      def to_s
        ret = Text.listencode value[:pobox]
        ret += ";#{Text.listencode value[:ext]}" if !value[:ext].empty? || !value[:street].empty? || !value[:locality].empty? || !value[:region].empty? || !value[:code].empty? || !value[:country].empty?
        ret += ";#{Text.listencode value[:street]}" if !value[:street].empty? || !value[:locality].empty? || !value[:region].empty? || !value[:code].empty? || !value[:country].empty?
        ret += ";#{Text.listencode value[:locality]}" if !value[:locality].empty? || !value[:region].empty? || !value[:code].empty? || !value[:country].empty?
        ret += ";#{Text.listencode value[:region]}" if !value[:region].empty? || !value[:code].empty? || !value[:country].empty?
        ret += ";#{Text.listencode value[:code]}" if !value[:code].empty? || !value[:country].empty?
        ret += ";#{Text.listencode value[:country]}" if !value[:country].empty?
        ret
      end

      def to_hash
        value
      end
    end

    class Textlist < Vobject::PropertyValue
      def initialize(val)
        self.value = val
        self.type = "textlist"
      end

      def to_s
        value.map { |m| Text.escape m }.join(",")
      end

      def to_hash
        value
      end
    end

    class Agent < Vobject::PropertyValue
      def initialize(val)
        val[:VCARD].delete(:VERSION)
        self.value = val
        self.type = "agent"
      end

      def to_hash
        ret = {}
        value.each do |k, v|
          ret[k] = {}
          v.each do |k1, v1|
            if v1.is_a?(Hash)
              ret[k][k1] = {}
              v1.each { |k2, v2| ret[k][k1][k2] = v2.to_hash }
            else
              ret[k][k1] = v1
            end
          end
        end
        ret
      end

      def to_s
        ret = Vobject::Component.new(:VCARD, value[:VCARD], []).to_s
        # spec says that colons must be expected, but none of the examples do
        ret.gsub(/\n/, "\\n").gsub(/,/, "\\,").gsub(/;/, "\\;")
        # ret.gsub(/\n/,"\\n").gsub(/:/,"\\:")
      end
    end
  end
end