/*!
@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