lib/vpim/address.rb in vpim-0.357 vs lib/vpim/address.rb in vpim-0.360

- old
+ new

@@ -45,96 +45,46 @@ # Used to represent calendar fields containing CAL-ADDRESS values. # The organizer or the attendees of a calendar event are examples of such # a field. # # Example: + # # ORGANIZER;CN="A. Person":mailto:a_person@example.com + # # ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION # ;CN="Sam Roberts";RSVP=TRUE:mailto:SRoberts@example.com # class Address - # Create an Address from a DirectoryInfo::Field, +field+. - # - # TODO - make private, and split into the encode/decode/create trinity. - def initialize(field) - unless field.value - raise ArgumentError - end - - @field = field - end - - # Return a representation of this Address as a DirectoryInfo::Field. - def field - @field.copy - end - # Create a copy of Address. If the original Address was frozen, this one # won't be. def copy - Marshal.load(Marshal.dump(self)) + #Marshal.load(Marshal.dump(self)) + self.dup.dirty end - # Addresses in a CAL-ADDRESS are represented as a URI, usually a mailto URI. - def uri - @field.value + def dirty #:nodoc: + @field = nil + self end - # Return true if the +uri+ is == to this address' URI. The comparison - # is case-insensitive. - # - # FIXME - why case insensitive? Email addresses. Should use a URI library - # if I can find one and it knows how to do URI comparisons. - def ==(uri) - Vpim::Methods.casecmp?(self.uri.to_str, uri.to_str) - end - - # The common or displayable name associated with the calendar address, - # or nil if there is none. - def cn - return nil unless n = @field.param('CN') - - # FIXME = the CN param may have no value, which is an error, but don't try - # to decode it, return either nil, or InvalidEncoding - Vpim.decode_text(n.first) - end - - # A string representation of an address, using the common name, and the - # URI. The URI protocol is stripped if it's "mailto:". - # - # TODO - this needs to properly escape the cn string! - def to_s - u = uri - u.gsub!(/^mailto: */i, '') - - if cn - "\"#{cn}\" <#{uri}>" - else - uri - end - end - - def inspect - "#<Vpim::Icalendar::Address:cn=#{cn.inspect} status=#{partstat} rsvp?=#{rsvp} #{uri.inspect}>" - end - + # Addresses in a CAL-ADDRESS are represented as a URI, usually a mailto URI. + attr_accessor :uri + # The common or displayable name associated with the calendar address, or + # nil if there is none. + attr_accessor :cn # The participation role for the calendar user specified by the address. # # The standard roles are: # - CHAIR Indicates chair of the calendar entity # - REQ-PARTICIPANT Indicates a participant whose participation is required # - OPT-PARTICIPANT Indicates a participant whose participation is optional # - NON-PARTICIPANT Indicates a participant who is copied for information purposes only # # The default role is REQ-PARTICIPANT, returned if no ROLE parameter was # specified. - def role - return 'REQ-PARTICIPANT' unless r = @field.param('ROLE') - r.first.upcase - end - + attr_accessor :role # The participation status for the calendar user specified by the # property PARTSTAT, a String. # # These are the participation statuses for an Event: # - NEEDS-ACTION Event needs action @@ -143,39 +93,127 @@ # - TENTATIVE Event tentatively accepted # - DELEGATED Event delegated # # Default is NEEDS-ACTION. # - # TODO - make the default depend on the component type. - def partstat - return 'NEEDS-ACTION' unless r = @field.param('PARTSTAT') - r.first.upcase + # FIXME - make the default depend on the component type. + attr_accessor :partstat + # The value of the RSVP field, either +true+ or +false+. It is used to + # specify whether there is an expectation of a reply from the calendar + # user specified by the property value. + attr_accessor :rsvp + + def initialize(field=nil) #:nodoc: + @field = field + @uri = '' + @cn = '' + @role = "REQ-PARTICIPANT" + @partstat = "NEEDS-ACTION" + @rsvp = false end - # Set or change the participation status of the address, the PARTSTAT, - # to +status+. - # - # See #partstat. - def partstat=(status) - @field['PARTSTAT'] = status.to_str - status + # Create a new Address. It will encode as a +name+ property. + def self.create(uri='') + adr = new + adr.uri = uri.to_str + adr end - # The value of the RSVP field, either +true+ or +false+. It is used to - # specify whether there is an expectation of a favor of a reply from the - # calendar user specified by the property value. - # - # TODO - should be #rsvp? - def rsvp - return false unless r = @field.param('RSVP') - r = r.first - return false unless r - case r - when /TRUE/i then true - when /FALSE/i then false - else raise InvalidEncodingError, "RSVP param value not TRUE/FALSE: #{r}" + def self.decode(field) + adr = new(field) + adr.uri = field.value + + cn = field.param('CN') + + if cn + adr.cn = cn.first end + + role = field.param('ROLE') + + if role + adr.role = role.first.strip.upcase + end + + partstat = field.param('PARTSTAT') + + if partstat + adr.partstat = partstat.first.strip.upcase + end + + rsvp = field.param('RSVP') + + if rsvp + adr.rsvp = case rsvp.first + when /TRUE/i then true + when /FALSE/i then false + else raise InvalidEncodingError, "RSVP param value not TRUE/FALSE: #{rsvp}" + end + end + + adr.freeze end + + # Return a representation of this Address as a DirectoryInfo::Field. + def encode(name) #:nodoc: + if @field + # FIXME - set the field name, it could be different from cached + return @field + end + + value = uri.to_str.strip + + if value.empty? + raise Uencodeable, "Address#uri is zero-length" + end + + params = {} + + if cn.length > 0 + params['CN'] = Vpim::encode_paramvalue(cn) + end + + # FIXME - default value is different for non-vEvent + if role.length > 0 && role != 'REQ-PARTICIPANT' + params['ROLE'] = Vpim::encode_paramtext(role) + end + + # FIXME - default value is different for non-vEvent + if partstat.length > 0 && partstat != 'NEEDS-ACTION' + params['PARTSTAT'] = Vpim::encode_paramtext(partstat) + end + + if rsvp + params['RSVP'] = 'true' + end + + Vpim::DirectoryInfo::Field.create(name, value, params) + end + + # Return true if the +uri+ is == to this address' URI. The comparison + # is case-insensitive (because email addresses and domain names are). + def ==(uri) + # TODO - could I use a URI library? + Vpim::Methods.casecmp?(self.uri.to_str, uri.to_str) + end + + # A string representation of an address, using the common name, and the + # URI. The URI protocol is stripped if it's "mailto:". + def to_s + u = uri + u = u.gsub(/^mailto: */i, '') + + if cn.length > 0 + "#{cn.inspect} <#{uri}>" + else + uri + end + end + + def inspect #:nodoc: + "#<Vpim::Icalendar::Address:cn=#{cn.inspect} status=#{partstat} rsvp=#{rsvp} #{uri.inspect}>" + end + end end end