Monotone-Parent: 848b310c090a03db48d0571c275639c9b9b49c9f

Monotone-Revision: d1a4f0ec595bfdd85dcd021dca6e4957ac192140

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2010-08-20T01:36:08
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2010-08-20 01:36:08 +00:00
parent d96c9f09ba
commit 89d282d220
2 changed files with 525 additions and 0 deletions

View File

@ -0,0 +1,68 @@
/* GCSAlarmsFolder.h - this file is part of $PROJECT_NAME_HERE$
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef GCSALARMSFOLDER_H
#define GCSALARMSFOLDER_H
#import <Foundation/NSObject.h>
@class NSCalendarDate;
@class NSException;
@class NSNumber;
@class NSString;
@class GCSFolderManager;
@interface GCSAlarmsFolder : NSObject
{
GCSFolderManager *folderManager;
}
+ (id) alarmsFolderWithFolderManager: (GCSFolderManager *) newFolderManager;
- (void) setFolderManager: (GCSFolderManager *) newFolderManager;
/* operations */
- (void) createFolderIfNotExists;
- (BOOL) canConnectStore;
- (NSDictionary *) recordForEntryWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path;
- (NSArray *) recordsForEntriesFromDate: (NSCalendarDate *) fromDate
toDate: (NSCalendarDate *) toDate;
- (void) writeRecordForEntryWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path
forUID: (NSString *) uid
recurrenceId: (NSCalendarDate *) recId
alarmNumber: (NSNumber *) alarmNbr
andAlarmDate: (NSCalendarDate *) alarmNbr;
- (void) deleteRecordForEntryWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path;
- (void) deleteRecordsForEntriesUntilDate: (NSCalendarDate *) date;
@end
#endif /* GCSALARMSFOLDER_H */

View File

