/* Copyright (C) 2002-2005 SKYRIX Software AG This file is part of SOPE. SOPE 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. SOPE 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 SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "SoObjCClass.h" #include "SoSelectorInvocation.h" #include #include #include "common.h" @implementation SoObjCClass - (id)initWithSoSuperClass:(SoClass *)_soClass class:(Class)_clazz { NSAssert(_clazz, @"missing ObjC class parameter !"); if ((self = [super initWithSoSuperClass:_soClass])) { self->clazz = _clazz; } return self; } - (id)initWithSoSuperClass:(SoClass *)_soClass { return [self initWithSoSuperClass:_soClass class:nil]; } - (void)rescanClass { NSMutableDictionary *prefixMap; NSEnumerator *e; NSString *methodName; prefixMap = [[NSMutableDictionary alloc] initWithCapacity:32]; [self debugWithFormat:@"scanning ObjC class %@ for SoObject methods ...", NSStringFromClass(self->clazz)]; e = [self->clazz methodNameEnumerator]; while ((methodName = [e nextObject])) { SoSelectorInvocation *invocation; NSString *methodPrefix; NSRange r; unsigned len; if ((len = [methodName length]) < 6) continue; r = [methodName rangeOfString:@"Action"]; if (r.length == 0) continue; /* eg: doItAction:abc: => doItAction */ methodPrefix = [methodName substringToIndex:(r.location + r.length)]; if (len > (r.location + r.length)) { /* something is beyond the xxxAction, *must* be followed by a colon */ if ([methodName characterAtIndex:(r.location + r.length)] != ':') continue; } [self debugWithFormat:@" found an action: %@", methodName]; if ((invocation = [prefixMap objectForKey:methodPrefix]) == nil) { invocation = [[SoSelectorInvocation alloc] init]; [prefixMap setObject:invocation forKey:methodPrefix]; [invocation release]; } [invocation addSelectorNamed:methodName]; } e = [prefixMap keyEnumerator]; while ((methodName = [e nextObject])) { SoSelectorInvocation *inv; NSString *slotName; slotName = [methodName hasSuffix:@"Action"] ? [methodName substringToIndex:([methodName length] - 6)] : methodName; inv = [prefixMap objectForKey:methodName]; [self setValue:inv forSlot:slotName]; } } /* factory */ - (id)instantiateObject { return [[[self->clazz alloc] init] autorelease]; } - (NSClassDescription *)soClassDescription { return [NSClassDescription classDescriptionForClass:self->clazz]; } - (NSString *)className { return NSStringFromClass(self->clazz); } - (Class)objcClass { return self->clazz; } /* description */ - (NSString *)description { NSMutableString *ms; ms = [NSMutableString stringWithCapacity:64]; [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass((Class)*(void**)self)]; if (self->soSuperClass) [ms appendFormat:@" super=0x%p", self->soSuperClass]; else [ms appendString:@" root"]; if (self->clazz) [ms appendFormat:@" objc=%@", NSStringFromClass(self->clazz)]; else [ms appendString:@" "]; if ([self->slots count] > 0) { [ms appendFormat:@" slots=%@", [[self->slots allKeys] componentsJoinedByString:@","]]; } [ms appendString:@">"]; return ms; } /* logging */ - (NSString *)loggingPrefix { return [NSString stringWithFormat:@"[so-objc-class:%@]", NSStringFromClass(self->clazz)]; } - (BOOL)isDebuggingEnabled { static int debugOn = -1; if (debugOn == -1) { debugOn = [[NSUserDefaults standardUserDefaults] boolForKey:@"SoObjCClassDebugEnabled"] ? 1 : 0; } return debugOn ? YES : NO; } @end /* SoObjCClass */