/* 
   FakeAdaptor.m

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
   Date: 1996

   This file is part of the GNUstep Database Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; see the file COPYING.LIB.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSString.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSUtilities.h>

#include <extensions/NSException.h>
#include <extensions/exceptions/GeneralExceptions.h>

#include <eoaccess/EONull.h>
#include <eoaccess/EOGenericRecord.h>
#include <eoaccess/EOSQLExpression.h>
#include <eoaccess/EOModel.h>
#include <eoaccess/EOEntity.h>
#include <eoaccess/EOAttribute.h>
#include <eoaccess/EORelationship.h>
#include <eoaccess/EOEntity.h>

#include "FakeAdaptor.h"

@implementation FakeAdaptor

- initWithName:(NSString*)aName
{
    name = [aName retain];
    return self;
}

- (void)dealloc
{
    [contexts release];
    [connectionDictionary release];
    [model release];
    [name release];
    [super dealloc];
}

- retain
{
    return [super retain];
}

- (void)release
{
    [super release];
}

- (NSString *)name
{
    return name;
}

- (void)setConnectionDictionary:(NSDictionary*)aDictionary
{
    [connectionDictionary autorelease];
    connectionDictionary = [aDictionary retain];
}

- (NSDictionary*)connectionDictionary
{
    return connectionDictionary;
}

- (BOOL)hasValidConnectionDictionary
{
    return YES;
}

- (void)setModel:(EOModel*)aModel
{
    [model autorelease];
    model = [aModel retain];
}

- (EOModel*)model
{
    return model;
}

- (FakeAdaptorContext*)createAdaptorContext
{
    return [[[FakeAdaptorContext alloc] initWithAdaptor:(EOAdaptor*)self]
	      autorelease];
}

- (void)contextDidInit:aCtx
{
    [contexts addObject:[NSValue valueWithNonretainedObject:aCtx]];
}

- (void)contextWillDealloc:aCtx
{
    int i;
    
    for (i = [contexts count] - 1; i >=0; i--)
	if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aCtx) {
	    [contexts removeObjectAtIndex:i];
	    break;
	}
}

- (BOOL)hasOpenChannels
{
    int i;
    
    for (i = [contexts count] - 1; i >=0; i--) {
	id ctx = [[contexts objectAtIndex:i] nonretainedObjectValue];
	if ([ctx hasOpenChannels])
	    return YES;
    }
    return NO;
}

- (Class)expressionClass
{
    return [EOSQLExpression class];
}

- (BOOL)isValidQualifierType:(NSString*)aTypeName
{
    return YES;
}

- formatAttribute:(EOAttribute*)attribute
{
    return [attribute expressionValueForContext:nil];
}

- formatValue:value forAttribute:(EOAttribute*)attribute
{
    return [value expressionValueForContext:nil];
}

- (void)reportError:(NSString*)anError
{
    NSLog(@"%@: reports error: %@", [self name], anError);
}

@end /* FakeAdaptor */


@implementation FakeAdaptorContext

- initWithAdaptor:(EOAdaptor*)anAdaptor
{
    adaptor = [(FakeAdaptor*)anAdaptor retain];
    [adaptor contextDidInit:self];
    return self;
}

- (void)dealloc
{
    [adaptor contextWillDealloc:self];
    [adaptor release];
    [channels release];
    [super dealloc];
}

- (void)channelDidInit:aCtx
{
    [channels addObject:[NSValue valueWithNonretainedObject:aCtx]];
}

- (void)channelWillDealloc:aCtx
{
    int i;
    
    for (i = [channels count] - 1; i >=0; i--)
	if ([[channels objectAtIndex:i] nonretainedObjectValue] == aCtx) {
	    [channels removeObjectAtIndex:i];
	    break;
	}
}

- (FakeAdaptor*)adaptor
{
    return adaptor;
}

- (FakeAdaptorChannel*)createAdaptorChannel
{
    return [[[FakeAdaptorChannel alloc] initWithAdaptorContext:(id)self] 
	autorelease];
}

- (BOOL)hasOpenChannels
{
    int i;
    
    for (i = [channels count] - 1; i >=0; i--) {
	id ctx = [[channels objectAtIndex:i] nonretainedObjectValue];
	if ([ctx isOpen])
	    return YES;
    }
    return NO;
}

