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

  <pre>
  -------------------------------------------------------------------------
  Modification history

  27.07.06 ola     initial version
  23.08.06 ola     license changed
  -------------------------------------------------------------------------
  </pre>
*/

#include <FTImport.h>
#include <FTImportDefaultXMLRule.h>
@implementation FTImport


+ (ECLogger *) log {
  return [ECLogging loggerForContext: @"FTImport"];
}


- init {
  self = [super init];
  
  self->login = nil;
  self->passwd = nil;
  self->targetGraphName = nil;
  self->sourceGraphName = nil;
  self->sourceBaseDirectory = nil;
  self->defaultRule = nil;

  self->output = [[ECStandardOutput alloc] init];
  
  return self;
}


- (void) dealloc {
  [self->login release];
  [self->passwd release];
  [self->targetGraphName release];
  [self->sourceGraphName release];
  [self->sourceBaseDirectory release];
  [self->output release];
  [self->defaultRule release];
  
  [super dealloc];
}


- (BOOL) cmdLineArgumentsOK {
  BOOL gotSourceGraphName = NO;
  BOOL gotSourceDirectory = NO;
  BOOL gotNewGraphname = NO;
  BOOL gotLogin = NO;
  BOOL gotPasswd = NO;
  NSString *arg;
  NSEnumerator *arguments = [[[NSProcessInfo processInfo] arguments]
    objectEnumerator];
  
  while( (arg = [arguments nextObject]) ) {
    if( [arg isEqualToString: @"-newGraphname"] ) {
      self->targetGraphName = [arguments nextObject];
      gotNewGraphname = YES;
      continue;
    } else if( [arg isEqualToString: @"-sourceGraphName"] ) {
      self->sourceGraphName = [arguments nextObject];
      gotSourceGraphName = YES;
      continue;
    } else if( [arg isEqualToString: @"-sourceBaseDirectory"] ) {
      self->sourceBaseDirectory = [arguments nextObject];
      gotSourceDirectory = YES;
      continue;
    } else if( [arg isEqualToString: @"-login"] ) {
      self->login = [arguments nextObject];
      gotLogin = YES;
      continue;
    } else if( [arg isEqualToString: @"-password"] ) {
      self->passwd = [arguments nextObject];
      gotPasswd = YES;
    }
  }
  
  return gotSourceDirectory && gotSourceDirectory && gotNewGraphname
    && gotLogin && gotPasswd && gotSourceGraphName ;
}


#define _argumentsOverview \
  @"\nCommand line parameters:\n"\
    "\t-configFile <FT config file>\n\t\tFT configuration file\n"\
    "\t-configFile <server config file>\n\t\tConfiguration file for the "\
      "server\n"\
    "\t-sourceGraphName <xml file>\n\t\tName of exported graph (physically the"\
      " name of the directory where the exported\n\t\tcontent relies in. This "\
      "directory is relative to <sourceBaseDirectory>\n"\
    "\t-sourceBaseDirectory <directory>\n\t\tBase directory from where to "\
      "start the import\n"\
    "\t-newGraphname <graphName>\n\t\tName of graph to be created during "\
      "import\n"\
    "\t-login <adminlogin>\n\t\tlogin account with sufficient rights\n"\
    "\t-password <passwd>\n\t\tpassword of the specified login"

- cmdLineArgumentsOverview {
  [self->output writeString:  _argumentsOverview];
  return self;
}


- (BOOL) fileSpecificationsOK {
  BOOL toReturn = NO;
  BOOL directoryExists;
  NSFileManager *fileMgr = [NSFileManager defaultManager];
  
  if( ![fileMgr 
    fileExistsAtPath: self->sourceBaseDirectory
    isDirectory: &directoryExists] ) {
    directoryExists = NO;
  }
  
  if( !directoryExists ) {
    [self->output
      writeString:
        [NSString 
          stringWithFormat: @"Source base directory does not exist: %@",
            self->sourceBaseDirectory]];
    
    toReturn = NO;
  } else {
    if( ![fileMgr
      fileExistsAtPath: 
        [NSString 
          stringWithFormat: @"%@/%@", 
            self->sourceBaseDirectory, self->sourceGraphName]] ) {
      [self->output 
        writeString:
          [NSString
            stringWithFormat: @"Source XML file does not exist: %@",
              self->sourceGraphName]];
      toReturn = NO;
    } else {
      toReturn = YES;
    }
  }
  
  return toReturn;
}


- (BOOL) graphDoesNotExist {
  BOOL toReturn = NO;
  
  EC_AUTORELEASEPOOL_BEGIN
  id <FTObjectToIdMapper> objectToIdMapper;
  id <FTGraphManager> graphManager;
  id <FTGraph> graph;
  
  objectToIdMapper = [[self session] defaultObjectToIdMapper];
  graphManager = [[self session] graphManager];
  
  graph = [graphManager 
    graphWithId:
      [objectToIdMapper 
        mapObject: self->targetGraphName]];
  
  if( nil != graph ) {
    [graph close];
    [self->output 
      writeString: 
        [NSString 
          stringWithFormat: @"Graph already exists with id=%@",
            self->targetGraphName]];
    toReturn = NO;
  } else {
    toReturn = YES;
  }
  EC_AUTORELEASEPOOL_END
  
  return toReturn;
}


