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

  17.07.06 ola     initial version
  23.08.06 ola     license changed
  -------------------------------------------------------------------------
  </pre>
*/
#include <FT/FTLogging.h>
#include <FT/FTDictionaryServiceTransactionStepImpl.h>
#include "FTDictionaryServiceForGraphImpl.h"

enum _operation_id_t {
  _OP_UNKNOWN = 0,
  _OP_SET,
  _OP_REMOVE
};


/**
 * definitions used for accessing variables within a transaction context
 */
#define __TRANS_CTX_NODE @"FTDictServ::node"
#define __TRANS_CTX_KEY @"FTDictServ::key"
#define __TRANS_CTX_OBJECT @"FTDictServ::object"
#define __TRANS_CTX_OPERATION @"FTDictServ::operation"
#define __TRANS_CTX_DICT_SERV_IMPL @"FTDictServ::dictServImpl"

#define __TRANS_CTX_OPERATION_SET @"FTDictServ::_OP_SET"
#define __TRANS_CTX_OPERATION_REMOVE @"FTDictServ::_OP_REMOVE"


@implementation FTDictionaryServiceTransactionStepImpl

+ (FTDictionaryServiceTransactionStepImpl *) transactionForOperationSETOfNode: 
  (id <FTNode>) aNode withKey: (id <NSCoding>) aKey 
  withObject: (id <NSCoding>) anObject 
  withDictionaryServiceGraphImpl:(FTDictionaryServiceForGraphImpl *)serviceImpl
  transactionContext: (FTTransactionContext *) context {
  
  [context addObject: aNode forKey: __TRANS_CTX_NODE];
  [context addObject: aKey forKey: __TRANS_CTX_KEY];
  [context addObject: anObject forKey: __TRANS_CTX_OBJECT];
  [context addObject: [NSNumber numberWithInt: _OP_SET] 
    forKey: __TRANS_CTX_OPERATION];
  [context addObject: serviceImpl forKey: __TRANS_CTX_DICT_SERV_IMPL];
  
  FTDictionaryServiceTransactionStepImpl *transaction =
    [[[FTDictionaryServiceTransactionStepImpl alloc] init] autorelease];
      
  return transaction;
}


+ (FTDictionaryServiceTransactionStepImpl *) transactionForOperationREMOVEOfNode: 
  (id <FTNode>) aNode withKey: (id <NSCoding>) aKey 
   withDictionaryServiceGraphImpl:(FTDictionaryServiceForGraphImpl *) serviceImpl
   transactionContext: (FTTransactionContext *) context {
   
  [context addObject: aNode forKey: __TRANS_CTX_NODE];
  [context addObject: aKey forKey: __TRANS_CTX_KEY];
  [context addObject: [NSNumber numberWithInt: _OP_REMOVE] 
    forKey: __TRANS_CTX_OPERATION];
  [context addObject: serviceImpl forKey: __TRANS_CTX_DICT_SERV_IMPL];
  
  FTDictionaryServiceTransactionStepImpl *transaction =
    [[[FTDictionaryServiceTransactionStepImpl alloc] init] autorelease];
    
  return transaction;
}


- (FTDictionaryServiceForGraphImpl *)
  dictServiceImplFromContext: (FTTransactionContext *) transactionContext {
  id toReturn = nil;

  toReturn = [transactionContext objectForKey: __TRANS_CTX_DICT_SERV_IMPL];

  if( nil == toReturn ) {
    [[FTLogging coreLog]
    fatal:@"FTDictionaryServiceTransactionStepImpl::dictServiceImplFromContext"\
        ": Unable to determine dict. service from current transaction context!"];
    [[[ECIllegalStateException alloc]
      initWithIllegalStateInfo: @"FTDictionaryServiceTransactionStepImpl::"\
        "dictServiceImplFromContext: Unable to determine dict. service from "\
        "current transaction context!"] 
      raise];
  }
  
  return (FTDictionaryServiceForGraphImpl *) toReturn;
}


- (id <NSCoding>)
  keyFromContext: (FTTransactionContext *) transactionContext {
  id toReturn = nil;

  toReturn = [transactionContext objectForKey: __TRANS_CTX_KEY];

  if( nil == toReturn ) {
    [[FTLogging coreLog]
      fatal: @"FTDictionaryServiceTransactionStepImpl::keyFromContext"\
        ": Unable to determine key from current transaction context!"];
    [[[ECIllegalStateException alloc]
      initWithIllegalStateInfo: @"FTDictionaryServiceTransactionStepImpl::"\
        "keyFromContext: Unable to determine key from current "\
        "transaction context!"]
      raise];
  }
  
  return (id <NSCoding>) toReturn;
}


