]> err.no Git - sope/commitdiff
new differ and accompanied functionality
authorznek <znek@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Wed, 1 Sep 2004 21:52:57 +0000 (21:52 +0000)
committerznek <znek@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Wed, 1 Sep 2004 21:52:57 +0000 (21:52 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@102 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

12 files changed:
sope-ical/NGiCal/ChangeLog
sope-ical/NGiCal/GNUmakefile
sope-ical/NGiCal/NGiCal.h
sope-ical/NGiCal/NGiCal.xcode/project.pbxproj
sope-ical/NGiCal/Version
sope-ical/NGiCal/common.h
sope-ical/NGiCal/iCalEvent.h
sope-ical/NGiCal/iCalEvent.m
sope-ical/NGiCal/iCalEventChanges.h [new file with mode: 0644]
sope-ical/NGiCal/iCalEventChanges.m [new file with mode: 0644]
sope-ical/NGiCal/iCalPerson.h
sope-ical/NGiCal/iCalPerson.m

index bbce5a3ec2bd1c1d6d65fc3e3d41e768f6eccc0c..47f63a9d36a553c34879427e1438d2a19c91f097 100644 (file)
@@ -1,3 +1,15 @@
+2004-09-01  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * v4.3.29
+
+       * iCalEventChanges.[hm]: new class for tracking changes between
+         two given events
+
+       * iCalEvent.[hm]: new API to generate iCalEventChanges objects.
+
+       * common.h: inline function and macro for "safe" comparison of
+         object values
+
 2004-09-01  Helge Hess  <helge.hess@opengroupware.org>
 
        * GNUmakefile.postamble: copy sax-model to FHS_INSTALL_ROOT + 
index 6691770bdd8f29a32922de69fa22cfd8305deb66..63458c492b98083ee45f4d76c946dd9ec38c37af 100644 (file)
@@ -25,6 +25,7 @@ libNGiCal_HEADER_FILES =      \
        iCalDuration.h          \
        iCalTrigger.h           \
        iCalDataSource.h        \
+       iCalEventChanges.h      \
 
 #      IcalResponse.h          \
 
@@ -45,6 +46,7 @@ libNGiCal_OBJC_FILES =        \
        iCalDuration.m          \
        iCalTrigger.m           \
        iCalDataSource.m        \
+       iCalEventChanges.m      \
 
 #      NSString+ICal.m         \
 #      IcalElements.m
index 5d4e21c12a46c9d6223f8a764af8c868f82b98fd..e35a4a5feb3713a021618daef5aad03d061e5308 100644 (file)
@@ -35,4 +35,6 @@
 #include <NGiCal/iCalDuration.h>
 #include <NGiCal/iCalTrigger.h>
 
+#include <NGiCal/iCalEventChanges.h>
+
 #endif /* __NGiCal_H__ */
index 8d38d37aed745411c2c2ae51bdd9c8eebb349f7e..17585f44c1fdc603b2a60388b3e081066b4350fa 100644 (file)
@@ -5,6 +5,36 @@
        };
        objectVersion = 39;
        objects = {
+               ADD1FC9906E4D6D400E387F0 = {
+                       fileEncoding = 5;
+                       indentWidth = 2;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = iCalEventChanges.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               ADD1FC9A06E4D6D400E387F0 = {
+                       fileEncoding = 5;
+                       indentWidth = 2;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = iCalEventChanges.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               ADD1FC9B06E4D6D400E387F0 = {
+                       fileRef = ADD1FC9906E4D6D400E387F0;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               ADD1FC9C06E4D6D400E387F0 = {
+                       fileRef = ADD1FC9A06E4D6D400E387F0;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
                ADDF4E5106DE4FC600C4E7F8 = {
                        children = (
                                ADDF4F3E06DE513D00C4E7F8,
                                ADDF4F6406DE513D00C4E7F8,
                                ADDF4F6606DE513D00C4E7F8,
                                ADDF4F6806DE513D00C4E7F8,
+                               ADD1FC9B06E4D6D400E387F0,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                ADDF4F6306DE513D00C4E7F8,
                                ADDF4F6506DE513D00C4E7F8,
                                ADDF4F6906DE513D00C4E7F8,
+                               ADD1FC9C06E4D6D400E387F0,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                GCC_WARN_UNKNOWN_PRAGMAS = NO;
                                INFOPLIST_FILE = "NGiCal-Info.plist";
                                INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-                               OPTIMIZATION_CFLAGS = "";
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "-seg1addr 0xC1E00000 -headerpad_max_install_names";
                                OTHER_REZFLAGS = "";
                                ADDF4F3406DE513D00C4E7F8,
                                ADDF4F3606DE513D00C4E7F8,
                                ADDF4F3A06DE513D00C4E7F8,
+                               ADD1FC9906E4D6D400E387F0,
                        );
                        isa = PBXGroup;
                        name = Headers;
                                ADDF4F3506DE513D00C4E7F8,
                                ADDF4F3706DE513D00C4E7F8,
                                ADDF4F3B06DE513D00C4E7F8,
+                               ADD1FC9A06E4D6D400E387F0,
                        );
                        isa = PBXGroup;
                        name = Classes;
index d077e9f95e3d65c889ec0fd5e8fde3842fa4e229..21126fa75dafc942f5a41e68322df712f1b131db 100644 (file)
@@ -2,4 +2,4 @@
 
 MAJOR_VERSION=4
 MINOR_VERSION=3
-SUBMINOR_VERSION:=28
+SUBMINOR_VERSION:=29
index 1633aa18eed5051a00547932bfabb38aafe653da..3c4514510c8341c2fdd334ae8df4204f0b22a69d 100644 (file)
 #include <EOControl/EOControl.h>
 #include <NGExtensions/NGExtensions.h>
 
+#define IS_EQUAL(a, b, sel) \
+  _iCalSafeCompareObjects(a, b, @selector(sel))
+
+static __inline__ BOOL _iCalSafeCompareObjects(id a, id b, SEL comparator) {
+  id va = a;
+  id vb = b;
+  BOOL (*compm)(id, SEL, id);
+
+  if((va == nil && vb != nil) || (va != nil && vb == nil))
+    return NO;
+  else if(va == vb)
+    return YES;
+  compm = (BOOL (*)( id, SEL, id))[va methodForSelector:comparator];
+  return compm(va, comparator, vb);
+}
+
 #endif /* __ICal_common_H__ */
index 1559038f5918630cfcb1855415ef739b2572d5f9..19f74fcb0ec0508f8c7b1a2a8ab83d1a6f873275 100644 (file)
@@ -34,7 +34,7 @@
 */
 
 @class NSString, NSMutableArray, NSCalendarDate;
-@class iCalPerson;
+@class iCalPerson, iCalEventChanges;
 
 @interface iCalEvent : iCalEntityObject
 {
@@ -53,6 +53,8 @@
 - (BOOL)hasDuration;
 - (NSTimeInterval)durationAsTimeInterval;
 
+- (iCalEventChanges *)getChangesRelativeToEvent:(iCalEvent *)_event;
+
 @end 
 
 #endif /* __NGiCal_iCalEvent_H__ */
index b97cbc13f5d5541f6fbacb26adff537bccb5afd6..b88259e5fc6f4e34aee57c2e9ee2e805a4d0e5b1 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "iCalEvent.h"
 #include "iCalPerson.h"
+#include "iCalEventChanges.h"
 #include "common.h"
 
 @interface NSString(DurationTimeInterval)
   return ms;
 }
 
+/* changes */
+
+- (iCalEventChanges *)getChangesRelativeToEvent:(iCalEvent *)_event {
+  return [iCalEventChanges changesFromEvent:_event
+                           toEvent:self];
+}
+
 @end /* iCalEvent */
 
 @implementation NSString(DurationTimeInterval)
diff --git a/sope-ical/NGiCal/iCalEventChanges.h b/sope-ical/NGiCal/iCalEventChanges.h
new file mode 100644 (file)
index 0000000..c761410
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2004 SKYRIX Software AG
+ This file is part of OpenGroupware.org.
+ 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$
+//  Created by znek on 31.08.04.
+
+#ifndef        __NGiCal_iCalEventChanges_H_
+#define        __NGiCal_iCalEventChanges_H_
+
+#include <Foundation/NSObject.h>
+
+@class iCalEvent, NSArray, NSMutableArray;
+
+@interface iCalEventChanges : NSObject
+{
+  NSMutableArray *insertedAttendees;
+  NSMutableArray *deletedAttendees;
+  NSMutableArray *updatedAttendees;
+  NSMutableArray *insertedAlarms;
+  NSMutableArray *deletedAlarms;
+  NSMutableArray *updatedAlarms;
+  NSMutableArray *updatedProperties;
+}
+
++ (id)changesFromEvent:(iCalEvent *)_old toEvent:(iCalEvent *)_to;
+- (id)initWithFromEvent:(iCalEvent *)_from toEvent:(iCalEvent *)_to;
+
+- (BOOL)hasChanges;
+
+- (BOOL)hasAttendeeChanges;
+- (NSArray *)insertedAttendees;
+- (NSArray *)deletedAttendees;
+- (NSArray *)updatedAttendees;
+
+- (BOOL)hasAlarmChanges;
+- (NSArray *)insertedAlarms;
+- (NSArray *)deletedAlarms;
+- (NSArray *)updatedAlarms;
+
+- (BOOL)hasPropertyChanges;
+- (NSArray *)updatedProperties;
+
+@end
+
+#endif /* __NGiCal_iCalEventChanges_H_ */
diff --git a/sope-ical/NGiCal/iCalEventChanges.m b/sope-ical/NGiCal/iCalEventChanges.m
new file mode 100644 (file)
index 0000000..f8eec4b
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ Copyright (C) 2004 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ 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 "iCalEventChanges.h"
+#include "iCalEvent.h"
+#include "iCalPerson.h"
+#include "common.h"
+
+@interface iCalEventChanges (PrivateAPI)
+- (void)_trackAttendeeChanges:(iCalEvent *)_from :(iCalEvent *)_to;
+- (void)_trackAlarmChanges:(iCalEvent *)_from :(iCalEvent *)_to;
+- (void)_trackPropertyChanges:(iCalEvent *)_from :(iCalEvent *)_to;
+@end
+
+@implementation iCalEventChanges
+
++ (id)changesFromEvent:(iCalEvent *)_from toEvent:(iCalEvent *)_to {
+  return [[[self alloc] initWithFromEvent:_from toEvent:_to] autorelease];
+}
+
+- (id)initWithFromEvent:(iCalEvent *)_from toEvent:(iCalEvent *)_to {
+  self = [super init];
+  if(self) {
+    self->insertedAttendees = [[NSMutableArray alloc] init];
+    self->deletedAttendees  = [[NSMutableArray alloc] init];
+    self->updatedAttendees  = [[NSMutableArray alloc] init];
+    self->insertedAlarms    = [[NSMutableArray alloc] init];
+    self->deletedAlarms     = [[NSMutableArray alloc] init];
+    self->updatedAlarms     = [[NSMutableArray alloc] init];
+    self->updatedProperties = [[NSMutableArray alloc] init];
+    [self _trackAttendeeChanges:_from :_to];
+    [self _trackPropertyChanges:_from :_to];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self->insertedAttendees release];
+  [self->deletedAttendees  release];
+  [self->updatedAttendees  release];
+  [self->insertedAlarms    release];
+  [self->deletedAlarms     release];
+  [self->updatedAlarms     release];
+  [self->updatedProperties release];
+  [super dealloc];
+}
+
+- (void)_trackAttendeeChanges:(iCalEvent *)_from :(iCalEvent *)_to {
+  unsigned f, t, fcount, tcount;
+  NSArray *fromAttendees, *toAttendees;
+
+  fromAttendees = [_from attendees];
+  fcount = [fromAttendees count];
+  toAttendees = [_to attendees];
+  tcount = [toAttendees count];
+  for(f = 0; f < fcount; f++) {
+    iCalPerson *fp;
+    BOOL found = NO;
+
+    fp = [fromAttendees objectAtIndex:f];
+
+    for(t = 0; t < tcount; t++) {
+      iCalPerson *tp;
+
+      tp = [toAttendees objectAtIndex:t];
+      if([fp hasSameEmailAddress:tp]) {
+        found = YES;
+        if(![fp isEqualToPerson:tp]) {
+          [self->updatedAttendees addObject:tp];
+        }
+        break;
+      }
+    }
+    if(!found) {
+      [self->deletedAttendees addObject:fp];
+    }
+  }
+  for(t = 0; t < tcount; t++) {
+    iCalPerson *tp;
+    BOOL found = NO;
+
+    tp = [toAttendees objectAtIndex:t];
+    for(f = 0; f < fcount; f++) {
+      iCalPerson *fp;
+
+      fp = [fromAttendees objectAtIndex:f];
+      if([tp hasSameEmailAddress:fp]) {
+        found = YES;
+        break;
+      }
+    }
+    if(!found)
+      [self->insertedAttendees addObject:tp];
+  }
+}
+
+- (void)_trackAlarmChanges:(iCalEvent *)_from :(iCalEvent *)_to {
+}
+
+- (void)_trackPropertyChanges:(iCalEvent *)_from :(iCalEvent *)_to {
+  if(!IS_EQUAL([_from startDate], [_to startDate], isEqualToDate:))
+    [self->updatedProperties addObject:@"startDate"];
+  if(!IS_EQUAL([_from endDate], [_to endDate], isEqualToDate:))
+    [self->updatedProperties addObject:@"endDate"];
+  if(!IS_EQUAL([_from created], [_to created], isEqualToDate:))
+    [self->updatedProperties addObject:@"created"];
+  if(!IS_EQUAL([_from lastModified], [_to lastModified], isEqualToDate:))
+    [self->updatedProperties addObject:@"lastModified"];
+  if(![_from durationAsTimeInterval] == [_to durationAsTimeInterval])
+    [self->updatedProperties addObject:@"duration"];
+  if(!IS_EQUAL([_from summary], [_to summary], isEqualToString:))
+    [self->updatedProperties addObject:@"summary"];
+  if(!IS_EQUAL([_from location], [_to location], isEqualToString:))
+    [self->updatedProperties addObject:@"location"];
+  if(!IS_EQUAL([_from comment], [_to comment], isEqualToString:))
+    [self->updatedProperties addObject:@"comment"];
+  if(!IS_EQUAL([_from priority], [_to priority], isEqualToString:))
+    [self->updatedProperties addObject:@"priority"];
+  if(!IS_EQUAL([_from status], [_to status], isEqualToString:))
+    [self->updatedProperties addObject:@"status"];
+  if(!IS_EQUAL([_from accessClass], [_to accessClass], isEqualToString:))
+    [self->updatedProperties addObject:@"accessClass"];
+  if(!IS_EQUAL([_from sequence], [_to sequence], isEqualToNumber:))
+    [self->updatedProperties addObject:@"sequence"];
+  if(!IS_EQUAL([_from organizer], [_to organizer], isEqual:))
+    [self->updatedProperties addObject:@"organizer"];
+}
+
+- (BOOL)hasChanges {
+  return [self hasAttendeeChanges]  ||
+         [self hasAlarmChanges]     ||
+         [self hasPropertyChanges];
+}
+
+- (BOOL)hasAttendeeChanges {
+  return [[self insertedAttendees] count] > 0 ||
+         [[self deletedAttendees]  count] > 0 ||
+         [[self updatedAttendees]  count] > 0;
+}
+
+- (BOOL)hasAlarmChanges {
+  return [[self insertedAlarms] count] > 0 ||
+         [[self deletedAlarms]  count] > 0 ||
+         [[self updatedAlarms]  count] > 0;
+}
+
+- (BOOL)hasPropertyChanges {
+  return [[self updatedProperties] count] > 0;
+}
+
+- (NSArray *)insertedAttendees {
+  return self->insertedAttendees;
+}
+- (NSArray *)deletedAttendees {
+  return self->deletedAttendees;
+}
+- (NSArray *)updatedAttendees {
+  return self->updatedAttendees;
+}
+
+- (NSArray *)insertedAlarms {
+  return self->insertedAlarms;
+}
+- (NSArray *)deletedAlarms {
+  return self->deletedAlarms;
+}
+- (NSArray *)updatedAlarms {
+  return self->updatedAlarms;
+}
+
+- (NSArray *)updatedProperties {
+  return self->updatedProperties;
+}
+
+/* descriptions */
+
+- (NSString *)description {
+  NSMutableString *ms;
+  
+  ms = [NSMutableString stringWithCapacity:128];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  
+  [ms appendFormat:@" updatedProperties=%@", self->updatedProperties];
+  [ms appendFormat:@" insertedAttendees=%@", self->insertedAttendees];
+  [ms appendFormat:@" deletedAttendees=%@", self->deletedAttendees];
+  [ms appendFormat:@" updatedAttendees=%@", self->updatedAttendees];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+@end
index 7b670c706e6e96ed97bbf3dabce7b32592764199..2fb6bf87354a7686c0d80c960eb48f80ee4f42c9 100644 (file)
@@ -55,6 +55,9 @@
 - (void)setPartStat:(NSString *)_s;
 - (NSString *)partStat;
 
+- (BOOL)isEqualToPerson:(iCalPerson *)_other;
+- (BOOL)hasSameEmailAddress:(iCalPerson *)_other;
+
 @end
 
 #endif /* __NGiCal_iCalPerson_H__ */
index a537156ef37754ca37f6c78b804a2bb7b812241f..0b7073562eb92890010328af024d22ef4c2b66c4 100644 (file)
   return self->partStat;
 }
 
+/* comparison */
+
+- (unsigned)hash {
+  if([self email])
+    return [[self email] hash];
+  return [super hash];
+}
+
+- (BOOL)isEqual:(id)_other {
+  if(_other == nil)
+    return NO;
+  if([_other class] != self->isa)
+    return NO;
+  if([_other hash] != [self hash])
+    return NO;
+  return [self isEqualToPerson:_other];
+}
+
+- (BOOL)isEqualToPerson:(iCalPerson *)_other {
+  if(![self hasSameEmailAddress:_other])
+    return NO;
+  if(!IS_EQUAL([self cn], [_other cn], isEqualToString:))
+    return NO;
+  if(!IS_EQUAL([self rsvp], [_other rsvp], isEqualToString:))
+    return NO;
+  if(!IS_EQUAL([self partStat], [_other partStat], isEqualToString:))
+    return NO;
+  if(!IS_EQUAL([self role], [_other role], isEqualToString:))
+    return NO;
+  if(!IS_EQUAL([self xuid], [_other xuid], isEqualToString:))
+    return NO;
+  return YES;
+}
+
+- (BOOL)hasSameEmailAddress:(iCalPerson *)_other {
+  return IS_EQUAL([self email], [_other email], isEqualToString:);
+}
+
 /* descriptions */
 
 - (NSString *)description {