mirror of
https://github.com/gnustep/libs-ec.git
synced 2025-02-19 10:01:24 +00:00
Add support for limited activitym periods for a rule
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/ec/trunk@38358 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
db6fc5df31
commit
31498b9afe
2 changed files with 319 additions and 4 deletions
36
EcAlerter.h
36
EcAlerter.h
|
@ -119,6 +119,42 @@
|
||||||
* of enhanced posix regular expressions. If this is not present,
|
* of enhanced posix regular expressions. If this is not present,
|
||||||
* any message text will match.
|
* any message text will match.
|
||||||
* </desc>
|
* </desc>
|
||||||
|
* <term>ActiveFrom</term>
|
||||||
|
* <desc>A date/time specifying the earliest point at which this rule
|
||||||
|
* may match any alarm. If the current date/time is earlier than
|
||||||
|
* this (optional) value then the rule simply can't match.
|
||||||
|
* </desc>
|
||||||
|
* <term>ActiveTo</term>
|
||||||
|
* <desc>A date/time specifying the latest point at which this rule
|
||||||
|
* may match any alarm. If the current date/time is later than
|
||||||
|
* this (optional) value then the rule simply can't match.
|
||||||
|
* </desc>
|
||||||
|
* <term>ActiveTimes</term>
|
||||||
|
* <desc>Either a string containing a comma separated list of ranges
|
||||||
|
* of times specified using a 24 hour clock, or a dictionary of such
|
||||||
|
* strings keyed on the days of the week (Monday, Tuesday, Wednesday,
|
||||||
|
* Thursday, Friday, Saturday, Sunday), possibly with an asterisk used
|
||||||
|
* as the key for a default string to be used for any day not listed. <br />
|
||||||
|
* If a simple string, the list applies to all days of the week
|
||||||
|
* (equivalent to a dictionary containing a single string keyed on
|
||||||
|
* an asterisk).<br />
|
||||||
|
* The times are in HH:MM format or may simply be the hours (HH) with
|
||||||
|
* a minute value of zero implied.<br />
|
||||||
|
* The range separator is a dash/minus, and the range includes the
|
||||||
|
* first value and excludes the second one.<br />
|
||||||
|
* eg. 10:45-11 means that the rule is active in the 15 minute interval
|
||||||
|
* from 10:45 until 11:00 but becomes inactive again at 11:00<br />
|
||||||
|
* The end of each range must be later than the start of the range,
|
||||||
|
* and the starts of each successive range must be later than or equal
|
||||||
|
* to the end of the preceding range.<br />
|
||||||
|
* As a special case the time 24:00 may be used as the end of the
|
||||||
|
* last range in a list.<br />
|
||||||
|
* If this field is simply omitted, the rule is active all day every day.
|
||||||
|
* </desc>
|
||||||
|
* <term>ActiveTimezone</term>
|
||||||
|
* <desc>The formal name of the time zone in which the system checks
|
||||||
|
* active date/time information. If omitted, the GMT timezone is assumed.
|
||||||
|
* </desc>
|
||||||
* <term>Stop</term>
|
* <term>Stop</term>
|
||||||
* <desc>A boolean (YES or NO) saying whether rule matching should
|
* <desc>A boolean (YES or NO) saying whether rule matching should
|
||||||
* stop if this rule is matched. If this is NO (the default) then
|
* stop if this rule is matched. If this is NO (the default) then
|
||||||
|
|
287
EcAlerter.m
287
EcAlerter.m
|
@ -253,12 +253,13 @@ replaceFields(NSDictionary *fields, NSString *template)
|
||||||
|
|
||||||
- (BOOL) setRules: (NSArray*)ra
|
- (BOOL) setRules: (NSArray*)ra
|
||||||
{
|
{
|
||||||
NSUInteger i = 0;
|
|
||||||
NSMutableArray *r = AUTORELEASE([ra mutableCopy]);
|
NSMutableArray *r = AUTORELEASE([ra mutableCopy]);
|
||||||
|
NSUInteger i;
|
||||||
|
|
||||||
for (i = 0; i < [r count]; i++)
|
for (i = 0; i < [r count]; i++)
|
||||||
{
|
{
|
||||||
NSMutableDictionary *md;
|
NSMutableDictionary *md;
|
||||||
|
NSObject *obj;
|
||||||
NSString *str;
|
NSString *str;
|
||||||
Regex *val;
|
Regex *val;
|
||||||
|
|
||||||
|
@ -344,6 +345,204 @@ replaceFields(NSDictionary *fields, NSString *template)
|
||||||
RELEASE(val);
|
RELEASE(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
str = [md objectForKey: @"ActiveFrom"];
|
||||||
|
if (nil != str)
|
||||||
|
{
|
||||||
|
NSDate *d = [NSDate dateWithString: str];
|
||||||
|
|
||||||
|
if (nil == d)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveFrom='%@' is not a valid date/time", str);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[md setObject: d forKey: @"ActiveFrom"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str = [md objectForKey: @"ActiveTo"];
|
||||||
|
if (nil != str)
|
||||||
|
{
|
||||||
|
NSDate *d = [NSDate dateWithString: str];
|
||||||
|
|
||||||
|
if (nil == d)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTo='%@' is not a valid date/time", str);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[md setObject: d forKey: @"ActiveTo"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str = [md objectForKey: @"ActiveTimezone"];
|
||||||
|
if (nil != str)
|
||||||
|
{
|
||||||
|
NSTimeZone *d = [NSTimeZone timeZoneWithName: str];
|
||||||
|
|
||||||
|
if (nil == d)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimezone='%@' is not a valid time zone", str);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
[md setObject: d forKey: @"ActiveTimeZone"];
|
||||||
|
}
|
||||||
|
obj = [md objectForKey: @"ActiveTimes"];
|
||||||
|
if ([obj isKindOfClass: [NSString class]])
|
||||||
|
{
|
||||||
|
obj = (NSString*)[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
obj, @"*", nil];
|
||||||
|
}
|
||||||
|
if ([obj isKindOfClass: [NSDictionary class]])
|
||||||
|
{
|
||||||
|
NSMutableDictionary *t = [[obj mutableCopy] autorelease];
|
||||||
|
NSEnumerator *e = [[t allKeys] objectEnumerator];
|
||||||
|
|
||||||
|
while (nil != (str = [e nextObject]))
|
||||||
|
{
|
||||||
|
NSString *k = [str stringByTrimmingSpaces];
|
||||||
|
NSMutableArray *a;
|
||||||
|
NSUInteger j;
|
||||||
|
NSInteger lastMinute = 0;
|
||||||
|
|
||||||
|
if (YES == [k isEqual: @"*"])
|
||||||
|
{
|
||||||
|
k = @"*";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Monday"])
|
||||||
|
{
|
||||||
|
k = @"Monday";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Tuesday"])
|
||||||
|
{
|
||||||
|
k = @"Tuesday";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Wednesday"])
|
||||||
|
{
|
||||||
|
k = @"Wednesday";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Thursday"])
|
||||||
|
{
|
||||||
|
k = @"Thursday";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Friday"])
|
||||||
|
{
|
||||||
|
k = @"Friday";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Saturday"])
|
||||||
|
{
|
||||||
|
k = @"Saturday";
|
||||||
|
}
|
||||||
|
else if (YES == [k caseInsensitiveCompare: @"Sunday"])
|
||||||
|
{
|
||||||
|
k = @"Sunday";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with bad day of week", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
a = [[[[t objectForKey: str] componentsSeparatedByString: @","]
|
||||||
|
mutableCopy] autorelease];
|
||||||
|
j = [a count];
|
||||||
|
while (j-- > 0)
|
||||||
|
{
|
||||||
|
NSMutableArray *r;
|
||||||
|
int from;
|
||||||
|
int to;
|
||||||
|
int h;
|
||||||
|
int m;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
str = [[a objectAtIndex: j] stringByTrimmingSpaces];
|
||||||
|
if ([str length] == 0)
|
||||||
|
{
|
||||||
|
[a removeObjectAtIndex: j];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
r = [[[str componentsSeparatedByString: @"-"]
|
||||||
|
mutableCopy] autorelease];
|
||||||
|
if ([r count] != 2)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with missing '-' in time range",
|
||||||
|
obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
str = [r objectAtIndex: 0];
|
||||||
|
c = sscanf([str UTF8String], "%d:%d", &h, &m);
|
||||||
|
if (0 == c)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with missing HH:MM", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
if (1 != c) m = 0;
|
||||||
|
if (h < 0 || h > 23)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with hour out of range", obj);
|
||||||
|
}
|
||||||
|
if (m < 0 || m > 59)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with minute out of range", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
from = (h * 60) + m;
|
||||||
|
|
||||||
|
str = [r objectAtIndex: 1];
|
||||||
|
c = sscanf([str UTF8String], "%d:%d", &h, &m);
|
||||||
|
if (0 == c)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with missing HH:MM", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
if (1 != c) m = 0;
|
||||||
|
if (h < 0 || h > 24 || (24 == h && 0 != m))
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with hour out of range", obj);
|
||||||
|
}
|
||||||
|
if (m < 0 || m > 59)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with minute out of range", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
if (0 == h && 0 == m)
|
||||||
|
{
|
||||||
|
h = 24;
|
||||||
|
}
|
||||||
|
to = (h * 60) + m;
|
||||||
|
|
||||||
|
if (to <= from)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' range end earlier than start",
|
||||||
|
obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
if (from < lastMinute)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' range start earlier than"
|
||||||
|
@" preceding one", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
lastMinute = to;
|
||||||
|
[r replaceObjectAtIndex: 0
|
||||||
|
withObject: [NSNumber numberWithInt: from]];
|
||||||
|
[r replaceObjectAtIndex: 1
|
||||||
|
withObject: [NSNumber numberWithInt: to]];
|
||||||
|
[a replaceObjectAtIndex: j withObject: r];
|
||||||
|
}
|
||||||
|
if (0 == [a count])
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' with empty time range", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
[t setObject: a forKey: k];
|
||||||
|
}
|
||||||
|
[md setObject: obj forKey: @"ActiveTimes"];
|
||||||
|
}
|
||||||
|
else if (obj != nil)
|
||||||
|
{
|
||||||
|
NSLog(@"ActiveTimes='%@' is not valid", obj);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASSIGN(rules, r);
|
ASSIGN(rules, r);
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -440,12 +639,17 @@ replaceFields(NSDictionary *fields, NSString *template)
|
||||||
- (void) applyRules: (NSArray*)rulesArray
|
- (void) applyRules: (NSArray*)rulesArray
|
||||||
toEvent: (EcAlerterEvent*)event
|
toEvent: (EcAlerterEvent*)event
|
||||||
{
|
{
|
||||||
CREATE_AUTORELEASE_POOL(pool);
|
NSAutoreleasePool *pool = nil;
|
||||||
BOOL found = NO;
|
NSTimeZone *tz = nil;
|
||||||
NSUInteger i;
|
BOOL found = NO;
|
||||||
|
NSCalendarDate *now = [NSCalendarDate date];
|
||||||
|
NSUInteger minuteOfDay = 0;
|
||||||
|
NSUInteger dayOfWeek = 0;
|
||||||
|
NSUInteger i;
|
||||||
|
|
||||||
for (i = 0; i < [rulesArray count]; i++)
|
for (i = 0; i < [rulesArray count]; i++)
|
||||||
{
|
{
|
||||||
|
NSDictionary *times;
|
||||||
NSDictionary *d;
|
NSDictionary *d;
|
||||||
NSString *match = nil;
|
NSString *match = nil;
|
||||||
Regex *e;
|
Regex *e;
|
||||||
|
@ -456,6 +660,80 @@ replaceFields(NSDictionary *fields, NSString *template)
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
d = [rulesArray objectAtIndex: i];
|
d = [rulesArray objectAtIndex: i];
|
||||||
|
|
||||||
|
times = [d objectForKey: @"ActiveTimes"];
|
||||||
|
if (nil != times)
|
||||||
|
{
|
||||||
|
NSDate *from = [d objectForKey: @"ActiveFrom"];
|
||||||
|
NSDate *to = [d objectForKey: @"ActiveTo"];
|
||||||
|
BOOL match = NO;
|
||||||
|
|
||||||
|
if ((nil == from || [from earlierDate: now] == from)
|
||||||
|
&& (nil == to || [to laterDate: now] == to))
|
||||||
|
{
|
||||||
|
NSTimeZone *z = [d objectForKey: @"ActiveTimezone"];
|
||||||
|
NSArray *ranges;
|
||||||
|
NSUInteger index;
|
||||||
|
|
||||||
|
if (nil == z)
|
||||||
|
{
|
||||||
|
static NSTimeZone *gmt = nil;
|
||||||
|
|
||||||
|
if (nil == gmt)
|
||||||
|
{
|
||||||
|
gmt = [[NSTimeZone timeZoneWithName: @"GMT"] retain];
|
||||||
|
}
|
||||||
|
z = gmt;
|
||||||
|
}
|
||||||
|
if (NO == [z isEqual: tz])
|
||||||
|
{
|
||||||
|
ASSIGN(tz, z);
|
||||||
|
[now setTimeZone: tz];
|
||||||
|
minuteOfDay = [now hourOfDay] * 60 + [now minuteOfHour];
|
||||||
|
dayOfWeek = [now dayOfWeek];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dayOfWeek)
|
||||||
|
{
|
||||||
|
case 0: ranges = [times objectForKey: @"Sunday"]; break;
|
||||||
|
case 1: ranges = [times objectForKey: @"Monday"]; break;
|
||||||
|
case 2: ranges = [times objectForKey: @"Tuesday"]; break;
|
||||||
|
case 3: ranges = [times objectForKey: @"Wednesday"]; break;
|
||||||
|
case 4: ranges = [times objectForKey: @"Thursday"]; break;
|
||||||
|
case 5: ranges = [times objectForKey: @"Friday"]; break;
|
||||||
|
default: ranges = [times objectForKey: @"Saturday"]; break;
|
||||||
|
}
|
||||||
|
if (nil == ranges)
|
||||||
|
{
|
||||||
|
ranges = [times objectForKey: @"*"];
|
||||||
|
}
|
||||||
|
index = [ranges count];
|
||||||
|
while (index-- > 0)
|
||||||
|
{
|
||||||
|
NSArray *range;
|
||||||
|
NSUInteger start;
|
||||||
|
|
||||||
|
range = [ranges objectAtIndex: index];
|
||||||
|
start = [[range objectAtIndex: 0] unsignedIntegerValue];
|
||||||
|
|
||||||
|
if (minuteOfDay >= start)
|
||||||
|
{
|
||||||
|
NSUInteger end;
|
||||||
|
|
||||||
|
end = [[range objectAtIndex: 1] unsignedIntegerValue];
|
||||||
|
if (minuteOfDay < end)
|
||||||
|
{
|
||||||
|
match = YES;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NO == match)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s = [d objectForKey: @"Tagged"];
|
s = [d objectForKey: @"Tagged"];
|
||||||
if (s != nil && NO == [s isEqual: [event->m objectForKey: @"Tag"]])
|
if (s != nil && NO == [s isEqual: [event->m objectForKey: @"Tag"]])
|
||||||
{
|
{
|
||||||
|
@ -816,6 +1094,7 @@ replaceFields(NSDictionary *fields, NSString *template)
|
||||||
NSLog(@"No match of %@ with %@", event->m, rulesArray);
|
NSLog(@"No match of %@ with %@", event->m, rulesArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DESTROY(tz);
|
||||||
RELEASE(pool);
|
RELEASE(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue