mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-07-19 07:04:53 +00:00
Monotone-Parent: 29948ba19f24f47aa6c1b2c0764586b89ff9493f
Monotone-Revision: 1a5434f30282a4932bf29227da4cf2da44ef5783 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-07-11T22:28:12 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -19,34 +19,21 @@
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSNull.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
|
||||
#import "iCalEntityObject+OCS.h"
|
||||
#import "iCalRepeatableEntityObject+OCS.h"
|
||||
#import <SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h>
|
||||
|
||||
#import "OCSiCalFieldExtractor.h"
|
||||
|
||||
@implementation OCSiCalFieldExtractor
|
||||
|
||||
static NSCalendarDate *distantFuture = nil;
|
||||
static NSNumber *distantFutureNumber = nil;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (!distantFuture)
|
||||
{
|
||||
distantFuture = [[NSCalendarDate distantFuture] retain];
|
||||
/* INT_MAX due to Postgres constraint */
|
||||
distantFutureNumber = [[NSNumber numberWithUnsignedInt: INT_MAX] retain];
|
||||
}
|
||||
}
|
||||
|
||||
+ (id) sharedICalFieldExtractor
|
||||
{
|
||||
static OCSiCalFieldExtractor *extractor = nil;
|
||||
@@ -59,287 +46,6 @@ static NSNumber *distantFutureNumber = nil;
|
||||
|
||||
/* operations */
|
||||
|
||||
- (NSNumber *) numberForDate: (NSCalendarDate *) _date
|
||||
{
|
||||
return ((_date == distantFuture)
|
||||
? distantFutureNumber
|
||||
: [NSNumber numberWithUnsignedInt: [_date timeIntervalSince1970]]);
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *) extractQuickFieldsFromEvent: (iCalEvent *) _event
|
||||
{
|
||||
NSMutableDictionary *row;
|
||||
NSCalendarDate *startDate, *endDate;
|
||||
NSArray *attendees;
|
||||
NSString *uid, *title, *location, *status;
|
||||
NSNumber *sequence, *dateNumber;
|
||||
id organizer;
|
||||
id participants, partmails;
|
||||
NSMutableString *partstates;
|
||||
unsigned int i, count;
|
||||
BOOL isAllDay;
|
||||
iCalAccessClass accessClass;
|
||||
|
||||
if (_event == nil)
|
||||
return nil;
|
||||
|
||||
/* extract values */
|
||||
|
||||
startDate = [_event startDate];
|
||||
endDate = [_event endDate];
|
||||
uid = [_event uid];
|
||||
title = [_event summary];
|
||||
if (![title isNotNull])
|
||||
title = @"";
|
||||
location = [_event location];
|
||||
sequence = [_event sequence];
|
||||
accessClass = [_event symbolicAccessClass];
|
||||
isAllDay = [_event isAllDay];
|
||||
status = [[_event status] uppercaseString];
|
||||
|
||||
attendees = [_event attendees];
|
||||
partmails = [attendees valueForKey: @"rfc822Email"];
|
||||
partmails = [partmails componentsJoinedByString: @"\n"];
|
||||
participants = [attendees valueForKey: @"cn"];
|
||||
participants = [participants componentsJoinedByString: @"\n"];
|
||||
|
||||
/* build row */
|
||||
|
||||
row = [NSMutableDictionary dictionaryWithCapacity:8];
|
||||
|
||||
[row setObject: @"vevent" forKey: @"c_component"];
|
||||
|
||||
if ([uid isNotNull])
|
||||
[row setObject:uid forKey: @"c_uid"];
|
||||
else
|
||||
[self logWithFormat: @"WARNING: could not extract a uid from event!"];
|
||||
|
||||
|
||||
[row setObject: [NSNumber numberWithBool: isAllDay]
|
||||
forKey: @"c_isallday"];
|
||||
[row setObject: [NSNumber numberWithBool: [_event isRecurrent]]
|
||||
forKey: @"c_iscycle"];
|
||||
[row setObject: [NSNumber numberWithBool: [_event isOpaque]]
|
||||
forKey: @"c_isopaque"];
|
||||
[row setObject: [NSNumber numberWithInt: [_event priorityNumber]]
|
||||
forKey: @"c_priority"];
|
||||
|
||||
[row setObject: title forKey: @"c_title"];
|
||||
if ([location isNotNull]) [row setObject: location forKey: @"c_location"];
|
||||
if ([sequence isNotNull]) [row setObject: sequence forKey: @"c_sequence"];
|
||||
|
||||
if ([startDate isNotNull])
|
||||
[row setObject: [self numberForDate: startDate]
|
||||
forKey: @"c_startdate"];
|
||||
if ([endDate isNotNull])
|
||||
{
|
||||
if (endDate == distantFuture)
|
||||
dateNumber = distantFutureNumber;
|
||||
else
|
||||
{
|
||||
if (isAllDay)
|
||||
i = 1;
|
||||
else
|
||||
i = 0;
|
||||
dateNumber
|
||||
= [NSNumber numberWithUnsignedInt:
|
||||
[endDate timeIntervalSince1970] - i];
|
||||
}
|
||||
[row setObject: dateNumber forKey: @"c_enddate"];
|
||||
}
|
||||
|
||||
if ([_event isRecurrent]) {
|
||||
NSCalendarDate *date;
|
||||
|
||||
date = [_event lastPossibleRecurrenceStartDate];
|
||||
if (!date) {
|
||||
/* this could also be *nil*, but in the end it makes the fetchspecs
|
||||
more complex - thus we set it to a "reasonable" distant future */
|
||||
date = distantFuture;
|
||||
}
|
||||
[row setObject:[self numberForDate:date] forKey: @"c_cycleenddate"];
|
||||
[row setObject:[_event cycleInfo] forKey: @"c_cycleinfo"];
|
||||
}
|
||||
|
||||
if ([participants length] > 0)
|
||||
[row setObject: participants forKey: @"c_participants"];
|
||||
if ([partmails length] > 0)
|
||||
[row setObject: partmails forKey: @"c_partmails"];
|
||||
|
||||
if ([status isNotNull]) {
|
||||
int code = 1;
|
||||
|
||||
if ([status isEqualToString: @"TENTATIVE"])
|
||||
code = 2;
|
||||
else if ([status isEqualToString: @"CANCELLED"])
|
||||
code = 0;
|
||||
[row setObject:[NSNumber numberWithInt:code] forKey: @"c_status"];
|
||||
}
|
||||
else {
|
||||
/* confirmed by default */
|
||||
[row setObject: [NSNumber numberWithInt:1] forKey: @"c_status"];
|
||||
}
|
||||
|
||||
[row setObject: [NSNumber numberWithUnsignedInt: accessClass]
|
||||
forKey: @"c_classification"];
|
||||
|
||||
organizer = [_event organizer];
|
||||
if (organizer) {
|
||||
NSString *email;
|
||||
|
||||
email = [organizer valueForKey: @"rfc822Email"];
|
||||
if (email)
|
||||
[row setObject:email forKey: @"c_orgmail"];
|
||||
}
|
||||
|
||||
/* construct partstates */
|
||||
count = [attendees count];
|
||||
partstates = [[NSMutableString alloc] initWithCapacity:count * 2];
|
||||
for ( i = 0; i < count; i++) {
|
||||
iCalPerson *p;
|
||||
iCalPersonPartStat stat;
|
||||
|
||||
p = [attendees objectAtIndex:i];
|
||||
stat = [p participationStatus];
|
||||
if(i != 0)
|
||||
[partstates appendString: @"\n"];
|
||||
[partstates appendFormat: @"%d", stat];
|
||||
}
|
||||
[row setObject:partstates forKey: @"c_partstates"];
|
||||
[partstates release];
|
||||
return row;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *) extractQuickFieldsFromTodo: (iCalToDo *) _task
|
||||
{
|
||||
NSMutableDictionary *row;
|
||||
NSCalendarDate *startDate, *dueDate;
|
||||
NSArray *attendees;
|
||||
NSString *uid, *title, *location, *status;
|
||||
NSNumber *sequence;
|
||||
id organizer, date;
|
||||
id participants, partmails;
|
||||
NSMutableString *partstates;
|
||||
unsigned i, count, code;
|
||||
iCalAccessClass accessClass;
|
||||
|
||||
if (_task == nil)
|
||||
return nil;
|
||||
|
||||
/* extract values */
|
||||
|
||||
startDate = [_task startDate];
|
||||
dueDate = [_task due];
|
||||
uid = [_task uid];
|
||||
title = [_task summary];
|
||||
if (![title isNotNull])
|
||||
title = @"";
|
||||
location = [_task location];
|
||||
sequence = [_task sequence];
|
||||
accessClass = [_task symbolicAccessClass];
|
||||
status = [[_task status] uppercaseString];
|
||||
|
||||
attendees = [_task attendees];
|
||||
partmails = [attendees valueForKey: @"rfc822Email"];
|
||||
partmails = [partmails componentsJoinedByString: @"\n"];
|
||||
participants = [attendees valueForKey: @"cn"];
|
||||
participants = [participants componentsJoinedByString: @"\n"];
|
||||
|
||||
/* build row */
|
||||
|
||||
row = [NSMutableDictionary dictionaryWithCapacity:8];
|
||||
|
||||
[row setObject: @"vtodo" forKey: @"c_component"];
|
||||
|
||||
if ([uid isNotNull])
|
||||
[row setObject:uid forKey: @"c_uid"];
|
||||
else
|
||||
[self logWithFormat: @"WARNING: could not extract a uid from event!"];
|
||||
|
||||
[row setObject:[NSNumber numberWithBool:[_task isRecurrent]]
|
||||
forKey: @"c_iscycle"];
|
||||
[row setObject:[NSNumber numberWithInt:[_task priorityNumber]]
|
||||
forKey: @"c_priority"];
|
||||
|
||||
[row setObject: [NSNumber numberWithBool: NO]
|
||||
forKey: @"c_isallday"];
|
||||
[row setObject: [NSNumber numberWithBool: NO]
|
||||
forKey: @"c_isopaque"];
|
||||
|
||||
[row setObject: title forKey: @"c_title"];
|
||||
if ([location isNotNull]) [row setObject: location forKey: @"c_location"];
|
||||
if ([sequence isNotNull]) [row setObject: sequence forKey: @"c_sequence"];
|
||||
|
||||
if ([startDate isNotNull])
|
||||
date = [self numberForDate: startDate];
|
||||
else
|
||||
date = [NSNull null];
|
||||
[row setObject: date forKey: @"c_startdate"];
|
||||
|
||||
if ([dueDate isNotNull])
|
||||
date = [self numberForDate: dueDate];
|
||||
else
|
||||
date = [NSNull null];
|
||||
[row setObject: date forKey: @"c_enddate"];
|
||||
|
||||
if ([_task isRecurrent])
|
||||
{
|
||||
[row setObject: [self numberForDate: distantFuture]
|
||||
forKey: @"c_cycleenddate"];
|
||||
[row setObject: [_task cycleInfo]
|
||||
forKey: @"c_cycleinfo"];
|
||||
}
|
||||
|
||||
if ([participants length] > 0)
|
||||
[row setObject:participants forKey: @"c_participants"];
|
||||
if ([partmails length] > 0)
|
||||
[row setObject:partmails forKey: @"c_partmails"];
|
||||
|
||||
if ([status isNotNull]) {
|
||||
code = 0; /* NEEDS-ACTION */
|
||||
if ([status isEqualToString: @"COMPLETED"])
|
||||
code = 1;
|
||||
else if ([status isEqualToString: @"IN-PROCESS"])
|
||||
code = 2;
|
||||
else if ([status isEqualToString: @"CANCELLED"])
|
||||
code = 3;
|
||||
[row setObject: [NSNumber numberWithInt: code] forKey: @"c_status"];
|
||||
}
|
||||
else {
|
||||
/* confirmed by default */
|
||||
[row setObject:[NSNumber numberWithInt:1] forKey: @"c_status"];
|
||||
}
|
||||
|
||||
[row setObject: [NSNumber numberWithUnsignedInt: accessClass]
|
||||
forKey: @"c_classification"];
|
||||
|
||||
organizer = [_task organizer];
|
||||
if (organizer) {
|
||||
NSString *email;
|
||||
|
||||
email = [organizer valueForKey: @"rfc822Email"];
|
||||
if (email)
|
||||
[row setObject:email forKey: @"c_orgmail"];
|
||||
}
|
||||
|
||||
/* construct partstates */
|
||||
count = [attendees count];
|
||||
partstates = [[NSMutableString alloc] initWithCapacity:count * 2];
|
||||
for ( i = 0; i < count; i++) {
|
||||
iCalPerson *p;
|
||||
iCalPersonPartStat stat;
|
||||
|
||||
p = [attendees objectAtIndex:i];
|
||||
stat = [p participationStatus];
|
||||
if(i != 0)
|
||||
[partstates appendString: @"\n"];
|
||||
[partstates appendFormat: @"%d", stat];
|
||||
}
|
||||
[row setObject:partstates forKey: @"c_partstates"];
|
||||
[partstates release];
|
||||
return row;
|
||||
}
|
||||
|
||||
- (CardGroup *) firstElementFromCalendar: (iCalCalendar *) ical
|
||||
{
|
||||
NSArray *elements;
|
||||
@@ -349,13 +55,7 @@ static NSNumber *distantFutureNumber = nil;
|
||||
elements = [ical allObjects];
|
||||
count = [elements count];
|
||||
if (count)
|
||||
{
|
||||
if (count > 1)
|
||||
[self logWithFormat:
|
||||
@"WARNING: given calendar contains more than one event: %@",
|
||||
ical];
|
||||
element = [elements objectAtIndex: 0];
|
||||
}
|
||||
element = [elements objectAtIndex: 0];
|
||||
else
|
||||
{
|
||||
[self logWithFormat: @"ERROR: given calendar contains no elements: %@", ical];
|
||||
@@ -365,34 +65,32 @@ static NSNumber *distantFutureNumber = nil;
|
||||
return element;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)extractQuickFieldsFromContent:(NSString *)_content {
|
||||
NSDictionary *fields;
|
||||
- (NSMutableDictionary *) extractQuickFieldsFromContent: (NSString *) _content
|
||||
{
|
||||
NSMutableDictionary *fields;
|
||||
id cal;
|
||||
|
||||
if ([_content length] == 0)
|
||||
return nil;
|
||||
|
||||
cal = [iCalCalendar parseSingleFromSource: _content];
|
||||
|
||||
fields = nil;
|
||||
if (cal)
|
||||
|
||||
if ([_content length])
|
||||
{
|
||||
if ([cal isKindOfClass:[iCalCalendar class]])
|
||||
cal = [self firstElementFromCalendar: cal];
|
||||
cal = [iCalCalendar parseSingleFromSource: _content];
|
||||
if (cal)
|
||||
{
|
||||
if ([cal isKindOfClass: [iCalCalendar class]])
|
||||
cal = [self firstElementFromCalendar: cal];
|
||||
|
||||
if ([cal isKindOfClass:[iCalEvent class]])
|
||||
fields = [[self extractQuickFieldsFromEvent:cal] retain];
|
||||
else if ([cal isKindOfClass:[iCalToDo class]])
|
||||
fields = [[self extractQuickFieldsFromTodo:cal] retain];
|
||||
else if ([cal isNotNull]) {
|
||||
[self logWithFormat: @"ERROR: unexpected iCalendar parse result: %@",
|
||||
cal];
|
||||
}
|
||||
if ([cal isKindOfClass: [iCalRepeatableEntityObject class]])
|
||||
fields = [cal quickRecord];
|
||||
else if ([cal isNotNull])
|
||||
[self logWithFormat: @"ERROR: unexpected iCalendar parse result: %@",
|
||||
cal];
|
||||
}
|
||||
else
|
||||
[self logWithFormat: @"ERROR: parsing source didn't return anything"];
|
||||
}
|
||||
else
|
||||
[self logWithFormat: @"ERROR: parsing source didn't return anything"];
|
||||
|
||||
return [fields autorelease];
|
||||
return fields;
|
||||
}
|
||||
|
||||
@end /* OCSiCalFieldExtractor */
|
||||
|
||||
Reference in New Issue
Block a user