mirror of
https://github.com/gnustep/libs-ec.git
synced 2025-02-16 00:21:01 +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,
|
||||
* any message text will match.
|
||||
* </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>
|
||||
* <desc>A boolean (YES or NO) saying whether rule matching should
|
||||
* 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
|
||||
{
|
||||
NSUInteger i = 0;
|
||||
NSMutableArray *r = AUTORELEASE([ra mutableCopy]);
|
||||
NSUInteger i;
|
||||
|
||||
for (i = 0; i < [r count]; i++)
|
||||
{
|
||||
NSMutableDictionary *md;
|
||||
NSObject *obj;
|
||||
NSString *str;
|
||||
Regex *val;
|
||||
|
||||
|
@ -344,6 +345,204 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
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);
|
||||
return YES;
|
||||
|
@ -440,12 +639,17 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
- (void) applyRules: (NSArray*)rulesArray
|
||||
toEvent: (EcAlerterEvent*)event
|
||||
{
|
||||
CREATE_AUTORELEASE_POOL(pool);
|
||||
BOOL found = NO;
|
||||
NSUInteger i;
|
||||
NSAutoreleasePool *pool = nil;
|
||||
NSTimeZone *tz = nil;
|
||||
BOOL found = NO;
|
||||
NSCalendarDate *now = [NSCalendarDate date];
|
||||
NSUInteger minuteOfDay = 0;
|
||||
NSUInteger dayOfWeek = 0;
|
||||
NSUInteger i;
|
||||
|
||||
for (i = 0; i < [rulesArray count]; i++)
|
||||
{
|
||||
NSDictionary *times;
|
||||
NSDictionary *d;
|
||||
NSString *match = nil;
|
||||
Regex *e;
|
||||
|
@ -456,6 +660,80 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
pool = [NSAutoreleasePool new];
|
||||
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"];
|
||||
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);
|
||||
}
|
||||
}
|
||||
DESTROY(tz);
|
||||
RELEASE(pool);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue