/* Copyright (C) 2000-2003 Max Berger This file is part of vCardReceiver, written for the OpenGroupware project (OGo) OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id$ #include #include #import "OGoSyncMLZSAdapterContactsDatabaseHandler.h" #import "OGoSyncMLZSAdapterSessionHandler.h" #import #import #import #import #import "OGoVCard.h" @implementation OGoSyncMLZSAdapterContactsDatabaseHandler - initWithSessionHandler:(OGoSyncMLZSAdapterSessionHandler *)handler { self = [super init]; if (self) { sessionHandler = handler; } return self; } - (NSString *)databaseLocation { return @"./Contacts/"; } - (NSString *)databaseDescription { return @"OpenGroupware Contacts"; } - (NSString *)syncWithLocation { return @""; } - (int)syncAlert { return SYNCML_SYNC_ALERT_NO; } - (NSArray *)allUIDs { LSCommandContext *cmdctx = [[sessionHandler syncml]backendDataForKey:@"Cmdctx"]; id contactManager = [[SxContactManager alloc]initWithContext:cmdctx]; NSEnumerator *enumerator; id obj; id uid; NSMutableArray *ret = [[NSMutableArray alloc]init]; enumerator = [contactManager listContactSet: [SxContactSetIdentifier publicPersons]]; while ((obj=[enumerator nextObject])!=nil) { uid = [[obj objectForKey:@"pkey"]description]; [ret addObject:[NSString stringWithFormat:@"Person %@",uid]]; } enumerator = [contactManager listContactSet: [SxContactSetIdentifier privatePersons]]; while ((obj=[enumerator nextObject])!=nil) { uid = [[obj objectForKey:@"pkey"]description]; [ret addObject:[NSString stringWithFormat:@"Person %@",uid]]; } enumerator = [contactManager listContactSet: [SxContactSetIdentifier accounts]]; while ((obj=[enumerator nextObject])!=nil) { uid = [[obj objectForKey:@"pkey"]description]; [ret addObject:[NSString stringWithFormat:@"Person %@",uid]]; } enumerator = [contactManager listContactSet: [SxContactSetIdentifier publicEnterprises]]; while ((obj=[enumerator nextObject])!=nil) { uid = [[obj objectForKey:@"pkey"]description]; [ret addObject:[NSString stringWithFormat:@"Enterprise %@",uid]]; } enumerator = [contactManager listContactSet: [SxContactSetIdentifier privateEnterprises]]; while ((obj=[enumerator nextObject])!=nil) { uid = [[obj objectForKey:@"pkey"]description]; [ret addObject:[NSString stringWithFormat:@"Enterprise %@",uid]]; } [contactManager release]; return [ret autorelease]; } - (EOKeyGlobalID*)_globalIDForUID:(NSString *)uid { NSArray *splituid = [uid componentsSeparatedByString:@" "]; id subuid = [splituid objectAtIndex:1]; id gid = [EOKeyGlobalID globalIDWithEntityName:[splituid objectAtIndex:0] keys:&subuid keyCount:1 zone:nil]; return gid; } - (NSString *)representationForUID:(id)uid { LSCommandContext *cmdctx = [[sessionHandler syncml]backendDataForKey:@"Cmdctx"]; id contactManager = [[SxContactManager alloc]initWithContext:(id)cmdctx]; id gid = [self _globalIDForUID:uid]; NSArray *gids = [NSArray arrayWithObjects:gid,nil]; NSEnumerator *enumerator = [contactManager idsAndVersionsAndVCardsForGlobalIDs:gids]; id theObject = [enumerator nextObject]; id vCardData = [theObject valueForKey:@"vCardData"]; [contactManager release]; if (vCardData) return [NSString stringWithString:vCardData]; return @""; } - (id)versionForUID:(id)UID { // FIXME: Should return the real version // return [self representationForUID:UID]; return @""; } - (BOOL)_isDict:(NSDictionary*)vdict sameAs:(NSDictionary *)gdict { NSMutableSet *keys = [[NSMutableSet alloc]init]; NSEnumerator *keyEnum; NSString *key; int same=0,superv=0,superg=0,different=0; id vObj, gObj; int vLen, gLen; [keys addObjectsFromArray:[vdict allKeys]]; [keys addObjectsFromArray:[gdict allKeys]]; keyEnum = [keys objectEnumerator]; while ((key = [keyEnum nextObject])) { vObj = [vdict objectForKey:key]; gObj = [gdict objectForKey:key]; if ([vObj respondsToSelector:@selector(length)]) vLen = [vObj length]; else vLen = (vObj==nil)?0:1; if ([gObj respondsToSelector:@selector(length)]) gLen = [gObj length]; else gLen = (gObj==nil)?0:1; if ((vLen == 0)&&(gLen > 0)) superg++; else if ((gLen == 0)&&(vLen > 0)) superv++; else if ((gLen > 0)&&(vLen>0)) { if ([vObj respondsToSelector:@selector(isEqualToDictionary:)]) { if ([self _isDict:vObj sameAs:gObj]) same++; else different++; } else { if ([vObj isEqual:gObj]) same++; else different++; } } } //NSLog(@"CompRes: %u %u %u %u",same,superv,superg,different); [keys release]; return ((same>0)&&(different==0)); } - (BOOL)_isOGoVCard:(OGoVCard*) vcarddata sameAs:(EOKeyGlobalID*)gid { LSCommandContext *cmdctx = [[sessionHandler syncml]backendDataForKey:@"Cmdctx"]; id contactManager = [[SxContactManager alloc]initWithContext:(id)cmdctx]; NSDictionary *info = [contactManager fullPersonInfoForPrimaryKey:[gid keyValues][0]]; NSDictionary *vinfo = [vcarddata info]; [contactManager release]; return [self _isDict:info sameAs:vinfo]; } - (NSException *)_handleException:(NSException *)_exception whileUpdatingContact:(SxUpdateContact *)_contact { NSLog(@"Error merging %@", _contact); NSLog(@"Error: %@", _exception); return nil; } - (NSString*)_searchAndAdd:(OGoVCard*) vcarddata { LSCommandContext *cmdctx; NSEnumerator *uidEnum; id currentUID; EOKeyGlobalID *gid; SxUpdateContact *updateContact = nil; cmdctx = [[sessionHandler syncml]backendDataForKey:@"Cmdctx"]; uidEnum = [[self allUIDs] objectEnumerator]; while ((currentUID = [uidEnum nextObject])) { gid = [self _globalIDForUID:currentUID]; if (![self _isOGoVCard:vcarddata sameAs:gid]) continue; NSLog(@"Merging..."); NSLog(@"New Data: %@",[vcarddata info]); updateContact = [[SxUpdatePerson alloc] initWithContext:cmdctx primaryKey: [gid keyValues][0] attributes: [vcarddata info]]; NS_DURING [updateContact update]; NS_HANDLER { [[self _handleException:localException whileUpdatingContact:updateContact] raise]; } NS_ENDHANDLER; NSLog(@"www"); [updateContact release]; NSLog(@"xxx"); [cmdctx flush]; NSLog(@"yyy"); return currentUID; } NSLog(@"Creating new entry"); updateContact = [[SxUpdatePerson alloc] initWithContext:cmdctx primaryKey:0 attributes:[vcarddata info]]; [updateContact update]; currentUID = [NSString stringWithFormat:@"Person %@", [[updateContact object] valueForKey:@"pkey"]]; [updateContact release]; [cmdctx flush]; return currentUID; } - (NSString*)addElement:(NSString *)data withUri:(NSString *)location { id parser = nil; SaxObjectDecoder *sax = nil; OGoVCard *root; NSString *uid; id factory = [SaxXMLReaderFactory standardXMLReaderFactory]; parser = [[factory createXMLReaderForMimeType:@"text/vcard"] retain]; sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"OGoVCard"]; [parser setContentHandler:sax]; [parser setErrorHandler:sax]; if (parser == nil) { NSLog(@"%s: WARNING! failed to init parser for type text/vcard", __PRETTY_FUNCTION__); } else if (sax == nil) { NSLog(@"%s: WARNING! failed to init object decoder for mapping OGoVCard", __PRETTY_FUNCTION__); } [parser parseFromSource:data]; root = [sax rootObject]; if (root == nil ) { NSLog(@"%s: failed parsing Add-request content", __PRETTY_FUNCTION__); return nil; } uid = [self _searchAndAdd:root]; [parser release]; [sax release]; return uid; } - (BOOL)deleteAll { return YES; } @end /* OGoSyncMLZSAdapterContactsDatabaseHandler */