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


76
77
78
79
80
81
# File 'lib/ri_cal/occurrence_enumerator.rb', line 76

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)

99
100
101
102
# File 'lib/ri_cal/occurrence_enumerator.rb', line 99

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

#bounded?Boolean

Returns:

  • (Boolean)

153
154
155
# File 'lib/ri_cal/occurrence_enumerator.rb', line 153

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


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

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


85
86
87
88
89
90
# File 'lib/ri_cal/occurrence_enumerator.rb', line 85

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)

94
95
96
# File 'lib/ri_cal/occurrence_enumerator.rb', line 94

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

#next_occurrenceObject


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/ri_cal/occurrence_enumerator.rb', line 104

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


120
121
122
123
124
125
# File 'lib/ri_cal/occurrence_enumerator.rb', line 120

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


163
164
165
166
167
168
# File 'lib/ri_cal/occurrence_enumerator.rb', line 163

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


157
158
159
160
161
# File 'lib/ri_cal/occurrence_enumerator.rb', line 157

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)

170
171
172
173
174
# File 'lib/ri_cal/occurrence_enumerator.rb', line 170

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