Class: RiCal::Component

Inherits:
Object show all
Defined in:
lib/ri_cal/component.rb,
lib/ri_cal/component/todo.rb,
lib/ri_cal/component/event.rb,
lib/ri_cal/component/alarm.rb,
lib/ri_cal/component/journal.rb,
lib/ri_cal/component/calendar.rb,
lib/ri_cal/component/timezone.rb,
lib/ri_cal/component/freebusy.rb,
lib/ri_cal/component/non_standard.rb,
lib/ri_cal/component/timezone/standard_period.rb,
lib/ri_cal/component/timezone/daylight_period.rb,
lib/ri_cal/component/timezone/timezone_period.rb

Overview

  • ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license

Defined Under Namespace

Classes: Alarm, Calendar, ComponentBuilder, Event, Freebusy, Journal, NonStandard, TZInfoTimezone, Timezone, Todo

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil, entity_name = nil, &init_block) ⇒ Component

:nodoc:


46
47
48
49
50
51
52
53
54
55
# File 'lib/ri_cal/component.rb', line 46

def initialize(parent=nil, entity_name = nil, &init_block) #:nodoc:
  @parent = parent
  if block_given?
    if init_block.arity == 1
      init_block.call(ComponentBuilder.new(self))
    else
      ComponentBuilder.new(self).instance_eval(&init_block)
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(selector, *args, &b) ⇒ Object

:nodoc:


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/ri_cal/component.rb', line 162

def method_missing(selector, *args, &b) #:nodoc:
  xprop_candidate = selector.to_s
  if (match = /^(x_.+)(=?)$/.match(xprop_candidate))
    x_property_key = match[1].gsub('_','-').upcase
    if match[2] == "="
      args.each do |val|
        add_x_property(x_property_key, val)
      end
    else
      x_properties[x_property_key].map {|property| property.value}
    end
  else
    super
  end
end

Instance Attribute Details

#importedObject

:nodoc:


44
45
46
# File 'lib/ri_cal/component.rb', line 44

def imported
  @imported
end

Class Method Details

.entity_nameObject

:nodoc:


155
156
157
# File 'lib/ri_cal/component/timezone.rb', line 155

def self.entity_name #:nodoc:
  "VTIMEZONE"
end

.from_parser(parser, parent, entity_name) ⇒ Object

:nodoc:


93
94
95
96
97
98
99
100
101
102
# File 'lib/ri_cal/component.rb', line 93

def self.from_parser(parser, parent, entity_name) #:nodoc:
  entity = self.new(parent, entity_name)
  entity.imported = true
  line = parser.next_separated_line
  while parser.still_in(entity_name, line)
    entity.process_line(parser, line)
    line = parser.next_separated_line
  end
  entity
end

.parse(io) ⇒ Object

:nodoc:


104
105
106
# File 'lib/ri_cal/component.rb', line 104

def self.parse(io) #:nodoc:
  Parser.new(io).parse
end

.parse_string(string) ⇒ Object

:nodoc:


112
113
114
# File 'lib/ri_cal/component.rb', line 112

def self.parse_string(string) #:nodoc:
  parse(StringIO.new(string))
end

Instance Method Details

#add_property_date_times_to(required_timezones, property) ⇒ Object

:nodoc:


195
196
197
198
199
200
201
202
203
204
205
# File 'lib/ri_cal/component.rb', line 195

def add_property_date_times_to(required_timezones, property) #:nodoc:
  if property
    if Array === property
      property.each do |prop|
        prop.add_date_times_to(required_timezones)
      end
    else
      property.add_date_times_to(required_timezones)
    end
  end
end

#add_subcomponent(component) ⇒ Object

:nodoc:


130
131
132
# File 'lib/ri_cal/component.rb', line 130

def add_subcomponent(component) #:nodoc:
  subcomponents[component.entity_name] << component
end

#add_x_property(name, prop, debug = false) ⇒ Object

Add a n extended property


158
159
160
# File 'lib/ri_cal/component.rb', line 158

