/* EOAttributeOrdering.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: EOAdaptor.m 1 2004-08-20 10:38:46Z znek $ #import "common.h" #import "EOAdaptor.h" #import "EOAdaptorChannel.h" #import "EOAdaptorContext.h" #import "EOAttribute.h" #import "EOFExceptions.h" #import "EOModel.h" #import "EOSQLExpression.h" @implementation EOAdaptor + (id)adaptorWithModel:(EOModel*)_model { /* Check first to see if the adaptor class exists in the running program by testing the existence of [_model adaptorClassName]. */ NSString *adaptorName = [_model adaptorName]; Class adaptorClass = NSClassFromString([_model adaptorClassName]); id adaptor; adaptor = adaptorClass ? AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]) : [self adaptorWithName:adaptorName]; [adaptor setModel:_model]; return adaptor; } + (NSArray *)adaptorSearchPathes { // TODO: add support for Cocoa static NSArray *searchPathes = nil; NSDictionary *env; NSMutableArray *ma; id tmp; if (searchPathes != nil) return searchPathes; env = [[NSProcessInfo processInfo] environment]; ma = [NSMutableArray arrayWithCapacity:8]; if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil) tmp = [env objectForKey:@"GNUSTEP_PATHLIST"]; tmp = [tmp componentsSeparatedByString:@":"]; if ([tmp count] > 0) { NSEnumerator *e; e = [tmp objectEnumerator]; while ((tmp = [e nextObject])) { tmp = [tmp stringByAppendingPathComponent:@"Library/GDLAdaptors-1.1"]; if (![ma containsObject:tmp]) [ma addObject:tmp]; } } else { NSLog(@"%s: empty library search path !", __PRETTY_FUNCTION__); } searchPathes = [ma copy]; return searchPathes; } + (id)adaptorWithName:(NSString *)adaptorName { int i, count; NSBundle *bundle; NSString *adaptorBundlePath = nil; Class adaptorClass = Nil; bundle = [NSBundle mainBundle]; /* Check error */ if ((adaptorName == nil) || [adaptorName isEqual:@""]) return nil; /* Look in application bundle */ bundle = [NSBundle mainBundle]; adaptorBundlePath = [bundle pathForResource:adaptorName ofType:@"gdladaptor"]; /* Look in standard paths */ if (adaptorBundlePath == nil) { NSFileManager *fm; NSString *dirname; NSArray *paths; fm = [NSFileManager defaultManager]; paths = [self adaptorSearchPathes]; dirname = [adaptorName stringByAppendingPathExtension:@"gdladaptor"]; /* Loop through the paths and check each one */ for (i = 0, count = [paths count]; i < count; i++) { NSString *p; BOOL isDir; p = [[paths objectAtIndex:i] stringByAppendingPathComponent:dirname]; if (![fm fileExistsAtPath:p isDirectory:&isDir]) continue; if (!isDir) continue; adaptorBundlePath = p; break; } } /* Make adaptor bundle */ bundle = adaptorBundlePath ? [NSBundle bundleWithPath:adaptorBundlePath] : nil; /* Check bundle */ if (bundle == nil) { NSLog(@"Cannot find adaptor bundle '%@'", adaptorName); #if 0 [[[[CannotFindAdaptorBundleException alloc] initWithFormat:@"Cannot find adaptor bundle '%@'", adaptorName] autorelease] raise]; #endif return nil; } /* load bundle */ if (![bundle load]) { NSLog(@"Cannot load adaptor bundle '%@'", adaptorName); #if 1 [[[[InvalidAdaptorBundleException alloc] initWithFormat:@"Cannot load adaptor bundle '%@'", adaptorName] autorelease] raise]; #endif return nil; } /* Get the adaptor bundle "infoDictionary", and pricipal class, ie. the adaptor class. Other info about the adaptor should be put in the bundle's "Info.plist" file (property list format - see NSBundle class documentation for details about reserved keys in this dictionary property list containing one entry whose key is adaptorClassName. It identifies the actual adaptor class from the bundle. */ adaptorClass = [bundle principalClass]; if (adaptorClass == Nil) { NSLog(@"The adaptor bundle '%@' at '%@' doesn't contain " @"a principal class (infoDict=%@)", adaptorName, [bundle bundlePath], [bundle infoDictionary]); [[[InvalidAdaptorBundleException alloc] initWithFormat:@"The adaptor bundle '%@' doesn't contain " @"a principal class (infoDict=%@)", adaptorName, [bundle infoDictionary]] raise]; } return AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]); } - (id)initWithName:(NSString*)_name { ASSIGN(self->name, _name); self->contexts = [[NSMutableArray allocWithZone:[self zone]] init]; return self; } - (void)dealloc { RELEASE(self->model); RELEASE(self->name); RELEASE(self->connectionDictionary); RELEASE(self->pkeyGeneratorDictionary); RELEASE(self->contexts); [super dealloc]; } /* accessors */ - (void)setConnectionDictionary:(NSDictionary*)_dictionary { if([self hasOpenChannels]) { [NSException raise:NSInvalidArgumentException format:@"Cannot set the connection dictionary " @"while the adaptor is connected!"]; } ASSIGN(self->connectionDictionary, _dictionary); [self->model setConnectionDictionary:_dictionary]; } - (NSDictionary *)connectionDictionary { return self->connectionDictionary; } - (BOOL)hasValidConnectionDictionary { return NO; } - (EOAdaptorContext*)createAdaptorContext { return AUTORELEASE([[[self adaptorContextClass] alloc] initWithAdaptor:self]); } - (NSArray *)contexts { NSMutableArray *ma; unsigned i, count; if ((count = [self->contexts count]) == 0) return nil; ma = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [ma addObject:[[self->contexts objectAtIndex:i] nonretainedObjectValue]]; return ma; } /* Setting pkey generation info */ - (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary { ASSIGN(self->pkeyGeneratorDictionary, aDictionary); [self->model setPkeyGeneratorDictionary:aDictionary]; } - (NSDictionary*)pkeyGeneratorDictionary { return self->pkeyGeneratorDictionary; } // notifications - (void)contextDidInit:aContext { [self->contexts addObject:[NSValue valueWithNonretainedObject:aContext]]; } - (void)contextWillDealloc:aContext { int i; for (i = [contexts count]-1; i >= 0; i--) { if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aContext) { [contexts removeObjectAtIndex:i]; break; } } } - (BOOL)hasOpenChannels { int i; for (i = [contexts count] - 1; i >= 0; i--) { EOAdaptorContext* ctx = [[contexts objectAtIndex:i] nonretainedObjectValue]; if ([ctx hasOpenChannels]) return YES; } return NO; } - (id)formatAttribute:(EOAttribute *)_attribute { return [_attribute expressionValueForContext:nil]; } - (id)formatValue:(id)_value forAttribute:(EOAttribute *)attribute { if (_value == nil) _value = [NSNull null]; return [_value expressionValueForContext:nil]; } - (void)reportError:(NSString*)error { if(delegateWillReportError) { if([delegate adaptor:self willReportError:error] == NO) return; } NSLog(@"%@ adaptor error: %@", name, error); } - (void)setDelegate:(id)_delegate { self->delegate = _delegate; self->delegateWillReportError = [self->delegate respondsToSelector: @selector(adaptor:willReportError:)]; } - (void)setModel:(EOModel *)_model { ASSIGN(self->model, _model); [self setConnectionDictionary:[_model connectionDictionary]]; [self setPkeyGeneratorDictionary:[_model pkeyGeneratorDictionary]]; } - (EOModel *)model { return self->model; } - (NSString *)name { return self->name; } - (Class)expressionClass { return [EOSQLExpression class]; } - (Class)adaptorContextClass { return [EOAdaptorContext class]; } - (Class)adaptorChannelClass { return [EOAdaptorChannel class]; } - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr { return YES; } - (BOOL)isValidQualifierType:(NSString*)typeName { return NO; } - (id)delegate { return self->delegate; } // description - (NSString *)description { return [NSString stringWithFormat: @"<%@[0x%08X]: name=%@ " @"model=%s connection-dict=%s>", NSStringFromClass([self class]), self, [self name], [self model] ? "yes" : "no", [self connectionDictionary] ? "yes" : "no"]; } @end /* EOAdaptor */ @implementation EOAdaptor(EOF2Additions) - (BOOL)canServiceModel:(EOModel *)_model { return YES; } @end