/*!
@header FTGraphVisitor
@abstract Module of FT
@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
16.06.06 ola initial version
23.08.06 ola license changed
-------------------------------------------------------------------------
*/
#include
#include
#include
#include
#include
#include
#include
@implementation FTGraphVisitor
+ (NSFileHandle *) createFile: (NSString *) filename {
int fh;
NSFileHandle *toReturn;
fh = creat( [filename cString], O_CREAT | O_TRUNC | O_WRONLY );
fchmod( fh, S_IRWXU );
toReturn = [[[NSFileHandle alloc]
initWithFileDescriptor: fh] autorelease];
return toReturn;
}
+ (void) writeXMLHeaderIntoFile: (NSFileHandle *) fileHandle
forGraphId: (NSString *) aGraphId
hasToCreateGraph: (BOOL) toCreateGraph
encoding: (int) anEncoding{
EC_AUTORELEASEPOOL_BEGIN
NSMutableString *currentLine;
currentLine = [[[NSMutableString alloc] init] autorelease];
[currentLine
appendFormat: @"\n\n"];
#if 0
[currentLine
appendFormat: @"\n\n"];
#endif
[currentLine
appendFormat: @"\n",
aGraphId, (YES == toCreateGraph ) ? @"YES" : @"NO"];
[fileHandle
writeData: [currentLine dataUsingEncoding: anEncoding]];
EC_AUTORELEASEPOOL_END
}
+ (void) writeXMLFooterIntoFile: (NSFileHandle *) fileHandle
encoding: (int) anEncoding {
[fileHandle
writeData: [@"\n" dataUsingEncoding: anEncoding]];
}
- initForSession: (id ) aSession
graphId: (id) aGraphId exportDirectory: (NSString *) dir
baseFilename: (NSString *) baseFilename
encoding: (int) anEncoding {
self = [super init];
self->session = [aSession retain];
self->graphIdString = [aGraphId retain];
self->exportDir = [dir retain];
self->baseExportFilename = [baseFilename retain];
self->graph = nil;
self->objectToIdMapper = nil;
self->graphManager = nil;
self->encoding = anEncoding;
self->blobFileIdCounter = 0;
return self;
}
- (void) dealloc {
[self->session release];
[self->graphIdString release];
[self->exportDir release];
[self->baseExportFilename release];
[super dealloc];
}
- exportContent {
EC_AUTORELEASEPOOL_BEGIN
id transaction;
if( [[FTExport log] isTraceEnabled] ) {
[[FTExport log]
trace: @"FTGraphVisitor::exportContent"];
}
self->objectToIdMapper = [self->session defaultObjectToIdMapper];
self->graphManager = [self->session graphManager];
if( [[FTExport log] isDebugEnabled] ) {
[[FTExport log] debug: @"FTGraphVisitor::exportContent: Looking for graph "\
"with id=\"%@\"", self->graphIdString];
}
transaction = [self->session
beginTransactionWithParent: nil
withSettings:nil];
self->graphId = [self->objectToIdMapper mapObject: self->graphIdString];
NS_DURING
self->graph = [self->graphManager graphWithId: self->graphId];
NS_HANDLER
[[FTExport log]
error: @"FTGraphVisitor::exportContent: Unable to fetch graph with id="\
"\"%@\"", self->graphIdString];
[localException raise];
NS_ENDHANDLER
if( [[FTExport log] isDebugEnabled] ) {
[[FTExport log] debug: @"FTGraphVisitor::exportContent: Got graph!"];
}
[[NSFileManager defaultManager]
createDirectoryAtPath:
[NSString stringWithFormat: @"%@/%@",
self->exportDir, self->baseExportFilename]
attributes: nil];
#if 1
[self exportGraphXml];
[self exportNodeIds];
#endif
[self olacheck];
EC_AUTORELEASEPOOL_END
return self;
}
- olacheck {
id graphIdMapper;
id nodeIterator;
id transaction;
graphIdMapper = [[graph objectToIdMapper] retain];
transaction = [self->session beginTransactionWithParent: nil
withSettings: nil];
nodeIterator = [self->graph nodeIterator];
while( [nodeIterator hasNext] ) {
id currentNode = [nodeIterator next];
id dictionary;
id allKeys;
dictionary = (id )
[currentNode serviceWithId: @"FTDictionaryService"];
allKeys = [dictionary allKeys];
}
return self;
}
/* name of overall XML file */
#define __graph_xml_file "%@/%@/graph.xml"
/* name of node id file: */
#define __node_ids_file "%@/%@/nodes.xml"
#define __node_refs_file "%@/%@/references.xml"
#define __node_blob_file "%@/%@/serviceData.xml"
- exportGraphXml {
EC_AUTORELEASEPOOL_BEGIN
NSFileHandle *fileHandle;
NS_DURING
fileHandle = [FTGraphVisitor createFile:
[NSString stringWithFormat: @__graph_xml_file,
self->exportDir, self->baseExportFilename]];
NS_HANDLER
[[FTExport log]
error: @"FTGraphVisitor::exportGraphXML: Unable to create overall XML "\
"fragment. Exception: %@", localException];
[fileHandle closeFile];
[localException raise];
NS_ENDHANDLER
NS_DURING
[FTGraphVisitor
writeXMLHeaderIntoFile: fileHandle
forGraphId: self->graphIdString
hasToCreateGraph: YES
encoding: self->encoding];
[FTGraphVisitor
writeXMLFooterIntoFile: fileHandle
encoding: self->encoding];
NS_HANDLER
[[FTExport log]
error: @"FTGraphVisitor::exportGraphXML: Error while creating header. "\
"Exception: %@", localException];
[fileHandle closeFile];
[localException raise];
NS_ENDHANDLER
[fileHandle closeFile];
EC_AUTORELEASEPOOL_END
return self;
}
- exportNodeIds {
EC_AUTORELEASEPOOL_BEGIN
id nodeIterator;
NSFileHandle *idsFileHandle, *refsFileHandle,
*blobFileHandle;
NS_DURING
idsFileHandle = [FTGraphVisitor createFile:
[NSString stringWithFormat: @__node_ids_file,
self->exportDir, self->baseExportFilename]];
refsFileHandle = [FTGraphVisitor createFile:
[NSString stringWithFormat: @__node_refs_file,
self->exportDir, self->baseExportFilename]];
blobFileHandle = [FTGraphVisitor createFile:
[NSString stringWithFormat: @__node_blob_file,
self->exportDir, self->baseExportFilename]];
NS_HANDLER
[[FTExport log]
error: @"FTGraphVisitor::exportNodeIds: error creating file:"\
" "__node_ids_file" Exception: %@", localException];
[localException raise];
NS_ENDHANDLER
[FTGraphVisitor
writeXMLHeaderIntoFile: idsFileHandle
forGraphId: self->graphIdString
hasToCreateGraph: NO
encoding: self->encoding];
[idsFileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
[FTGraphVisitor
writeXMLHeaderIntoFile: refsFileHandle
forGraphId: self->graphIdString
hasToCreateGraph: NO
encoding: self->encoding];
[refsFileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
[FTGraphVisitor
writeXMLHeaderIntoFile: blobFileHandle
forGraphId: self->graphIdString
hasToCreateGraph: NO
encoding: self->encoding];
[blobFileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
NS_DURING
id outgoingEdges;
id graphIdMapper;
graphIdMapper = [[graph objectToIdMapper] retain];
nodeIterator = [self->graph nodeIterator];
while( [nodeIterator hasNext] ) {
NSMutableString *currentLine;
id currentNode = [nodeIterator next];
currentLine = [[[NSMutableString alloc]
initWithFormat: @" \n",
[currentNode nodeId]] autorelease];
[idsFileHandle
writeData: [currentLine dataUsingEncoding: self->encoding]];
/* determine outgoing nodes: */
currentLine = [[[NSMutableString alloc]
initWithFormat: @" \n",
[currentNode nodeId]]
autorelease];
[refsFileHandle
writeData: [currentLine dataUsingEncoding: self->encoding]];
outgoingEdges = [currentNode outgoingEdges];
while( [outgoingEdges hasNext] ) {
id edge;
edge = [outgoingEdges next];
currentLine = [[[NSMutableString alloc]
initWithFormat: @" \n",
[[edge targetNode] nodeId],
[edge edgeId]] autorelease];
[refsFileHandle
writeData: [currentLine dataUsingEncoding: self->encoding]];
}
currentLine = [[[NSMutableString alloc]
initWithFormat: @" \n"] autorelease];
[refsFileHandle
writeData: [currentLine dataUsingEncoding: self->encoding]];
[self writeBlobEntriesOfNode: currentNode
usingFileHandle: blobFileHandle];
}
[idsFileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
[FTGraphVisitor
writeXMLFooterIntoFile: idsFileHandle
encoding: self->encoding];
[refsFileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
[FTGraphVisitor
writeXMLFooterIntoFile: refsFileHandle
encoding: self->encoding];
[blobFileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
[FTGraphVisitor
writeXMLFooterIntoFile: blobFileHandle
encoding: self->encoding];
NS_HANDLER
[[FTExport log]
error: @"FTGraphVisitor::exportNodeIds: Got exception while iterating "\
"through all nodes. Exception message: %@", localException];
[localException raise];
NS_ENDHANDLER
[idsFileHandle closeFile];
[refsFileHandle closeFile];
[blobFileHandle closeFile];
EC_AUTORELEASEPOOL_END
return self;
}
- writeBlobEntriesOfNode: (id ) node
usingFileHandle: (NSFileHandle *) fileHandle {
EC_AUTORELEASEPOOL_BEGIN
NSMutableString *currentLine;
id keyIterator;
id dictionaryService;
currentLine = [NSMutableString
stringWithFormat: @" \n", [node nodeId]];
[fileHandle
writeData: [currentLine dataUsingEncoding: self->encoding]];
dictionaryService = (id )
[node serviceWithId: @"FTDictionaryService"];
keyIterator = [dictionaryService allKeys];
while( [keyIterator hasNext] ) {
id key = [keyIterator next];
id value = [dictionaryService objectForKey: key];
if( [[FTExport log] isDebugEnabled] ) {
[[FTExport log] debug: @"FTGraphVisitor::writeBlobEntriesOfNode: "\
"Got a key of dictionary service: %@", key];
}
if( nil != key && nil != value ) {
NSString *filename;
filename = [self writeKey: key withValue: value];
[fileHandle
writeData:
[[NSString
stringWithFormat: @" \n", filename ]
dataUsingEncoding: self->encoding]];
}
}
[fileHandle
writeData: [@" \n" dataUsingEncoding: self->encoding]];
EC_AUTORELEASEPOOL_END
return self;
}
#define __blobdata_file @"%@/%@/blobdata-%u.obj"
- (NSString *) writeKey: (id ) aKey
withValue: (id ) value {
NSString *filename;
NSString *filenameEntry;
NSMutableData *data;
NSKeyedArchiver *archiver;
/* todo: use a more space friendly approach here... */
filenameEntry = [[NSString alloc]
initWithFormat: @"blobdata-%u.obj", ++(self->blobFileIdCounter)];
filename = [NSString
stringWithFormat: @"%@/%@/%@", self->exportDir,
self->baseExportFilename, filenameEntry ];
EC_AUTORELEASEPOOL_BEGIN
data = [[[NSMutableData alloc] init] autorelease];
archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData: data]
autorelease];
[archiver encodeObject: aKey forKey: @"key"];
[archiver encodeObject: value forKey: @"value"];
[archiver finishEncoding];
[data
writeToFile: filename
atomically: YES];
EC_AUTORELEASEPOOL_END
return [filenameEntry autorelease];
}
@end