def add_x_property(name, prop, debug=false)
  x_properties[name.gsub("_","-").upcase] << prop.to_ri_cal_text_property
end

#alarmsObject

return an array of Alarm components within this component :nodoc: Alarms may be contained within Events, and Todos


126
127
128
# File 'lib/ri_cal/component.rb', line 126

def alarms
  subcomponents["VALARM"]
end

#daylightObject

:nodoc:


163
164
165
# File 'lib/ri_cal/component/timezone.rb', line 163

def daylight #:nodoc:
  @subcomponents["DAYLIGHT"]
end

#default_tzidObject

:nodoc:


57
58
59
60
61
62
63
# File 'lib/ri_cal/component.rb', line 57

def default_tzid #:nodoc:
  if @parent
    @parent.default_tzid
  else
    PropertyValue::DateTime.default_tzid
  end
end

#entity_nameObject

:nodoc:


120
121
122
# File 'lib/ri_cal/component.rb', line 120

def entity_name #:nodoc:
  self.class.entity_name
end

#export(stream = nil) ⇒ Object

Export this single component as an iCalendar component containing only this component and any required additional components (i.e. VTIMEZONES referenced from this component) if stream is nil (the default) then this method will return a string, otherwise stream should be an IO to which the iCalendar file contents will be written


250
251
252
253
254
# File 'lib/ri_cal/component.rb', line 250

def export(stream=nil)
  wrapper_calendar = Calendar.new
  wrapper_calendar.add_subcomponent(self)
  wrapper_calendar.export(stream)
end

#export_prop_to(export_stream, name, prop) ⇒ Object

:nodoc:


207
208
209
210
211
212
# File 'lib/ri_cal/component.rb', line 207

def export_prop_to(export_stream, name, prop) #:nodoc:
  if prop
    string = prop_string(name, prop)
    export_stream.puts(string) if string
  end
end

#export_subcomponent_to(export_stream, subcomponent) ⇒ Object

:nodoc:


222
223
224
225
226
# File 'lib/ri_cal/component.rb', line 222

def export_subcomponent_to(export_stream, subcomponent) #:nodoc:
  subcomponent.each do |component|
    component.export_to(export_stream)
  end
end

#export_to(export_stream) ⇒ Object

Export this component to an export stream


236
237
238
239
240
241
242
243
244
# File 'lib/ri_cal/component.rb', line 236

def export_to(export_stream)
  export_stream.puts("BEGIN:#{entity_name}")
  export_properties_to(export_stream)
  export_x_properties_to(export_stream)
  subcomponents.values.each do |sub|
    export_subcomponent_to(export_stream, sub)
  end
  export_stream.puts("END:#{entity_name}")
end

#export_x_properties_to(export_stream) ⇒ Object

:nodoc:


214
215
216
217
218
219
220
# File 'lib/ri_cal/component.rb', line 214

def export_x_properties_to(export_stream) #:nodoc:
  x_properties.each do |name, props|
    props.each do | prop |
      export_stream.puts("#{name}:#{prop}")
    end
  end
end

#find_timezone(identifier) ⇒ Object

:nodoc:


65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ri_cal/component.rb', line 65

def find_timezone(identifier) #:nodoc:
  if @parent
    @parent.find_timezone(identifier)
  else
    begin
      Calendar::TZInfoWrapper.new(TZInfo::Timezone.get(identifier), self)
    rescue ::TZInfo::InvalidTimezoneIdentifier => ex
      raise RiCal::InvalidTimezoneIdentifier.invalid_tzinfo_identifier(identifier)
    end
  end
end

#imported?Boolean

:nodoc:


108
109
110
# File 'lib/ri_cal/component.rb', line 108

def imported? #:nodoc:
  imported
end

#initialize_copy(original) ⇒ Object

:nodoc:


183
184
# File 'lib/ri_cal/component.rb', line 183

def initialize_copy(original) #:nodoc:
end

#last_before_local(period_array, time) ⇒ Object

:nodoc:


