Class: RiCal::OccurrenceEnumerator::EnumerationInstance

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ri_cal/occurrence_enumerator.rb

Overview

EnumerationInstance holds the values needed during the enumeration of occurrences for a component.

Instance Method Summary collapse

Constructor Details

#initialize(component) ⇒ EnumerationInstance

Returns a new instance of EnumerationInstance.



73
74
75
76
77
78
# File 'lib/ri_cal/occurrence_enumerator.rb', line 73

def initialize(component)
  @component = component
  @rrules = OccurrenceMerger.for(@component, [@component.rrule_property, @component.rdate_property].flatten.compact)
  @exrules = OccurrenceMerger.for(@component, [@component.exrule_property, @component.exdate_property].flatten.compact)
  @yielded = 0
end

Instance Method Details

#before_start?(occurrence) ⇒ Boolean

Also exclude occurrences before the :starting date_time

Returns:

  • (Boolean)


96
97
98
99
# File 'lib/ri_cal/occurrence_enumerator.rb', line 96

def before_start?(occurrence)
  (@start && occurrence.dtstart.to_datetime < @start) ||
  @overlap_range && occurrence.before_range?(@overlap_range)
end

#bounded?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/ri_cal/occurrence_enumerator.rb', line 150

def bounded?
  @rrules.bounded? || @count || @cutoff || @overlap_range
end

#each(options = nil) ⇒ Object

yield each occurrence to a block some components may be open-ended, e.g. have no COUNT or DTEND



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/ri_cal/occurrence_enumerator.rb', line 127

def each(options = nil)
  process_options(options) if options
  if @rrules.empty?
    unless before_start?(@component)
      yield @component unless options_stop(@component)
    end
  else
    occurrence = next_occurrence
    while (occurrence)
      candidate = @component.recurrence(occurrence)
      if options_stop(candidate)
        occurrence = nil
      else
        unless before_start?(candidate)
          @yielded += 1
          yield candidate
        end
        occurrence = next_occurrence
      end
    end
  end
end

#exclusion_for(occurrence) ⇒ Object

return the next exclusion which starts at the same time or after the start time of the occurrence return nil if this exhausts the exclusion rules



82
83
84
85
86
87
# File 'lib/ri_cal/occurrence_enumerator.rb', line 82

def exclusion_for(occurrence)
  while (@next_exclusion && @next_exclusion.dtstart < occurrence.dtstart)
    @next_exclusion = @exrules.next_occurrence
  end
  @next_exclusion
end

#exclusion_match?(occurrence, exclusion) ⇒ Boolean

TODO: Need to research this, I beleive that this should also take the end time into account,

but I need to research

Returns:

  • (Boolean)


91
92
93
# File 'lib/ri_cal/occurrence_enumerator.rb', line 91

def exclusion_match?(occurrence, exclusion)
  exclusion && (occurrence.dtstart == exclusion.dtstart)
end

#next_occurrenceObject



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/ri_cal/occurrence_enumerator.rb', line 101

def next_occurrence
  @next_exclusion ||= @exrules.next_occurrence
  occurrence = nil

  until occurrence
    if (occurrence = @rrules.next_occurrence)
      if exclusion_match?(occurrence, exclusion_for(occurrence))
        occurrence = nil # Look for the next one
      end
    else
      break
    end
  end
  occurrence
end

#options_stop(occurrence) ⇒ Object



117
118
119
120
121
122
# File 'lib/ri_cal/occurrence_enumerator.rb', line 117

def options_stop(occurrence)
  occurrence != :excluded &&
  (@cutoff && occurrence.dtstart.to_datetime >= @cutoff) || 
  (@count && @yielded >= @count) ||
  (@overlap_range && occurrence.after_range?(@overlap_range))
end

#process_options(options) ⇒ Object



160
161
162
163
164
165
# File 'lib/ri_cal/occurrence_enumerator.rb', line 160

def process_options(options)
  @start = options[:starting] && options[:starting].to_datetime
  @cutoff = options[:before] && options[:before].to_datetime
  @overlap_range = process_overlap_range(options[:overlapping])
  @count = options[:count]
end

#process_overlap_range(overlap_range) ⇒ Object



154
155
156
157
158
# File 'lib/ri_cal/occurrence_enumerator.rb', line 154

def process_overlap_range(overlap_range)
  if overlap_range
    @overlap_range = [overlap_range.first.to_overlap_range_start, overlap_range.last.to_overlap_range_end]
  end
end

#to_a(options = {}) ⇒ Object Also known as: entries

Raises:

  • (ArgumentError)


167
168
169
170
171
# File 'lib/ri_cal/occurrence_enumerator.rb', line 167

def to_a(options = {})
  process_options(options)
  raise ArgumentError.new("This component is unbounded, cannot produce an array of occurrences!") unless bounded?
  super()
end