/*! @header FTDefaultObjectToIdMapper @abstract Maps objects (usually strings) to identifier. @availability OS X, GNUstep @copyright 2004, 2005, 2006 Free Software Foundation, Inc. This library 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.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  -------------------------------------------------------------------------
  Modification history

  09.02.2005 ola     initial version
  23.08.2006 ola     license changed
  -------------------------------------------------------------------------
  
*/ #include #include #include #include #include #include @implementation FTDefaultObjectToIdMapper - initWithDatabaseName: (NSString *) aDatabaseName forServer: (FTServerImpl *) aServer { self = [super init]; self->database = nil; self->databaseName = [aDatabaseName retain]; self->insertLock = [[NSLock alloc] init]; self->server = [aServer retain]; return self; } - (void) dealloc { [self->server release]; if( nil != self->database ) { [self unmountDatabase]; } [self->insertLock release]; [self->databaseName release]; [super dealloc]; } - (BDBDatabaseConfig *) dbConfig { BDBDatabaseConfig * dbConfig = [[BDBDatabaseConfig alloc] init]; [dbConfig setDatabaseType: BDB_BTREE]; [dbConfig setBTreeRecordNumbering: YES]; [dbConfig setAllowDuplicates: NO]; return dbConfig; } - (id ) lookupObject: (id) toLookup { FTIdImpl *foundObject = nil; BDBDatabaseEntry *entryKey; BDBDatabaseEntry *entryValue; if( nil == self->database ) { [[[ECIllegalStateException alloc] initWithIllegalStateInfo: @"FTDefaultObjectToIdMapper::lookupObject: "\ "Database not mounted!" ] raise]; } EC_AUTORELEASEPOOL_BEGIN entryKey = [[[BDBDatabaseEntry alloc] initWithObject: toLookup] autorelease ]; entryValue = [[[BDBDatabaseEntry alloc] init] autorelease]; BDBOperationStatus operationStatus; operationStatus = BDB_STATUS_UNKNOWN; NS_DURING operationStatus = [database getEntryWithTransaction: nil key: entryKey data: entryValue ]; if( BDB_STATUS_SUCCESS == operationStatus ) { foundObject = (FTIdImpl *) ([[entryValue object] retain]); } NS_HANDLER if( [localException isKindOfClass: [BDBException class]] ) { BDBException *bdbException = (BDBException *) localException; FTInternalDatamanagementException *ex = [[FTInternalDatamanagementException alloc ] initWithBDBException: bdbException ]; [ex setCause: localException]; [ex raise]; } else { FTUnknownException *ex = [[FTUnknownException alloc] initWithContextInfo: @"While fetching a BDB entry" exception: localException ]; [ex setCause: localException]; [ex raise]; } NS_ENDHANDLER if( BDB_STATUS_SUCCESS != operationStatus ) { if( BDB_STATUS_NOTFOUND != operationStatus ) { // we're having an error [[[FTInternalDatamanagementException alloc] initWithOperationStatus: operationStatus] raise]; } } EC_AUTORELEASEPOOL_END return foundObject; } - (id ) mapObject: (NSString *) strObject { BDBDatabaseEntry *entryKey; BDBDatabaseEntry *entryValue; FTIdImpl *toReturn = nil; if( nil == self->database ) { [[[ECIllegalStateException alloc] initWithIllegalStateInfo: @"FTDefaultObjectToIdMapper::lookupObject: "\ "Database not mounted!" ] raise]; } EC_AUTORELEASEPOOL_BEGIN if( nil == strObject ) { [[[ECIllegalArgumentException alloc] initWithArgumentInfo: @"Given object equals nil"] raise]; } if( [strObject length] < 1 ) { [[[ECIllegalArgumentException alloc] initWithArgumentInfo: @"Given string contains no characters"] raise]; } NS_DURING [insertLock lock]; toReturn = (FTIdImpl *) [self lookupObject: strObject]; NS_HANDLER /** * release lock since we got an exception */ [insertLock unlock]; [localException raise]; NS_ENDHANDLER if( nil == toReturn ) { /* entry seems not to exist in db -> create new one. * At present we simply use the key as value. This may change in future... */ entryKey = [[[BDBDatabaseEntry alloc] initWithObject: strObject] autorelease ]; toReturn = [[FTIdImpl alloc] initWithString: strObject]; entryValue = [[[BDBDatabaseEntry alloc] initWithObject: toReturn] autorelease ]; NS_DURING BDBOperationStatus operationStatus; operationStatus = [database putEntryWithTransaction: nil key: entryKey value: entryValue ]; if( BDB_STATUS_SUCCESS != operationStatus ) { [[[FTInternalDatamanagementException alloc] initWithOperationStatus: operationStatus] raise]; } NS_HANDLER [insertLock unlock]; [localException raise]; NS_ENDHANDLER } [insertLock unlock]; EC_AUTORELEASEPOOL_END return [toReturn autorelease]; } - mountDatabase { BDBDatabaseConfig *dbConfig; EC_AUTORELEASEPOOL_BEGIN if( [[FTLogging coreLog] isDebugEnabled] ) { [[FTLogging coreLog] debug: @"FTDefaultObjectToIdMapper::mountDatabase: "\ "Opening database %@...", self->databaseName ]; } if( ![[NSFileManager defaultManager] fileExistsAtPath: self->databaseName] ) { NSMutableString *info = [[NSMutableString alloc] initWithFormat: @"FTDefaultObjectToIdMapper::setupDatabase: "\ "Database named %@ does not exist", self->databaseName]; [[[ECIllegalStateException alloc] initWithIllegalStateInfo: info] raise]; } dbConfig = [[self dbConfig] autorelease]; self->database = [BDBDatabase initWithFilename: self->databaseName databaseName: nil databaseConfig: dbConfig]; if( [[FTLogging coreLog] isDebugEnabled] ) { [[FTLogging coreLog] debug: @"FTDefaultObjectToIdMapper::mountDatabase: DONE" ]; } EC_AUTORELEASEPOOL_END return self; } - setupDatabase { BDBDatabaseConfig *dbConfig; EC_AUTORELEASEPOOL_BEGIN /** * does the file already exist? */ if( [[NSFileManager defaultManager] fileExistsAtPath: self->databaseName] ) { NSMutableString *info = [[NSMutableString alloc] initWithFormat: @"FTDefaultObjectToIdMapper::setupDatabase: "\ "Database named %@ already exists", self->databaseName]; [[[ECIllegalStateException alloc] initWithIllegalStateInfo: info] raise]; } if( [[FTLogging coreLog] isDebugEnabled] ) { [[FTLogging coreLog] debug: @"FTDefaultObjectToIdMapper::setupDatabase: "\ "Creating database %@...", self->databaseName ]; } dbConfig = [[self dbConfig] autorelease]; [dbConfig setAllowCreate: YES]; self->database = [BDBDatabase initWithFilename: self->databaseName databaseName: nil databaseConfig: dbConfig]; if( [[FTLogging coreLog] isDebugEnabled] ) { [[FTLogging coreLog] debug: @"FTDefaultObjectToIdMapper::setupDatabase: DONE" ]; } EC_AUTORELEASEPOOL_END return self; } - unmountDatabase { if( nil != self->database ) { NS_DURING [self->database close]; NS_HANDLER [self->database release]; self->database = nil; NS_ENDHANDLER } return self; } @end