- (id <FTNode>)
  nodeFromContext: (FTTransactionContext *) transactionContext {
  id toReturn = nil;

  toReturn = [transactionContext objectForKey: __TRANS_CTX_NODE];

  if( nil == toReturn ) {
    [[FTLogging coreLog]
      fatal: @"FTDictionaryServiceTransactionStepImpl::nodeFromContext"\
        ": Unable to determine node from current transaction context!"];
    [[[ECIllegalStateException alloc]
      initWithIllegalStateInfo: @"FTDictionaryServiceTransactionStepImpl::"\
        "nodeFromContext: Unable to determine node from current "\
        "transaction context!"]
      raise];
  }
  
  return (id <FTNode>) toReturn;
}


- (id <NSCoding>)
  objectFromContext: (FTTransactionContext *) transactionContext {
  id <FTNode> toReturn = nil;

  toReturn = [transactionContext objectForKey: __TRANS_CTX_OBJECT];

  if( nil == toReturn ) {
    [[FTLogging coreLog]
      fatal: @"FTDictionaryServiceTransactionStepImpl::objectFromContext"\
        ": Unable to determine object from current transaction context!"];
    [[[ECIllegalStateException alloc]
      initWithIllegalStateInfo: @"FTDictionaryServiceTransactionStepImpl::"\
        "objectFromContext: Unable to determine object from current "\
        "transaction context!"]
      raise];
  }
  
  return (id <NSCoding>) toReturn;
}


- (enum _operation_id_t) 
  operationIdFromContext: (FTTransactionContext *) transactionContext {
  enum _operation_id_t toReturn = _OP_UNKNOWN;
  id tmp;
  
  tmp = [transactionContext objectForKey: __TRANS_CTX_OPERATION];
  if( nil != tmp ) {
    toReturn = [((NSNumber *) tmp) intValue];
  }
  
  if( _OP_UNKNOWN == toReturn ) {
    [[FTLogging coreLog]
      fatal: @"FTDictionaryServiceTransactionStepImpl::operationIdFromContext"\
        ": Unable to determine operation from current transaction context!"];
    [[[ECIllegalStateException alloc]
      initWithIllegalStateInfo: @"FTDictionaryServiceTransactionStepImpl::"\
        "operationIdFromContext: Unable to determine operation from current "\
        "transaction context!"]
      raise];
  }
  
  return toReturn;
}


- (BOOL) performAction: (FTTransactionContext *) transactionContext {
  BOOL success = NO;
  enum _operation_id_t operationId;
  
  if( [[FTLogging coreLog] isTraceEnabled] ) {
    [[FTLogging coreLog] trace: @"FTDictionaryServiceTransactionStepImpl::"\
      "performAction"];
  }
  
  operationId = [self operationIdFromContext: transactionContext];
  
  switch( operationId ) {
    case _OP_SET:
      success = [self performActionSETWithContext: transactionContext];
      break;
      
    case _OP_REMOVE:
      success = [self performActionREMOVEWithContext: transactionContext];
      break;
      
    default:
      [[[ECIllegalStateException alloc]
        initWithIllegalStateInfo: 
          @"FTDictionaryServiceTransactionStepImpl::performAction: UNKNOWN"\
          " operationId given"]
        raise];
      break;
  }
  
  return success;
}


- (BOOL) performActionREMOVEWithContext: (FTTransactionContext *) context {
  id <FTNode> node;
  id <NSCoding> key;
  FTDictionaryServiceForGraphImpl *dictService;

  if( [[FTLogging coreLog] isTraceEnabled] ) {
    [[FTLogging coreLog] trace: @"FTDictionaryServiceTransactionStepImpl::"\
      "performAction: operation=REMOVE"];
  }
  
  node = [self nodeFromContext: context];
  key = [self keyFromContext: context];
  dictService = [self dictServiceImplFromContext: context];
  
  [dictService 
    removeObjectForKey: key
    ofNode: node];

  return YES;
}


- (BOOL) performActionSETWithContext: (FTTransactionContext *) context {
  id <FTNode> node;
  id <NSCoding> key;
  id <NSCoding> object;
  FTDictionaryServiceForGraphImpl *dictService;
  
  if( [[FTLogging coreLog] isTraceEnabled] ) {
    [[FTLogging coreLog] trace: @"FTDictionaryServiceTransactionStepImpl::"\
      "performActionSETWithContext"];
  }

  node = [self nodeFromContext: context];
  key = [self keyFromContext: context];
  object = [self objectFromContext: context];
  dictService = [self dictServiceImplFromContext: context];
  
  [dictService 
    addObject: object
    forKey: key
    forNode: node];
    
  return YES;
}


- (BOOL) undoAction: (FTTransactionContext *) transactionContext {
  return YES;
}
@end
