File: occurrence_list.rb

package info (click to toggle)
mhc 1.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,452 kB
  • sloc: ruby: 12,700; lisp: 7,577; makefile: 70; sh: 68
file content (155 lines) | stat: -rw-r--r-- 4,455 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# -*- coding: utf-8 -*-
module RiCal
  class PropertyValue
    # OccurrenceList is used to represent the value of an RDATE or EXDATE property.
    #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
    #
    class OccurrenceList < Array
      attr_accessor :tzid #:nodoc:

      class Enumerator # :nodoc:

        attr_accessor :default_duration, :occurrence_list

        # TODO: the component parameter should always be the parent
        def initialize(occurrences, component) # :nodoc:
          self.occurrence_list = occurrences
          self.default_duration = component.default_duration
          @index = 0
        end
        
        def bounded?
          true
        end
        
        def empty?
          occurrence_list.empty?
        end

        def next_occurrence
          if @index < occurrence_list.length
            result = occurrence_list[@index].occurrence_period(default_duration)
            @index += 1
            result
          else
            nil
          end
        end
      end

      def initialize(timezone_finder, options={}) # :nodoc:
        super
        validate_elements
      end

      def self.convert(timezone_finder, *ruby_objects) # :nodoc:
        # ruby_objects = [ruby_objects] unless Array === ruby_objects
        source_elements = ruby_objects.inject([]) { |se, element|
          if String === element
            element.split(",").each {|str| se << str}
          else
            se << element
          end
          se
          }        
        new(timezone_finder, :source_elements => source_elements )
      end

      def values_to_elements(values) # :nodoc:
        values.map {|val| val.to_ri_cal_occurrence_list_value(self)}
      end
      
      def tzid_from_source_elements # :nodoc:
        if @source_elements && String === (first_source = @source_elements.first)
          probe = first_source.to_ri_cal_occurrence_list_value rescue nil
          unless probe
            return @source_elements.shift
          end
        end
        nil
      end
      
      def tzid_conflict(element_tzid) # :nodoc:
        element_tzid && tzid != element_tzid
      end
      
      def validate_elements # :nodoc:
        if @source_elements
          self.tzid = tzid_from_source_elements
           @elements = values_to_elements(@source_elements)
          @value = @elements.map {|prop| prop.value}
        else
          @elements = values_to_elements(@value)
          self.tzid = params['TZID']
        end
        # if the tzid wasn't set by the parameters
        self.tzid ||= @elements.map {|element| element.tzid}.find {|id| id}
        @elements.each do |element|
          raise InvalidPropertyValue.new("Mixed timezones are not allowed in an occurrence list") if tzid_conflict(element.tzid)
          element.tzid = tzid
        end
      end

      def has_local_timezone? # :nodoc:
        tzid && tzid != 'UTC'
      end

      def visible_params # :nodoc:
        result = params.dup

        case @elements.first
        when Date
          result = {"VALUE" => "DATE"}.merge(params)
        when DateTime
          result = {"VALUE" => "DATE-TIME"}.merge(params)
        when Period
          result = {"VALUE" => "PERIOD"}.merge(params)
        end

        if has_local_timezone?
          result['TZID'] = tzid
        else
          result.delete('TZID')
        end
        result
      end

      def value # :nodoc:
        @elements.map {|element| element.value}.join(",")
      end

      # Return an array of the occurrences within the list
      def ruby_value
        @elements.map {|prop| prop.ruby_value}
      end
    end

    attr_accessor :elements, :source_elements #:nodoc:
    private :elements, :elements=, :source_elements=, :source_elements

    def for_parent(parent) #:nodoc:
      if timezone_finder.nil?
        @timezone_finder = parent
        self
      elsif timezone_finder == parent
        self
      else
        OccurrenceList.new(parent, :value => value)
      end
    end

    # Return an enumerator which can produce the elements of the occurrence list
    def enumerator(component) # :nodoc:
      OccurrenceList::Enumerator.new(@elements, component)
    end

    def add_date_times_to(required_timezones) #:nodoc:
      if @elements
        @elements.each do | occurrence |
          occurrence.add_date_times_to(required_timezones)
        end
      end
    end

  end
end