- (BOOL)hasBusyChannels
{
    int i;
    
    for (i = [channels count] - 1; i >=0; i--) {
	id ctx = [[channels objectAtIndex:i] nonretainedObjectValue];
	if ([ctx isFetchInProgress])
	    return YES;
    }
    return NO;
}

- setSuccessCount:(int)yn
{
    countSuccess = yn;
    return self;
}

- setFailCount:(int)yn
{
    countFailure = yn;
    return self;
}

- (BOOL)retCode
{
    if (countFailure > 0) {
	countFailure--;
	return NO;
    }
    if (countSuccess > 0) {
    	countSuccess--;
	return YES;
    }
    if (countFailure == 0 && countFailure == 0)
	return YES;
    else
	return NO;
}

- (BOOL)beginTransaction
{
    nestLevel++;
    return [self retCode];
}

- (BOOL)commitTransaction
{
    if (!nestLevel)
	THROW([[InternalInconsistencyException alloc] initWithFormat:
	    @"FakeAdaptor: No transaction in progress "
	    @"in [FakeAdaptor commitTransaction]",
	    self]);
    nestLevel--;
    return [self retCode];
}

- (BOOL)rollbackTransaction
{
    if (!nestLevel)
	THROW([[InternalInconsistencyException alloc] initWithFormat:
	    @"FakeAdaptor: No transaction in progress "
	    @"in [FakeAdaptor rollbackTransaction]",
	    self]);
    nestLevel--;
    return [self retCode];
}

- (BOOL)canNestTransactions
{
    return YES;
}

- (void)transactionDidBegin
{
    nestLevel++;
}

- (void)transactionDidCommit
{
    if (!nestLevel)
	THROW([[InternalInconsistencyException alloc] initWithFormat:
	    @"FakeAdaptor: No transaction in progress "
	    @"in [FakeAdaptor commitTransaction]",
	    self]);
    nestLevel--;
}

- (void)transactionDidRollback
{
    if (!nestLevel)
	THROW([[InternalInconsistencyException alloc] initWithFormat:
	    @"FakeAdaptor: No transaction in progress "
	    @"in [FakeAdaptor transactionDidRollback]",
	    self]);
    nestLevel--;
}

- (unsigned)transactionNestingLevel
{
    return nestLevel;
}

@end /* FakeAdaptorContext */


@implementation FakeAdaptorChannel

- initWithAdaptorContext:(FakeAdaptorContext*)aContext
{
    context = [aContext retain];
    [context channelDidInit:self];
    return self;
}

- (void)dealloc
{
    [context channelWillDealloc:self];
    [context release];
    [super dealloc];
}

- setSuccessCount:(int)yn
{
    countSuccess = yn;
    return self;
}

- setFailCount:(int)yn
{
    countFailure = yn;
    return self;
}

- (BOOL)retCode
{
    if (countFailure > 0) {
	countFailure--;
	return NO;
    }
    if (countSuccess > 0) {
    	countSuccess--;
	return YES;
    }
    if (countFailure == 0 && countFailure == 0)
	return YES;
    else
	return NO;
}

- (FakeAdaptorContext*)adaptorContext
{
    return context;
}

- (BOOL)isOpen
{
    return isOpen;
}

- (BOOL)openChannel
{
    return isOpen = [self retCode];
}

- (void)closeChannel
{
    isOpen = NO;
}

- (BOOL)insertRow:(NSDictionary*)aRow forEntity:(EOEntity*)anEntity
{
    return [self retCode];
}

- (BOOL)updateRow:(NSDictionary*)aRow 
  describedByQualifier:(EOQualifier*)aQualifier
{
    return [self retCode];
}

- (BOOL)deleteRowsDescribedByQualifier:(EOQualifier*)aQualifier
{
    return [self retCode];
}

- (BOOL)selectAttributes:(NSArray*)attributes
  describedByQualifier:(EOQualifier*)aQualifier
  fetchOrder:(NSArray*)aFetchOrder
  lock:(BOOL)aLockFlag
{
    return [self retCode];
}

- (NSArray*)describeResults
{
    return nil;
}

- (NSMutableDictionary*)fetchAttributes:(NSArray*)attributes 
  withZone:(NSZone*)zone
{
    return nil;
}

- (BOOL)isFetchInProgress
{
    return isFetchInProgress;
}

- (void)cancelFetch
{
    isFetchInProgress = NO;
}

- (BOOL)evaluateExpression:(NSString*)anExpression
{
    return [self retCode];
}

@end /* FakeAdaptorChannel */