- installParsingRule: (FTImportDefaultXMLRule *) aRule
  usingXMLControl: (ECXMLControl *) control {
  ECXMLControlRuleSelector *ruleSelector;
  ECXMLControlDelegateMessageRule *delegationRule;
  
  [control enableDefaultRules: NO];
  ruleSelector = [control ruleSelector];
  
  delegationRule = [[[ECXMLControlDelegateMessageRule alloc]
    initWithDelegationTarget: aRule
    selectorToCall: @selector(addGraphForEvent:)
    forXMLElementTypename: @"FTExport"] autorelease];

  [ruleSelector 
    addRule: delegationRule 
    forEvent: [ECXMLControlEvent eventId_elementStarted]];
  
  delegationRule = [[[ECXMLControlDelegateMessageRule alloc]
    initWithDelegationTarget: aRule
    selectorToCall: @selector(addNodeIdForEvent:)
    forXMLElementTypename: @"node"] autorelease];

  [ruleSelector 
    addRule: delegationRule 
    forEvent: [ECXMLControlEvent eventId_elementStarted]];
  
  delegationRule = [[[ECXMLControlDelegateMessageRule alloc]
    initWithDelegationTarget: aRule
    selectorToCall: @selector(addNodeReference:)
    forXMLElementTypename: @"reference"] autorelease];

  [ruleSelector 
    addRule: delegationRule 
    forEvent: [ECXMLControlEvent eventId_elementStarted]];

  delegationRule = [[[ECXMLControlDelegateMessageRule alloc]
    initWithDelegationTarget: aRule
    selectorToCall: @selector(addNodeReferenceList:)
    forXMLElementTypename: @"nodeReferenceList"] autorelease];

  [ruleSelector 
    addRule: delegationRule 
    forEvent: [ECXMLControlEvent eventId_elementStarted]];

  delegationRule = [[[ECXMLControlDelegateMessageRule alloc]
    initWithDelegationTarget: aRule
    selectorToCall: @selector(addServiceData:)
    forXMLElementTypename: @"nodeServiceData"] autorelease];

  [ruleSelector 
    addRule: delegationRule 
    forEvent: [ECXMLControlEvent eventId_elementStarted]];

  delegationRule = [[[ECXMLControlDelegateMessageRule alloc]
    initWithDelegationTarget: aRule
    selectorToCall: @selector(addServiceDataItem:)
    forXMLElementTypename: @"dataItem"] autorelease];

  [ruleSelector 
    addRule: delegationRule 
    forEvent: [ECXMLControlEvent eventId_elementStarted]];


  return self;
}


- (ECLogger *) log {
  return [FTImport log];
}


- run {
  NSString *sourceXMLFilename;
  ECXMLControl *xmlControl;
  NSArray *xmlFiles;
  int i;
  
  if( ![self fileSpecificationsOK] ) {
    return self;
  }
  
  [self startServerUsingLogin: self->login
    usingPassword: self->passwd];
  
  if( [[FTImport log] isInfoEnabled] ) {
    [[FTImport log]
      info: @"Server started. Now checking existence of graph..."];
  }
  
  if( ![self graphDoesNotExist] ) {
    return self;
  }
  
  NS_DURING

  EC_AUTORELEASEPOOL_BEGIN
  xmlFiles = [NSArray 
    arrayWithObjects: @"graph.xml", @"nodes.xml", @"references.xml",
      @"serviceData.xml", nil];
  
  self->defaultRule = [[FTImportDefaultXMLRule alloc] 
    initForImport: self];

  for( i = 0; i < [xmlFiles count]; i++ ) {
    EC_AUTORELEASEPOOL_BEGIN
    sourceXMLFilename = [NSString
      stringWithFormat: @"%@/%@/%@",
        self->sourceBaseDirectory, self->sourceGraphName,
        [xmlFiles objectAtIndex: i]];
      
    if( [[FTImport log] isInfoEnabled] ) {
      [[FTImport log]
        info: @"Interpreting source XML file: %@", sourceXMLFilename];
    }
  
    xmlControl = [[[ECXMLControl alloc]
      initWithContentsOfURL: 
        [[[NSURL alloc]
          initFileURLWithPath: sourceXMLFilename ]
          autorelease]] autorelease];
  
    [self 
      installParsingRule: self->defaultRule
      usingXMLControl: xmlControl];
  
    [xmlControl parseXML];
    
    EC_AUTORELEASEPOOL_END
  }
    
  EC_AUTORELEASEPOOL_END
  NS_HANDLER
    [self->defaultRule releaseResources];
    [self->defaultRule release];
    self->defaultRule = nil;
    [self closeSessionAndStopServer];

    [localException raise];
  NS_ENDHANDLER

  [self->defaultRule releaseResources];
  [self->defaultRule release];
  self->defaultRule = nil;
  [self closeSessionAndStopServer];

  return self;
}


- (NSString *) sourceBaseDirectory {
  return [NSString 
    stringWithFormat: @"%@/%@", self->sourceBaseDirectory,
      self->sourceGraphName];
}


- (NSString *) targetGraphName {
  return self->targetGraphName;
}
@end


int main( int argc, char *argv[] ) {
  EC_AUTORELEASEPOOL_BEGIN  
  FTImport *importTool;
  
  NSLog( @"FTImport Version %@", FTIMPORT_VERSION );
  importTool = [[[FTImport alloc] init] autorelease];
  
  [FTAbstractTool startTool: importTool];
  
  EC_AUTORELEASEPOOL_END
  
  exit( 0 );
}

