/*****************************************************************************
FILE:               Oracle7Context.m
LANGUAGE:           Objective-C
SYSTEM:             GNUstep
USER-INTERFACE:     None
DESCRIPTION

    This class is the GNUstep/db context to the Oracle7 databases.
    Its implementation is based on the OCI v8, and should be compatible
    with, both Oracle7, Oracle8 and future Oracle9 databases.

AUTHORS
    <PJB> Pascal J. Bourguignon <pjb@imaginet.fr>
MODIFICATIONS
    1999/07/24 Creation.
BUGS
    - ...
LEGAL
    Written by:  Pascal J. Bourguignon <pjb@imaginet.fr>
    Funds from:  Orange Concept (http://www.orange-concept.com/)
    Date:        August 1999 - February 2000

    This file is part of the Oracle7 Adaptor, GNUstep Database Library.
    The Oracle7 Adaptor allows access to Oracle[678] databases from GDL.

    Copyright (C) 2000 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 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.,  59 Temple  Place, Suite  330, Boston,
    MA 02111-1307 USA
*****************************************************************************/

#include <Oracle7Context.h>
#include <Oracle7Context-ForFriends.h>
#include <Oracle7Channel.h>
#include <Oracle7Utilities.h>

#include <oci.h>
#include <O2CI7Context.h>


DECLARE_SYMBOL(Oracle7Context_eInvalidAdaptor)



@implementation Oracle7Context

// NSObject methods:


    -(id)init
    {
        [NSException raise:Oracle7Adaptor_eBadInitializer format:@""];
        return([self initWithAdaptor:nil]);
    }//init;


    -(void)dealloc
    {
       NSAssert(numOpenChannels==0,@"-[Oracle7Context dealloc] with numOpenChannels>0 should not occur since the channels retain the context!");
        [super dealloc];
    }//dealloc;



// EOAdaptorContext methods:


    -(id)initWithAdaptor:(EOAdaptor*)anAdaptor
    {
        self=[super initWithAdaptor:anAdaptor];
        if(self!=nil){
            if([anAdaptor isKindOfClass:[Oracle7Adaptor class]]){
                ociContext=nil;
                numOpenChannels=0;
            }else{
                [NSException raise:Oracle7Context_eInvalidAdaptor format:@""];
                return(nil);
            }
        }
        return(self);
    }//initWithAdaptor:;


    -(EOAdaptorChannel*)createAdaptorChannel
    {
        EOAdaptorChannel* result=[super createAdaptorChannel];
        return(result);
    }//createAdaptorChannel;



    -(BOOL)canNestTransactions
    {
        return(NO); // SEE: What can we do for nested transactions.
    }//canNestTransactions;


    -(BOOL)primaryBeginTransaction
    {
        if(ociContext==nil){
            [adaptor reportError:NSLocalizedStringFromTableInBundle(@"Must open a channel before commiting back a transaction.",@"Oracle7Context",Oracle7Utilities_Bundle(),@"Error Message.")];
            return(NO);
        }
        if([ociContext setAutoCommit:NO]){
            return(YES);
        }else{
            [adaptor reportError:[[ociContext errorMessages]
                            componentsJoinedByString:@"\n"]];
            return(NO);
        }
    }//primaryBeginTransaction;


    -(BOOL)primaryCommitTransaction
    {
        if(ociContext==nil){
            [adaptor reportError:NSLocalizedStringFromTableInBundle(@"Must open a channel before commiting back a transaction.",@"Oracle7Context",Oracle7Utilities_Bundle(),@"Error Message.")];
            return(NO);
        }
        if([ociContext transCommit]){
            return(YES);
        }else{
            [adaptor reportError:[[ociContext errorMessages]
                            componentsJoinedByString:@"\n"]];
            return(NO);
        }
    }//primaryCommitTransaction;


    -(BOOL)primaryRollbackTransaction
    {
        if(ociContext==nil){
            [adaptor reportError:NSLocalizedStringFromTableInBundle(@"Must open a channel before rolling back a transaction.",@"Oracle7Context",Oracle7Utilities_Bundle(),@"Error Message.")];
            return(NO);
        }
        if([ociContext transRollback]){
            return(YES);
        }else{
            [adaptor reportError:[[ociContext errorMessages]
                            componentsJoinedByString:@"\n"]];
            return(NO);
        }
    }//primaryRollbackTransaction;


// Oracle7Context methods:

    // None.


@end // Oracle7Context;

// -------------------------------------------------------------------------- //

@implementation Oracle7Context(ForFriends)
    

    -(NSString*)connectionString
    {
        NSDictionary* connDict=[adaptor connectionDictionary];
        NSString* username=[connDict objectForKey:Oracle7Adaptor_cdUsername];
        NSString* password=[connDict objectForKey:Oracle7Adaptor_cdPassword];
        NSString* serverid=[connDict objectForKey:Oracle7Adaptor_cdServerId];
        NSString* hostname=[connDict objectForKey:Oracle7Adaptor_cdHostMachine];
        
        if(hostname==nil){
            // SQL*Net v2 connection string
            return([NSString stringWithFormat:@"%@/%@@%@",
                             username,password,serverid]);
        }else{
            // SQL*Net v1 connection string
            return([NSString stringWithFormat:@"%@/%@@T:%@:%@",
                             username,password,hostname,serverid]);
        }
    }//connectionString;


    -(O2CI7Context*)createContext
    {
        if(numOpenChannels>0){
            NSAssert(ociContext!=nil,NSLocalizedStringFromTableInBundle(@"When there are already openChannels, ociContext should be non-nil.",@"Oracle7Context",Oracle7Utilities_Bundle(),@"Assertion: When it's the first openChannels, ociContext should be nil."));
            numOpenChannels++;
            return(ociContext);
        }
        NSAssert(ociContext==nil,NSLocalizedStringFromTableInBundle(@"When it's the first openChannels, ociContext should be nil.",@"Oracle7Context",Oracle7Utilities_Bundle(),@"Assertion: When it's the first openChannels, ociContext should be nil."));
        if([adaptor hasValidConnectionDictionary]){
            NSString* connection=[self connectionString];
            ociContext=[[O2CI7Context alloc]init];
            if([ociContext loginName:connection 
                           password:nil connectString:nil]){
                numOpenChannels++;
                return(ociContext);
            }else{
                [adaptor reportError:[[ociContext errorMessages]
                        componentsJoinedByString:@"\n"]];
                return(nil);
            }
        }else{
            [adaptor reportError:NSLocalizedStringFromTableInBundle(@"The connection dictionary is not valid. Cannot connect to the database.",@"Oracle7Context",Oracle7Utilities_Bundle(),@"Error Message.")];
            return(nil);
        }
    }//createContext;


    -(void)disposeContext:(O2CI7Context*)aContext
    {
        NSAssert(aContext==ociContext,@"closing channel should "
                @"pass back the same ociContext.");
        numOpenChannels--;
        if(numOpenChannels<=0){
            numOpenChannels=0;
            if(![ociContext logout]){
                [adaptor reportError:[[ociContext errorMessages]
                        componentsJoinedByString:@"\n"]];
            }
            [ociContext release];
            ociContext=nil;
        }
    }//disposeContext:;

@end // Oracle7Context(Private);


/*** Oracle7Context.m                 -- 2000-02-21 07:11:23 -- PJB ***/