187
188
189
190
191
192
193
# File 'lib/ri_cal/component/timezone.rb', line 187

def last_before_local(period_array, time) #:nodoc:
  candidates = period_array.map {|period|
    period.last_before_local(time)
  }
  result = candidates.max {|a, b| a.dtstart_property <=> b.dtstart_property}
  result
end

#last_before_utc(period_array, time) ⇒ Object

:nodoc:


179
180
181
182
183
184
185
# File 'lib/ri_cal/component/timezone.rb', line 179

def last_before_utc(period_array, time) #:nodoc:
  candidates = period_array.map {|period|
    period.last_before_utc(time)
  }
  result = candidates.max {|a, b| a.dtstart_property <=> b.dtstart_property}
  result
end

#last_period(standard, daylight) ⇒ Object

:nodoc:


167
168
169
170
171
172
173
174
175
176
177
# File 'lib/ri_cal/component/timezone.rb', line 167

def last_period(standard, daylight) #:nodoc:
  if standard
    if daylight
      standard.dtstart > daylight.dtstart ? standard : daylight
    else
      standard
    end
  else
    daylight
  end
end

#parse_subcomponent(parser, line) ⇒ Object

:nodoc:


134
135
136
# File 'lib/ri_cal/component.rb', line 134

def parse_subcomponent(parser, line) #:nodoc:
  subcomponents[line[:value]] << parser.parse_one(line, self)
end

#process_line(parser, line) ⇒ Object

:nodoc:


138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ri_cal/component.rb', line 138

def process_line(parser, line) #:nodoc:
  if line[:name] == "BEGIN"
    parse_subcomponent(parser, line)
  else
    setter = self.class.property_parser[line[:name]]
    if setter
      send(setter, line)
    else
      self.add_x_property(line[:name], PropertyValue::Text.new(self, line))
    end
  end
end

#prop_string(prop_name, *properties) ⇒ Object

:nodoc:


186
187
188
189
190
191
192
193
# File 'lib/ri_cal/component.rb', line 186

def prop_string(prop_name, *properties) #:nodoc:
  properties = properties.flatten.compact
  if properties && !properties.empty?
    properties.map {|prop| "#{prop_name}#{prop.to_s}"}.join("\n")
  else
    nil
  end
end

#standardObject

:nodoc:


159
160
161
# File 'lib/ri_cal/component/timezone.rb', line 159

def standard #:nodoc:
  @subcomponents["STANDARD"]
end

#subcomponent_classObject

:nodoc:


89
90
91
# File 'lib/ri_cal/component.rb', line 89

def subcomponent_class #:nodoc:
  {}
end

#subcomponentsObject

:nodoc:


116
117
118
# File 'lib/ri_cal/component.rb', line 116

def subcomponents #:nodoc:
  @subcomponents ||= Hash.new {|h, k| h[k] = []}
end

#time_zone_for(ruby_object) ⇒ Object

:nodoc:


85
86
87
# File 'lib/ri_cal/component.rb', line 85

def time_zone_for(ruby_object) #:nodoc:
  @parent.time_zone_for(ruby_object) #:nodoc:
end

#to_sObject

return a string containing the rfc2445 format of the component


229
230
231
232
233
# File 'lib/ri_cal/component.rb', line 229

def to_s
  io = StringIO.new
  export_to(io)
  io.string
end

#tz_info_source?Boolean


77
78
79
80
81
82
83
# File 'lib/ri_cal/component.rb', line 77

def tz_info_source?
  if @parent
    @parent.tz_info_source?
  else
    true
  end
end

#valid?Boolean

Predicate to determine if the component is valid according to RFC 2445


179
180
181
# File 'lib/ri_cal/component.rb', line 179

def valid?
  !mutual_exclusion_violation
end

#x_propertiesObject

return a hash of any extended properties, (i.e. those with a property name starting with “X-” representing an extension to the RFC 2445 specification)


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

def x_properties
  @x_properties ||= Hash.new {|h,k| h[k] = []}
end