@ -0,0 +1,457 @@
/* GCSAlarmsFolder.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSNull+misc.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLAccess/EOAdaptorContext.h>
#import <GDLAccess/EOAttribute.h>
#import <GDLAccess/EOEntity.h>
#import <GDLAccess/EOSQLQualifier.h>
#import "EOQualifier+GCS.h"
#import "GCSChannelManager.h"
#import "GCSFolderManager.h"
#import "GCSSpecialQueries.h"
#import "GCSStringFormatter.h"
#import "NSURL+GCS.h"
#import "GCSAlarmsFolder.h"
static NSString *alarmsFolderURLString = nil;
#warning GCSAlarmsFolder should share a common ancestor with GCSFolder
@implementation GCSAlarmsFolder
+ (void) initialize
{
NSUserDefaults *ud;
if (!alarmsFolderURLString)
{
ud = [NSUserDefaults standardUserDefaults];
ASSIGN (alarmsFolderURLString,
[ud stringForKey: @"OCSEMailAlarmsFolderURL"]);
}
}
+ (id) alarmsFolderWithFolderManager: (GCSFolderManager *) newFolderManager
{
GCSAlarmsFolder *newFolder;
if (alarmsFolderURLString)
{
newFolder = [self new];
[newFolder autorelease];
[newFolder setFolderManager: newFolderManager];
}
else
{
[self errorWithFormat: @"'OCSEMailAlarmsFolderURL' is not set"];
newFolder = nil;
}
return newFolder;
}
- (void) setFolderManager: (GCSFolderManager *) newFolderManager
{
ASSIGN (folderManager, newFolderManager);
}
/* accessors */
- (NSURL *) _location
{
NSURL *location;
if (alarmsFolderURLString)
location = [NSURL URLWithString: alarmsFolderURLString];
else
{
[self warnWithFormat: @"'OCSEMailAlarmsFolderURL' is not set"];
location = nil;
}
return location;
}
- (GCSChannelManager *) _channelManager
{
return [folderManager channelManager];
}
- (NSString *) _storeTableName
{
return [[self _location] gcsTableName];
}
- (EOEntity *) _storeTableEntityForChannel: (EOAdaptorChannel *) tc
{
static EOEntity *entity = nil;
EOAttribute *attribute;
NSString *tableName;
NSString *columns[] = { @"c_path", @"c_name", @"c_uid",
@"c_recurrence_id", @"c_alarm_number",
@"c_alarm_date", nil };
NSString **column;
NSMutableArray *keys;
NSDictionary *types;
if (!entity)
{
entity = [EOEntity new];
tableName = [self _storeTableName];
[entity setName: tableName];
[entity setExternalName: tableName];
types = [[tc specialQueries] emailAlarmsAttributeTypes];
column = columns;
while (*column)
{
attribute = [EOAttribute new];
[attribute setName: *column];
[attribute setColumnName: *column];
[attribute setExternalType: [types objectForKey: *column]];
[entity addAttribute: attribute];
[attribute release];
column++;
}
keys = [NSMutableArray arrayWithCapacity: 2];
[keys addObject: [entity attributeNamed: @"c_path"]];
[keys addObject: [entity attributeNamed: @"c_name"]];
[entity setPrimaryKeyAttributes: keys];
keys = [NSMutableArray arrayWithCapacity: 3];
[keys addObject: [entity attributeNamed: @"c_uid"]];
[keys addObject: [entity attributeNamed: @"c_recurrence_id"]];
[keys addObject: [entity attributeNamed: @"c_alarm_number"]];
[entity setClassProperties: keys];
[entity setAttributesUsedForLocking: [NSArray array]];
}
return entity;
}
/* connection */
- (EOAdaptorChannel *) _acquireStoreChannel
{
return [[self _channelManager] acquireOpenChannelForURL: [self _location]];
}
- (void) _releaseChannel: (EOAdaptorChannel *) _channel
{
[[self _channelManager] releaseChannel:_channel];
}
- (BOOL) canConnectStore
{
return [[self _channelManager] canConnect:[self _location]];
}
- (void) createFolderIfNotExists
{
EOAdaptorChannel *tc;
NSString *sql, *tableName;
GCSSpecialQueries *queries;
tc = [self _acquireStoreChannel];
tableName = [self _storeTableName];
queries = [tc specialQueries];
sql = [NSString stringWithFormat: @"SELECT count(*) FROM %@",
[self _storeTableName]];
if ([tc evaluateExpressionX: sql])
{
sql = [queries createEMailAlarmsFolderWithName: tableName];
if (![tc evaluateExpressionX: sql])
[self logWithFormat:
@"email alarms folder table '%@' successfully created!",
tableName];
}
else
[tc cancelFetch];
[self _releaseChannel: tc];
}
/* operations */
/* table has the following fields:
c_path VARCHAR(255) NOT NULL
c_name VARCHAR(255) NOT NULLo
c_uid VARCHAR(255) NOT NULL
c_recurrence_id INT NULL
c_alarm_number INT NOT NULL
*/
- (NSDictionary *) recordForEntryWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
NSString *tableName;
NSException *error;
NSArray *attrs;
NSDictionary *record;
EOEntity *entity;
EOSQLQualifier *qualifier;
tableName = [self _storeTableName];
record = nil;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_path='%@' AND c_name='%@'",
path, cname];
[qualifier autorelease];
[context beginTransaction];
error = [tc selectAttributesX: [entity attributesUsedForFetch]
describedByQualifier: qualifier
fetchOrder: nil
lock: NO];
if (error)
[self errorWithFormat:@"%s: cannot execute fetch: %@",
__PRETTY_FUNCTION__, error];
else
{
attrs = [tc describeResults: NO];
record = [tc fetchAttributes: attrs withZone: NULL];
[tc cancelFetch];
}
[context rollbackTransaction];
[self _releaseChannel: tc];
}
return record;
}
- (NSArray *) recordsForEntriesFromDate: (NSCalendarDate *) fromDate
toDate: (NSCalendarDate *) toDate
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
NSString *tableName;
NSException *error;
NSArray *attrs;
NSDictionary *record;
EOEntity *entity;
EOSQLQualifier *qualifier;
NSMutableArray *records;
tableName = [self _storeTableName];
records = nil;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier
= [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_alarm_date >= %d AND c_alarm_date <= %d",
(int) [fromDate timeIntervalSince1970],
(int) [toDate timeIntervalSince1970]];
[qualifier autorelease];
[context beginTransaction];
error = [tc selectAttributesX: [entity attributesUsedForFetch]
describedByQualifier: qualifier
fetchOrder: nil
lock: NO];
if (error)
[self errorWithFormat:@"%s: cannot execute fetch: %@",
__PRETTY_FUNCTION__, error];
else
{
records = [NSMutableArray array];
attrs = [tc describeResults: NO];
while ((record = [tc fetchAttributes: attrs withZone: NULL]))
[records addObject: record];
}
[context rollbackTransaction];
[self _releaseChannel: tc];
}
return records;
}
- (NSDictionary *) _newRecordWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path
forUID: (NSString *) uid
recurrenceId: (NSCalendarDate *) recId
alarmNumber: (NSNumber *) alarmNbr
andAlarmDate: (NSCalendarDate *) alarmDate
{
NSNumber *tRecId, *tADate;
tRecId = [NSNumber numberWithInt: (int) [recId timeIntervalSince1970]];
tADate = [NSNumber numberWithInt: (int) [alarmDate timeIntervalSince1970]];
return [NSDictionary dictionaryWithObjectsAndKeys: cname, @"c_name",
path, @"c_path",
uid, @"c_uid",
tRecId, @"c_recurrence_id",
alarmNbr, @"c_alarm_number",
tADate, @"c_alarm_date",
nil];
}
- (void) writeRecordForEntryWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path
forUID: (NSString *) uid
recurrenceId: (NSCalendarDate *) recId
alarmNumber: (NSNumber *) alarmNbr
andAlarmDate: (NSCalendarDate *) alarmDate
{
NSDictionary *record, *newRecord;
NSException *error;
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
newRecord = [self _newRecordWithCName: cname
inCalendarAtPath: path
forUID: uid
recurrenceId: recId
alarmNumber: alarmNbr
andAlarmDate: alarmDate];
record = [self recordForEntryWithCName: cname
inCalendarAtPath: path];
entity = [self _storeTableEntityForChannel: tc];
[context beginTransaction];
if (record)
{
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_path='%@' AND c_name='%@'",
path, cname];
[qualifier autorelease];
error = [tc updateRowX: newRecord describedByQualifier: qualifier];
}
else
error = [tc insertRowX: newRecord forEntity: entity];
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot write record: %@",
__PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
}
- (void) deleteRecordForEntryWithCName: (NSString *) cname
inCalendarAtPath: (NSString *) path
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
NSException *error;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_path='%@' AND c_name='%@'",
path, cname];
[qualifier autorelease];
[context beginTransaction];
error = [tc deleteRowsDescribedByQualifierX: qualifier];
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot delete record: %@",
__PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
}
- (void) deleteRecordsForEntriesUntilDate: (NSCalendarDate *) date
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
NSException *error;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_alarm_date <= %d",
(int) [date timeIntervalSince1970]];
[qualifier autorelease];
[context beginTransaction];
error = [tc deleteRowsDescribedByQualifierX: qualifier];
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot delete record: %@",
__PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
}
@end