Subversion Repositories DevTools

Rev

Rev 2232 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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

#pragma warn -com
#include <LoggingMacros.h>
#pragma warn +com

#include <vcl.h>
#pragma hdrstop

#include "time.h"
#include "pcreposix.h"

#include "CopyIteration.h"
#include "DataModule.h"
#include "DefinedVariable.h"
#include "DefinedVariableTable.h"
#include "EvaluationContext.h"
#include "FieldExpression.h"
#include "FileCtrl.hpp"
#include "GenerationProperties.h"
#include "ICryptographicServerProxy.h"
#include "IHash.h"
#include "ImportTransactionParameters.h"
#include "InitProgress.h"
#include "IMessageDigest.h"
#include "ISecurityWrapperFactory.h"
#include "Iteration.h"
#include "IterationConfig.h"
#include "IXmlSchemaWrapperElement.h"
#include "Login.h"
#include "Main.h"
#include "ParameterScope.h"
#include "ProjectConfig.h"
#include "Registry.hpp"
#include "RunTests.h"
#include "ScenarioParameters.h"
#include "Sequence.h"
#include "SequenceCollection.h"
#include "TestDirectorImport.h"
#include "TestHosts.h"
#include "TestScenario.h"
#include "TestScenarioProperties.h"
#include "TestScenarioTemplate.h"
#include "TimeEstimate.h"
#include "TransactionFieldTemplate.h"
#include "TransactionConfig.h"
#include "TransactionSpecification.h"
#include "TransactionSpecificationValue.h"
#include "TransactionSpecificationValueKey.h"
#include "TransactionStream.h"
#include "TransactionTemplateCollection.h"
#include "UdDrainFile.h"
#include "Utilities.h"
#include <algorithm>
#include <ctype.h>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Grids_ts"
#pragma link "TSDBGrid"
#pragma link "TSGrid"
#pragma link "TXMLSchema"
#pragma link "AdvGrid"
#pragma link "BaseGrid"
#pragma link "DBAdvGrd"
#pragma link "DBAdvNavigator"
#pragma link "AdvPageControl"
#pragma link "AsgFindDialog"
#pragma link "DBAdvGrd"
#pragma link "DBAdvGrid"
#pragma resource "*.dfm"
TMainForm *MainForm;

#define TDBADVGRID_FIXED        0
#define INCLUDE_PARENTS         TDBADVGRID_FIXED

const char *TMainForm::g_headerStructure        = "SysHdr_t";
const int       TMainForm::g_messagePanel               = 0;

/**
 *      Process paint message.
 */
void ProcessPaintMessages( HWND Handle )
{
        MSG msg;
        while ( PeekMessage( &msg, Handle, WM_PAINT, WM_PAINT, PM_REMOVE ) )
        {
                DispatchMessage( &msg );
        }
}
//---------------------------------------------------------------------------

const bool __fastcall TMainForm::openSecurityFactory( const char * library )
{

        m_securityWrapper = ::LoadLibrary( library );
        if ( m_securityWrapper )
        {
                m_getSecurityWrapperFactory
                        = reinterpret_cast< getSecurityWrapperFactory_t >(
                                ::GetProcAddress(
                                        m_securityWrapper,
                                        "getSecurityWrapperFactory" ) );

                if ( m_getSecurityWrapperFactory )
                {
                        m_securityWrapperFactory = &m_getSecurityWrapperFactory();
                        if ( m_securityWrapperFactory )
                        {
                                return ( m_securityWrapperFactory->start() );
                        }
                }
        }

        return ( false );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::closeSecurityFactory()
{
        if ( m_securityWrapperFactory )
        {
                m_securityWrapperFactory->stop();
                m_securityWrapperFactory = 0;
        }
        m_getSecurityWrapperFactory = 0;
        if ( m_securityWrapper )
        {
                ::FreeLibrary( m_securityWrapper );
                m_securityWrapper = 0;
        }
}
//---------------------------------------------------------------------------

__fastcall TMainForm::TMainForm(TComponent* Owner)
:       TForm(Owner),
        m_progressBar( 0 ),
        m_securityWrapper( 0 ),
        m_getSecurityWrapperFactory( 0 ),
        m_securityWrapperFactory( 0 )
{
        TestCasesTabSheet->TabVisible = false;
        TestScenariosTabSheet->TabVisible = false;

        m_Registry = new TRegistry;
        m_Registry->RootKey = HKEY_CURRENT_USER;
        if (! m_Registry->OpenKey("\\Software\\ERG\\TxnTestManager", true) )
        {
                m_Registry->CloseKey();
                delete m_Registry;
                m_Registry = NULL;
        }

        m_progressBar = new ProgressBar( MainStatusBar );
        
        openSecurityFactory();
}
//---------------------------------------------------------------------------

__fastcall TMainForm::~TMainForm()
{
        closeSecurityFactory();

        delete m_progressBar;
        m_progressBar = 0;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ProjectConfigBtnClick(TObject *Sender)
{
        ProjectConfigForm->ShowModal();

        LoadProjectCombo();
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::IterationConfigBtnClick(TObject *Sender)
{
        if (!m_currentproject.IsEmpty())
        {
                IterationConfigForm->ShowForm(m_currentproject);

        ProjectsComboBoxChange(this);
    }
}
//---------------------------------------------------------------------------

void TMainForm::LoadProjectCombo()
{
    ProjectsComboBox->Clear();

        AnsiString      mru_project_code;

    if (m_Registry != NULL)
    {
            if (m_Registry->ValueExists("MRUProjectCode"))
        {
                mru_project_code = m_Registry->ReadString("MRUProjectCode");
        }
    }

        TADOQuery       *query = new TADOQuery(this);
        query->Connection = Data_Module->IntegrationDBConnection;

        AnsiString      sql_statement;
        sql_statement.sprintf("SELECT * FROM PROJECTS");
        query->SQL->Text = sql_statement;
        query->Open();

        int     mru_item_index = 0;
        int     i=0;
        while (!query->Eof)
        {
                AnsiString      name = query->FieldByName("NAME")->AsString;
                AnsiString      *code = new AnsiString(query->FieldByName("PROJECT_CODE")->AsString);

                if (*code == mru_project_code)
                {
                        mru_item_index = i;
                }

                ProjectsComboBox->AddItem(name, (TObject *)code);

                i++;
                query->Next();
        }

    ProjectsComboBox->ItemIndex = mru_item_index;
    ProjectsComboBoxChange(this);
}

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

void __fastcall TMainForm::FormShow(TObject *Sender)
{
#ifdef LOGGING_ACTIVE
    ProgrammerLogging::start("TxnTestManager.ini");
#endif

        if (LoginForm->ShowModal() == mrOk)
    {
        try
                {
                        // Initialise Startup TabSheets
                        TestsPageControl->ActivePage = TestCaseTabSheet;
                        TestParametersPageControl->ActivePage = IterationParametersTabSheet;

                        // Initialise the Database connection
                        Data_Module->IntegrationDBConnection->Connected = false;

                        AnsiString connectionString;
                        connectionString.sprintf( "Provider=OraOLEDB.Oracle.1;Data Source=%s", LoginForm->DatabaseEdit->Text );
                        Data_Module->IntegrationDBConnection->ConnectionString = connectionString;
                        Data_Module->IntegrationDBConnection->Open(LoginForm->UsernameEdit->Text, LoginForm->PasswordEdit->Text);
                        if (Data_Module->IntegrationDBConnection->Connected)
                        {
                                MASSTxnsQuery->Active = false;
                                TestCaseQuery->Active = false;
                                TestScenariosQuery->Active = false;
                                TxnSpecQuery->Active = false;
                                TxnValuesQuery->Active = false;
                                TxnHdrValuesQuery->Active = false;
                                IterationParamsQuery->Active = false;
                                SequenceGeneratorQuery->Active = false;

                                srand( static_cast< unsigned >( time( 0 ) ) );
                                int             first_rand_seed = rand();

                                srand( first_rand_seed << (first_rand_seed & 0x00FF) );
//              int             first_rand = rand();

                                // Locate the XML SWIS Schema
                                XMLSchema->Active = true;

                                vector<string>  schemas;
                                if (XMLSchema->GetSchemas(schemas))
                                {
                                        vector<string>::iterator        itr = schemas.begin();

                                        while (itr != schemas.end())
                                        {
                                                AnsiString              xml_schema = (*itr).c_str();

                                                if (xml_schema.Pos(MASSUDWriter) == 1)
                                                {
                                                        m_xml_schemas.push_back(xml_schema.c_str());
                                                }

                                                ++itr;
                                        }
                                }

                                if (m_xml_schemas.size() == 0)
                                {
                                        MessageDlg("Failed to locate any MASS UD Writer XMLs\n"
                                                           "Check XMLSchema.ini file",
                                                           mtError, TMsgDlgButtons() << mbOK, 0);
                                }

                                LoadProjectCombo();
                                IterationsComboBoxChange(Sender);
                        }
                        else
                        {
                                Close();
                        }
                }
                catch(...)
                {
                        Close();
        }
    }
    else
    {
                Close();
    }
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::LoadTestCaseNodes(TTreeNode *testcase_node)
{
        bool    initially_expanded = testcase_node->Expanded;

    TestCaseTreeView->Items->BeginUpdate();

        testcase_node->DeleteChildren();

    TADOQuery   *txnquery = new TADOQuery(this);
    txnquery->Connection = Data_Module->IntegrationDBConnection;

    AnsiString sql_statement;
    sql_statement.sprintf("SELECT MASS_TXNS.NAME,TRANSACTION_SPECIFICATION.TXNSPEC_NO "
                          "FROM MASS_TXNS,TRANSACTION_SPECIFICATION "
                          "WHERE TRANSACTION_SPECIFICATION.TESTSCENARIO_NO=%d "
                          "AND   MASS_TXNS.PROJECTCODE=TRANSACTION_SPECIFICATION.PROJECT_CODE "
                          "AND   MASS_TXNS.ITERATION=TRANSACTION_SPECIFICATION.ITERATION "
                          "AND   MASS_TXNS.UDTYPE=TRANSACTION_SPECIFICATION.UDTYPE "
                          "AND   MASS_TXNS.UDSUBTYPE=TRANSACTION_SPECIFICATION.UDSUBTYPE "
                          "ORDER BY TRANSACTION_SPECIFICATION.SEQ_NO",
                          (int)testcase_node->Data);
    txnquery->SQL->Text = sql_statement;
    txnquery->Open();
    while (!txnquery->Eof)
    {
        AnsiString  txnname     = txnquery->FieldByName("NAME")->AsString;
        int                     txnspec_no      = txnquery->FieldByName("TXNSPEC_NO")->AsInteger;

        TestCaseTreeView->Items->AddChildObject(testcase_node, txnname.c_str(), (TObject *)txnspec_no);

        txnquery->Next();
    }

    delete txnquery;

    if (initially_expanded)
    {
        testcase_node->Expand(true);
    }
    else
    {
            testcase_node->Collapse(true);
    }

    TestCaseTreeView->Items->EndUpdate();
}

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

void __fastcall TMainForm::EditTestCaseExecute(TObject *Sender)
{
        //
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewEnter(TObject *Sender)
{
        if (!TestScenariosTabSheet->TabVisible)
    {
                TestScenariosTabSheet->TabVisible = true;
        TestCasesTabSheet->TabVisible = false;
    }

    if ( (MainPageControl->ActivePage != TestScenariosTabSheet) &&
         (MainPageControl->ActivePage != ScenarioStepsTabSheet) )
    {
                MainPageControl->ActivePage = TestScenariosTabSheet;
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseQueryAfterPost(TDataSet *DataSet)
{
    if (TestCaseQuery->Active)
    {
        TestCaseQuery->Close();
    }
    
    TestCaseQuery->Open();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::loadLegacyHeaderValues( TransactionTemplateCollection & templates, const AnsiString & project, const int & iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "FIELDNAME,"
                                "FIELDVALUE "
                        "FROM "
                                "TXNHDR_VALUES "
                        "WHERE "
                                "PROJECT_CODE=\'%s\' AND "
                                "ITERATION=%d",
                        project.c_str(),
                        iteration );
                query->SQL->Text = sqlStatement;
                query->Open();

                AnsiString xpath;
                AnsiString value;
                while ( !query->Eof )
                {
                        value = query->FieldByName( "FIELDVALUE" )->AsString;
                        if ( !value.IsEmpty() )
                        {
                                if ( value[ 1 ] == '=' )
                                {
                                        value.Delete( 1, 1 );
                                }

                                if ( !value.IsEmpty() )
                                {
                                        switch ( value[ 1 ] )
                                        {
                                                case '@':
                                                        value[ 1 ] = '=';
                                                        if ( FieldExpression::isFunctor(
                                                                        value.c_str() + 1 ) )
                                                        {
                                                                value += "()";
                                                        }
                                                        break;
                                                default:
                                                        break;
                                        }
                                }
                        }

                        xpath.sprintf(
                                "/%s/%s",
                                g_headerStructure,
                                query->FieldByName( "FIELDNAME" )->AsString.c_str() );
                        templates.getTestScenario( 0 ).getField( xpath.c_str() ).
                                setValue( value.c_str() );
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::loadLegacyParameters( TransactionTemplateCollection & templates, const AnsiString & project, const int & iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "NAME,"
                                "FIELDVALUE,"
                                "TESTSCENARIO_NO "
                        "FROM "
                                "ITERATION_PARAMS "
                        "WHERE "
                                "PROJECT_CODE=\'%s\' AND "
                                "ITERATION=%d",
                        project.c_str(),
                        iteration );
                query->SQL->Text = sqlStatement;
                query->Open();

                AnsiString      fieldName;
                int                     scenario = 0;
                AnsiString xpath;
                AnsiString value;
                while ( !query->Eof )
                {
                        fieldName = query->FieldByName( "NAME" )->AsString;
                        scenario = query->FieldByName( "TESTSCENARIO_NO" )->AsInteger;

                        value = query->FieldByName( "FIELDVALUE" )->AsString;
                        if ( !value.IsEmpty() )
                        {
                                if ( value[ 1 ] == '=' )
                                {
                                        value.Delete( 1, 1 );
                                }

                                if ( !value.IsEmpty() )
                                {
                                        switch ( value[ 1 ] )
                                        {
                                                case '@':
                                                        value[ 1 ] = '=';
                                                        if ( FieldExpression::isFunctor(
                                                                        value.c_str() + 1 ) )
                                                        {
                                                                value += "()";
                                                        }
                                                        break;
                                                default:
                                                        break;
                                        }
                                }
                        }

                        if ( !fieldName.IsEmpty() )
                        {
                                switch ( fieldName[ 1 ] )
                                {
                                case '$':
                                        xpath.sprintf(
                                                ".*/%s",
                                                fieldName.c_str() + 1 );

                                        templates.getTestScenario( scenario ).getField( xpath.c_str() ).
                                                setValue( value.c_str() );
                                        break;
                                case '@':       // We don't worry about variables here.
                                        break;
                                default:
                                        break;
                                }
                        }
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionTemplates( TransactionTemplateCollection & templates, const AnsiString & project, const int & iteration )
{
        templates.clear();
        loadLegacyHeaderValues( templates, project, iteration );
        loadLegacyParameters( templates, project, iteration );

        // Now apply our current templates, which override the legacy templates.
}
//---------------------------------------------------------------------------

const bool __fastcall TMainForm::findSchema( std::string &              handle,
                                                                                         const AnsiString &     projectCode,
                                                                                         const int &            iteration )
{
        std::string     project;
        std::string     majorVersion;

        for ( std::vector< std::string >::const_iterator
                        where = m_xml_schemas.begin();
                  where != m_xml_schemas.end();
                  ++where )
        {
                if ( XMLSchema->GetAttributeProperty( *where, "project", project ) &&
                         ( projectCode == AnsiString( project.c_str() ).UpperCase() ) )
                {
                        if ( ( XMLSchema->GetAttributeProperty( *where, "majorversion", majorVersion ) ) &&
                                 ( iteration == atoi( majorVersion.c_str() ) ) )
                        {
                                handle = *where;
                                return ( true );
                        }
                }
        }
        handle.erase();

        return ( false );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::IterationsComboBoxChange(TObject *Sender)
{
        AnsiString      sql_statement;

        if ( IterationsComboBox->ItemIndex != -1 )
        {
                const int candidate = reinterpret_cast< int >(
                        IterationsComboBox
                                ->Items
                                        ->Objects[ IterationsComboBox->ItemIndex ] );
                if ( findSchema( m_schema_handle,
                                                 m_currentproject.UpperCase(),
                                                 candidate ) )
                {
                        m_currentiteration = candidate;
                        IterationCopyButton->Enabled = true;
                }
                else
                {
                        m_currentiteration = 0;
                        IterationsComboBox->ItemIndex = -1;
                        IterationCopyButton->Enabled = false;
                }
        }
        else
        {
                m_currentiteration = 0;
        }

    if (m_Registry != NULL)
    {
        m_Registry->WriteInteger("MRUProjectIteration", m_currentiteration);
    }

        buildTransactionTemplates( m_transactionTemplates, m_currentproject, m_currentiteration );
        ApplyTemplates->Enabled = ( m_transactionTemplates.getTemplateCount() > 0 );

        // Load the Project/Iterations MASS Txns
        MASSTxnsQuery->Close();
    sql_statement="";
    sql_statement.sprintf("SELECT * FROM MASS_TXNS WHERE PROJECTCODE='%s' AND ITERATION=%d ORDER BY NAME,UDTYPE,UDSUBTYPE",
                                                  m_currentproject.c_str(),
                                                  m_currentiteration);
    MASSTxnsQuery->SQL->Text = sql_statement;
        MASSTxnsQuery->Open();

        InitialiseMASSTxns();
        InitialiseCopyParametersTabSheet( Sender );

    // Refresh the TestCases
        if (TestCaseQuery->Active)
        {
                TestCaseQuery->Close();
        }
        TestCaseQuery->Open();

        // Load the Project/Iterations Iteration Parameters
        IterationParamsQuery->Close();
        sql_statement="";
        sql_statement.sprintf("SELECT * FROM ITERATION_PARAMS "
                                                  "WHERE PROJECT_CODE='%s' AND ITERATION=%d"
                                                  "AND TESTSCENARIO_NO IS NULL "
                                                  "ORDER BY NAME",
                                                  m_currentproject.c_str(),
                                                  m_currentiteration);
        IterationParamsQuery->SQL->Text = sql_statement;
        IterationParamsQuery->Open();

        SequenceGeneratorQuery->Close();
        sql_statement="";
        sql_statement.sprintf("SELECT * FROM SEQGEN "
                                                  "WHERE PROJECT_CODE='%s' AND ITERATION=%d"
                                                  "ORDER BY SEQNAME",
                                                  m_currentproject.c_str(),
                                                  m_currentiteration);
        SequenceGeneratorQuery->SQL->Text = sql_statement;
        SequenceGeneratorQuery->Open();

#if 0
        //
        if ( TestScenariosQuery->Active )
        {
                TestScenariosQuery->Close();
        }
        sql_statement="";
        sql_statement.sprintf("SELECT * FROM TEST_SCENARIOS "
                                                  "WHERE PROJECT_CODE='%s' AND ITERATION=%d"
                                                  "ORDER BY TESTCASE_ID",
                                                  Utilities::EscapeString( m_currentproject ).c_str(),
                                                  m_currentiteration);
        TestScenariosQuery->SQL->Text = sql_statement;
        TestScenariosQuery->Open();
#endif

    // Load the Project/Iterations TXNHDR Parameters
    TxnHdrValuesQuery->Close();
    sql_statement="";
    sql_statement.sprintf("SELECT * FROM TXNHDR_VALUES "
                                          "WHERE PROJECT_CODE='%s' AND ITERATION=%d",
                                                  m_currentproject.c_str(),
                                                  m_currentiteration);
        TxnHdrValuesQuery->SQL->Text = sql_statement;
        TxnHdrValuesQuery->Open();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ProjectsComboBoxChange(TObject *Sender)
{
    TADOQuery   *query = new TADOQuery(this);
    AnsiString  sql_statement;

        IterationsComboBox->Clear();

    // Close our dependent queries
    if (TestCaseQuery->Active)
    {
        TestCaseQuery->Close();
    }
        TestCaseTreeView->Items->Clear();

        if ( ProjectsComboBox->ItemIndex != -1 )
        {
                m_currentproject = *(AnsiString *)(ProjectsComboBox->Items->Objects[ProjectsComboBox->ItemIndex]);
        }

    if (m_Registry != NULL)
    {
                m_Registry->WriteString("MRUProjectCode", m_currentproject);
    }

    query->Connection = Data_Module->IntegrationDBConnection;

    sql_statement="";
    sql_statement.sprintf("SELECT TESTTEAM_CODE FROM PROJECTS WHERE PROJECT_CODE='%s'",
                                                  m_currentproject.c_str() );
    query->SQL->Text = sql_statement;

    query->Open();
    m_testteamcode = query->FieldByName("TESTTEAM_CODE")->AsString;
        query->Close();

    sql_statement="";
    sql_statement.sprintf("SELECT * FROM ITERATIONS WHERE PROJECT_CODE='%s' ORDER BY ITERATION",
                          m_currentproject.c_str() );

    query->SQL->Text = sql_statement;

    query->Open();

        m_currentiteration = 0;

        int     mru_project_iteration = 0;
        if (m_Registry != NULL)
        {
                if (m_Registry->ValueExists("MRUProjectIteration"))
                {
                        mru_project_iteration = m_Registry->ReadInteger("MRUProjectIteration");
                }
        }

        /**
         *      Build the iterations available for this project.  Include only those
         *      iterations for which schemas have been loaded.
         */
        int                     index = 0;
        int                     mru_project_iteration_index = -1;
        AnsiString      entryString;
        int                     iteration = 0;
        std::string     schemaHandle;
        while (!query->Eof)
        {
                iteration = query->FieldByName( "ITERATION" )->AsInteger;

                if ( findSchema( schemaHandle,
                                                 m_currentproject.UpperCase(),
                                                 iteration ) )
                {
                        if ( m_currentiteration == 0 )
                        {
                                m_currentiteration = iteration;
                        }
                        if ( mru_project_iteration == iteration )
                        {
                                mru_project_iteration_index = index;
                        }

                        entryString.sprintf( "%d", iteration );
                        IterationsComboBox->AddItem(
                                entryString,
                                reinterpret_cast< TObject * >( iteration ) );

                        ++index;
                }

                query->Next();
        }

        if ( mru_project_iteration_index != -1 )
        {
                IterationsComboBox->ItemIndex = mru_project_iteration_index;
        IterationsComboBoxChange(Sender);

                bool allow;
                TestCaseGridRowChanging(Sender, 0, 1, allow = true );
        }
        else
        {
                IterationCopyButton->Enabled = false;
        }

    delete query;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::tsDBGrid2RowChanged(TObject *Sender,
          Variant &OldRow, Variant &NewRow)
{
        TestScenariosTabSheet->TabVisible = true;
        MainPageControl->ActivePage = TestScenariosTabSheet;
    TestCasesTabSheet->TabVisible = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::UseCaseDBGridEnter(TObject *Sender)
{
        TestCasesTabSheet->TabVisible = true;
        MainPageControl->ActivePage = TestCasesTabSheet;
    TestScenariosTabSheet->TabVisible = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::IterationParamsQueryAfterInsert(
      TDataSet *DataSet)
{
        DataSet->FieldByName("PROJECT_CODE")->AsString  = m_currentproject;
        DataSet->FieldByName("ITERATION")->AsInteger    = m_currentiteration;
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::ImportXMLSchemaBtnClick(TObject *Sender)
{
        bool    found_xml_schema = false;

        vector<string>::iterator        itr = m_xml_schemas.begin();

    while (itr != m_xml_schemas.end())
    {
        string                  handle = (*itr).c_str();
        vector<string>  schema_structures;
        string                  project;
        string                  iteration;

                XMLSchema->GetAttributeProperty(handle, "project", project);

        if ( m_currentproject.UpperCase() == AnsiString(project.c_str()).UpperCase() )
        {
                XMLSchema->GetAttributeProperty(handle, "majorversion", iteration);

            if (m_currentiteration == atoi(iteration.c_str()))
            {
                found_xml_schema = true;
                
                        XMLSchema->GetAttributes(handle, schema_structures);

                TADOQuery       *query = new TADOQuery(this);
                AnsiString      sql_statement;
                query->Connection = Data_Module->IntegrationDBConnection;

                Data_Module->IntegrationDBConnection->BeginTrans();

                try
                                {
                                        // Disable any constraints
                                        query->SQL->Text = "ALTER TABLE TRANSACTION_SPECIFICATION DISABLE CONSTRAINT TRANS_SPEC_MASS_TXNS_C";
                    query->ExecSQL();

                    sql_statement.sprintf("DELETE FROM MASS_TXNS WHERE PROJECTCODE='%s' AND ITERATION=%d",
                                          m_currentproject.c_str(),
                                                                                  m_currentiteration);

                    query->SQL->Text = sql_statement;
                    query->ExecSQL();

                    vector<string>::iterator    s_itr = schema_structures.begin();

                    while (s_itr != schema_structures.end())
                    {
                        string  struct_handle = (*s_itr);
                        string  specificationonly;
                        string  txnname;
                        string  udtype;
                                                string  udsubtype;
                                                string  documentation;

                                                XMLSchema->GetAttributeProperty(struct_handle, "specificationonly", specificationonly);

                                                if (specificationonly == "false")
                                                {
                                                        XMLSchema->GetAttributeProperty(struct_handle, "name",          txnname);
                                                        XMLSchema->GetAttributeProperty(struct_handle, "UDType",        udtype);
                                                        XMLSchema->GetAttributeProperty(struct_handle, "UDSubtype",     udsubtype);
                                                        XMLSchema->GetAttributeProperty( struct_handle, "documentation", documentation );

                            if (udtype.length() > 0)
                                                        {
                                                                sql_statement="";
                                                                sql_statement.sprintf("INSERT INTO MASS_TXNS(PROJECTCODE,ITERATION,NAME,UDTYPE,UDSUBTYPE,DESCRIPTION) "
                                                                                                          "VALUES (\'%s\', %d,\'%s\',%d,%d,\'%s\')",
                                                                                                          m_currentproject.c_str(),
                                                                                                          m_currentiteration,
                                                                                                          txnname.c_str(),
                                                                                                          atoi(udtype.c_str()),atoi(udsubtype.c_str()),
                                                                                                          Utilities::EscapeString( documentation ).c_str()
                                                                                                          );

                                query->SQL->Text = sql_statement;
                                query->ExecSQL();
                            }
                        }

                        ++s_itr;
                    }

                                        // Re-enable any constraints
                                        query->SQL->Text = "ALTER TABLE TRANSACTION_SPECIFICATION ENABLE CONSTRAINT TRANS_SPEC_MASS_TXNS_C";
                    query->ExecSQL();

                    Data_Module->IntegrationDBConnection->CommitTrans();
                                }
                catch(...)
                {
                        Data_Module->IntegrationDBConnection->RollbackTrans();
                }

                MASSTxnsQuery->Close();
                MASSTxnsQuery->Open();

                delete query;
            }
        }

        ++itr;
        }

    if (found_xml_schema)
    {
        AnsiString      msg;
        msg.sprintf("Imported XML definition for the Project: %s - Iteration: %d",
                    m_currentproject, m_currentiteration);

        MessageDlg(msg, mtInformation, TMsgDlgButtons() << mbOK, 0);
    }
    else
    {
        AnsiString      msg;
        msg.sprintf("Failed to locate an XML definition for the Project: %s - Iteration: %d",
                    m_currentproject, m_currentiteration);

        MessageDlg(msg, mtError, TMsgDlgButtons() << mbOK, 0);
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::readTransactionSpecifications(
                                        TransactionSpecification &      transaction,
                                        const int &                                     transactionSpecification )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "XPATH,"
                                "FIELDVALUE,"
                                "OBSOLETE "
                        "FROM "
                                "TXNSPEC_VALUES "
                        "WHERE "
                                "TXNSPEC_NO=%d",
                        transactionSpecification );
                query->SQL->Text = sqlStatement;
                query->Open();

                while ( !query->Eof )
                {
                        transaction.addValue(
                                query->FieldByName( "XPATH" )->AsString.c_str(),
                                query->FieldByName( "FIELDVALUE" )->AsString.c_str(),
                                query->FieldByName( "OBSOLETE" )->AsBoolean );
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::obsoleteTransactionSpecifications(
                                        const TransactionSpecification & transaction )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                for ( std::map< std::string, TransactionSpecificationValue * >::const_iterator
                                where = transaction.getValues().begin();
                          where != transaction.getValues().end();
                          ++where )
                {
                        if ( where->second->isMarked() )
                        {
                                if ( where->second->isObsolete() )
                                {
                                        MDETAIL( "Restoring previously obsolete \"" \
                                                << where->second->getXPath() \
                                                << "\" of transaction specification " \
                                                << transaction.getTransactionSpecificationNumber() \
                                                << '.' );
                                        sqlStatement.sprintf(
                                                "UPDATE TXNSPEC_VALUES SET "
                                                        "OBSOLETE='N' "
                                                "WHERE "
                                                        "TXNSPEC_NO=%d AND "
                                                        "XPATH=\'%s\'",
                                                transaction.getTransactionSpecificationNumber(),
                                                Utilities::EscapeString( where->second->getXPath() ) );
                                        query->SQL->Text = sqlStatement;
                                        if ( query->ExecSQL() != 1 )
                                        {
                                                MTHROW( std::runtime_error, \
                                                        "Cannot restore previously obsolete field \"" \
                                                        << where->second->getXPath() \
                                                        << "\" of transaction specification " \
                                                        << transaction.getTransactionSpecificationNumber() \
                                                        << '.' );
                                        }
                                }
                        }
                        else
                        {
                                if ( where->second->getExpression().length() )
                                {
                                        if ( !where->second->isObsolete() )
                                        {
                                                MDETAIL( "Obsoleting \"" \
                                                        << where->second->getXPath() \
                                                        << "\" of transaction specification " \
                                                        << transaction.getTransactionSpecificationNumber() \
                                                        << '.' );
                                                sqlStatement.sprintf(
                                                        "UPDATE TXNSPEC_VALUES SET "
                                                                "OBSOLETE='Y' "
                                                        "WHERE "
                                                                "TXNSPEC_NO=%d AND "
                                                                "XPATH=\'%s\'",
                                                        transaction.getTransactionSpecificationNumber(),
                                                        Utilities::EscapeString( where->second->getXPath() ) );
                                                query->SQL->Text = sqlStatement;
                                                if ( query->ExecSQL() != 1 )
                                                {
                                                        MTHROW( std::runtime_error, \
                                                                "Cannot obsolete field \"" \
                                                                << where->second->getXPath() \
                                                                << "\" of transaction specification " \
                                                                << transaction.getTransactionSpecificationNumber() \
                                                                << '.' );
                                                }
                                        }
                                }
                                else
                                {
                                        MDETAIL( "Deleting obsolete and unused \"" \
                                                << where->second->getXPath() \
                                                << "\" of transaction specification " \
                                                << transaction.getTransactionSpecificationNumber() \
                                                << '.' );
                                        sqlStatement.sprintf(
                                                "DELETE FROM "
                                                        "TXNSPEC_VALUES "
                                                "WHERE "
                                                        "TXNSPEC_NO=%d AND "
                                                        "XPATH=\'%s\'",
                                                transaction.getTransactionSpecificationNumber(),
                                                Utilities::EscapeString( where->second->getXPath() ) );
                                        query->SQL->Text = sqlStatement;
                                        if ( query->ExecSQL() != 1 )
                                        {
                                                MTHROW( std::runtime_error, \
                                                        "Cannot delete obsolete field \"" \
                                                        << where->second->getXPath() \
                                                        << "\" of transaction specification " \
                                                        << transaction.getTransactionSpecificationNumber() \
                                                        << '.' );
                                        }
                                }
                        }
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionsForIteration(
                                        TransactionCache &      transactionCache,
                                        ProgressBar &           progressBar,
                                        const std::string &     schema,
                                        const std::string &     project,                        
                                        const int &                     iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "TXNSPEC_NO,"
                                "NAME,"
                                "TESTSCENARIO_NO "
                        "FROM "
                                "TRANSACTION_SPECIFICATION,"
                                "MASS_TXNS "
                        "WHERE "
                                "TRANSACTION_SPECIFICATION.PROJECT_CODE=\'%s\' AND "
                                "TRANSACTION_SPECIFICATION.ITERATION=%d AND "
                                "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND "
                                "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND "
                                "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND "
                                "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE "
                        "ORDER BY "
                                "TESTSCENARIO_NO,"
                                "TXNSPEC_NO",
                        project.c_str(),
                        iteration );
                query->SQL->Text = sqlStatement;
                query->Open();

                AnsiString xpath;
                AnsiString message;
                while ( !query->Eof )
                {
                        if ( !m_transactionCache.isContained( query->FieldByName( "TXNSPEC_NO" )->AsInteger ) )
                        {
                                message.sprintf(
                                        " Building %s ...",
                                        query->FieldByName( "NAME" )->AsString.c_str() );
                                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message;
                                Application->ProcessMessages();

                                buildTransactionSpecificationValues(
                                        transactionCache,
                                        query->FieldByName( "TESTSCENARIO_NO" )->AsInteger,
                                        query->FieldByName( "TXNSPEC_NO" )->AsInteger,
                                        query->FieldByName( "NAME" )->AsString.c_str(),
                                        g_headerStructure,
                                        schema,
                                        iteration );
                        }
                        else
                        {
                                message.sprintf(
                                        " Using cached %s ...",
                                        query->FieldByName( "NAME" )->AsString.c_str() );
                                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message;
                                Application->ProcessMessages();
                        }

                        progressBar.increment();
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;

                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "";
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionsForScenario(
                                        TransactionCache &      transactionCache,
                                        ProgressBar &           progressBar,
                                        const int &                     scenario,
                                        const std::string &     schema,
                                        const int &                     iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "TXNSPEC_NO,"
                                "NAME "
                        "FROM "
                                "TRANSACTION_SPECIFICATION,"
                                "MASS_TXNS "
                        "WHERE "
                                "TRANSACTION_SPECIFICATION.TESTSCENARIO_NO=%d AND "
                                "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND "
                                "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND "
                                "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND "
                                "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE "
                        "ORDER BY "
                                "TXNSPEC_NO",
                        scenario );
                query->SQL->Text = sqlStatement;
                query->Open();

                AnsiString xpath;
                AnsiString message;
                while ( !query->Eof )
                {
                        if ( !m_transactionCache.isContained( query->FieldByName( "TXNSPEC_NO" )->AsInteger ) )
                        {
                                message.sprintf(
                                        " Building %s ...",
                                        query->FieldByName( "NAME" )->AsString.c_str() );

                                buildTransactionSpecificationValues(
                                        transactionCache,
                                        scenario,
                                        query->FieldByName( "TXNSPEC_NO" )->AsInteger,
                                        query->FieldByName( "NAME" )->AsString.c_str(),
                                        g_headerStructure,
                                        schema,
                                        iteration );
                        }
                        else
                        {
                                message.sprintf(
                                        " Using cached %s ...",
                                        query->FieldByName( "NAME" )->AsString.c_str() );
                        }

                        MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message;
                        Application->ProcessMessages();

                        progressBar.increment();
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;

                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "";
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionSpecificationValues(
                                        TransactionCache &      transactionCache,
                                        const int &                     testScenario,
                                        const int &                     transactionSpecification,
                                        const std::string &     transactionStructureName,
                                        const std::string &     headerStructureName,
                                        const std::string &     schema,
                                        const int &                     iteration )
{
        /**
         *      Ensure that for each transactionSpecification and iteration we do this 
         *      only on startup and whenever we import a schema.
         */

        int ordinal = 0;
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                std::string structureHandle;
                std::string headerHandle;
                try
                {
                        if ( XMLSchema->Create(
                                        schema.c_str(),
                                        transactionStructureName.c_str(),
                                        iteration,
                                        structureHandle,
                                        0 ) )
                        {
                                if ( XMLSchema->Create(
                                                schema.c_str(),
                                                headerStructureName.c_str(),
                                                iteration,
                                                headerHandle,
                                                0 ) )
                                {
                                        try
                                        {
                                                Data_Module->IntegrationDBConnection->BeginTrans();

                                                TransactionSpecification & transaction = transactionCache.getTransactionSpecification( transactionSpecification );
                                                readTransactionSpecifications( transaction, transactionSpecification );

                                                buildTransactionSpecificationValues(
                                                        *query,
                                                        transactionStructureName,
                                                        testScenario,
                                                        transactionSpecification,
                                                        structureHandle,
                                                        ordinal = 0,
                                                        transaction );
                                                buildTransactionSpecificationValues(
                                                        *query,
                                                        headerStructureName,
                                                        testScenario,
                                                        transactionSpecification,
                                                        headerHandle,
                                                        ordinal = 0,
                                                        transaction );

                                                obsoleteTransactionSpecifications( transaction );
                                                Data_Module->IntegrationDBConnection->CommitTrans();
                                        }
                                        catch ( const std::exception & exception )
                                        {
                                                std::stringstream stream;
                                                stream
                                                        << "Cannot build transaction specification values for \"" \
                                                        << transactionStructureName \
                                                        << "\".  " \
                                                        << exception.what();
                                                MessageDlg(
                                                        stream.str().c_str(),
                                                        mtError, TMsgDlgButtons() << mbOK, 0 );

                                                transactionCache.deleteTransactionSpecification( transactionSpecification );
                                                Data_Module->IntegrationDBConnection->RollbackTrans();
                                        }
                                        catch ( ... )
                                        {
                                                std::stringstream stream;
                                                stream
                                                        << "Cannot build transaction specification values for \"" \
                                                        << transactionStructureName \
                                                        << "\".";
                                                MessageDlg(
                                                        stream.str().c_str(),
                                                        mtError, TMsgDlgButtons() << mbOK, 0 );

                                                transactionCache.deleteTransactionSpecification( transactionSpecification );
                                                Data_Module->IntegrationDBConnection->RollbackTrans();
                                                throw;
                                        }
                                }
                                else
                                {
                                        std::stringstream stream;
                                        stream
                                                << "Cannot create structure \""
                                                << headerStructureName
                                                << "\" for iteration "
                                                << iteration << ".  Is \""
                                                << XMLSchema->Profile.c_str() << "\" configured correctly?";
                                        MessageDlg(
                                                stream.str().c_str(),
                                                mtError, TMsgDlgButtons() << mbOK, 0 );
                                }
                        }
                        else
                        {
                                std::stringstream stream;
                                stream
                                        << "Cannot create structure \""
                                        << transactionStructureName
                                        << "\" for iteration "
                                        << iteration << ".  Is \""
                                        << XMLSchema->Profile.c_str() << "\" configured correctly?";
                                MessageDlg(
                                        stream.str().c_str(),
                                        mtError, TMsgDlgButtons() << mbOK, 0 );
                        }
                }
                __finally
                {
                        XMLSchema->Destroy( headerHandle );
                        XMLSchema->Destroy( structureHandle );
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionSpecificationFieldValue(
                                        TADOQuery &                                     query,
                                        const std::string &                     rootStructure,
                                        const std::string &                     fieldHandle,
                                        const int &                                     testScenario,
                                        const int &                                     transactionSpecification,
                                        int &                                           ordinal,
                                        const &                                         childCount,
                                        TransactionSpecification &      transactions,
                                        const int &                                     subscript )
{
        std::string tagValue;

        // If we get a tag, then use it.  Otherwise, tough luck.
        if ( !XMLSchema->GetAttributeProperty( fieldHandle, "tag", tagValue ) ||
                 tagValue.length() > 0 )
        {
                std::string     fieldName;
                std::string     xPath;

                if ( XMLSchema->GetAttributeProperty( fieldHandle, "name", fieldName ) &&
                         XMLSchema->GetAttributeProperty( fieldHandle, "xpath", xPath ) )
                {
                        /**
                         *      Build the full xpath as the schema reports only the path
                         *      relative to the root structure.
                         */
                        const std::string fullXPath = "/" + rootStructure + xPath;

                        AnsiString displayName;
                        if ( !subscript )
                        {
                                displayName = fieldName.c_str();
                        }
                        else
                        {
#if TDBADVGRID_FIXED
                                displayName.sprintf( "[%d]", subscript );
#else
                                displayName.sprintf( "%s[%d]", fieldName.c_str(), subscript );
#endif
                        }

                        /**
                         *      Work out whether we have to insert or update, and whether we
                         *      have to migrate or not.
                         */
                        bool insert             = false;
                        bool migrate    = false;
                        if ( transactions.isContained( fullXPath ) )
                        {
                                insert = false;
                                migrate = false;
                        }
                        else
                        {
                                if ( transactions.isContained( xPath ) )
                                {
                                        insert = false;
                                        migrate = true;
                                }
                                else
                                {
                                        insert = true;
                                        migrate = false;
                                }
                        }

                        /**
                         *      We now assert this value into the database.
                         */
                        std::stringstream stream;
                        if ( !insert )
                        {
                                if ( !migrate )
                                {
                                        stream << "UPDATE TXNSPEC_VALUES SET "
                                                        << "CHILD_COUNT=" << childCount << ','
                                                        << "DISPLAY_FIELDNAME=\'" << Utilities::EscapeString( displayName ).c_str() << "\',"
                                                        << "FIELDNAME=\'" << Utilities::EscapeString( fieldName ) << "\',"
                                                        << "FIELDTAG=" << atoi( tagValue.c_str() ) << ','
                                                        << "ORDINAL=" << ++ordinal << ','
                                                        << "SUBSCRIPT=" << subscript << ','
                                                        << "TESTSCENARIO_NO=" << testScenario
                                                << " WHERE "
                                                        << "TXNSPEC_NO=\'" << transactionSpecification << "\' AND "
                                                        << "XPATH=\'" << fullXPath << '\'';
                                        transactions.markValue( fullXPath );
                                }
                                else
                                {
                                        stream << "UPDATE TXNSPEC_VALUES SET "
                                                        << "CHILD_COUNT=" << childCount << ','
                                                        << "DISPLAY_FIELDNAME=\'" << Utilities::EscapeString( displayName ).c_str() << "\',"
                                                        << "FIELDNAME=\'" << Utilities::EscapeString( fieldName ) << "\',"
                                                        << "FIELDTAG=" << atoi( tagValue.c_str() ) << ','
                                                        << "ORDINAL=" << ++ordinal << ','
                                                        << "SUBSCRIPT=" << subscript << ','
                                                        << "TESTSCENARIO_NO=" << testScenario << ','
                                                        << "XPATH=\'" << fullXPath << '\''
                                                << " WHERE "
                                                        << "TXNSPEC_NO=\'" << transactionSpecification << "\' AND "
                                                        << "XPATH=\'" << xPath << '\'';
                                        transactions.markValue( xPath );
                                }
                        }
                        else
                        {
                                stream << "INSERT INTO TXNSPEC_VALUES ( "
                                                "TXNSPEC_NO,"
                                                "XPATH,"
                                                "CHILD_COUNT,"
                                                "DISPLAY_FIELDNAME,"
                                                "FIELDNAME,"
                                                "FIELDTAG,"
                                                "OBSOLETE,"
                                                "ORDINAL,"
                                                "SUBSCRIPT,"
                                                "TESTSCENARIO_NO,"
                                                "USER_SUPPLIED"
                                        " ) VALUES ( "
                                                << transactionSpecification << ",\'"
                                                << fullXPath << "\',"
                                                << childCount << ",\'"
                                                << Utilities::EscapeString( displayName ).c_str() << "\',\'"
                                                << Utilities::EscapeString( fieldName ).c_str() << "\',"
                                                << atoi( tagValue.c_str() ) << ','
                                                << "\'N\'" << ','
                                                << ++ordinal << ','
                                                << subscript << ','
                                                << testScenario << ','
                                                << "\'N\'"
                                        << " )";
                        }

                        query.SQL->Text = stream.str().c_str();
                        if ( query.ExecSQL() != 1 )
                        {
                                MTHROW( std::runtime_error, \
                                        "Cannot update field \"" \
                                        << fullXPath \
                                        << "\" of transaction specification " \
                                        << transactionSpecification \
                                        << '.' );
                        }
                }
                else
                {
                        MTHROW( std::runtime_error, \
                                "Cannot get name and xpath for schema element \"" \
                                << fieldHandle \
                                << "\"." );
                }
        }
        else
        {
                MTHROW( std::runtime_error, \
                        "Cannot get tag value for schema element \"" \
                        << fieldHandle \
                        << "\".  The tag is present but has a zero-length value." );
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionSpecificationRepeatValue(
                                        TADOQuery &                                     query,
                                        const std::string &                     rootStructure,
                                        const std::string &                     attribute,
                                        const int &                                     testScenario,
                                        const int &                                     transactionSpecification,
                                        const std::string &                     transactionStructureHandle,
                                        int &                                           ordinal,
                                        TransactionSpecification &      transactions,
                                        const int &                                     repeatLimit )
{
        std::string refcountField;
        std::string repeatSize;

        /**
         *      Find the upper bound of the repeat by looking for the "max" property
         *      of the "refcountfield" (possibly an xPath), and then for our
         *      "maxOccurs" property.
         */
        XMLSchema->GetAttributeProperty( attribute, "refcountfield", refcountField );
        if ( refcountField.length() )
        {
                XMLSchema->GetAttributeProperty(
                        transactionStructureHandle + "." + refcountField,
                        "max",
                        repeatSize );
        }

        if ( !repeatSize.length() )
        {
                XMLSchema->GetAttributeProperty(
                        attribute,
                        "maxOccurs",
                        repeatSize );
        }

        if ( repeatSize.length() )
        {
                /**
                 *      Now instantiate the array so that we may traverse it, but limit it to
                 *      repeatLimit elements.
                 */
                const int       size = std::min< int >( atoi( repeatSize.c_str() ), repeatLimit );
                std::string             repeatName;

                if ( ( refcountField.length() == 0 ) ||
                         XMLSchema->SetAttributeValue( transactionStructureHandle, refcountField, size ) )
                {
                        if ( XMLSchema->GetAttributeProperty( attribute, "name", repeatName ) )
                        {
                                AnsiString      repeatElement;
                                std::string             datatype;
                                repeatElement.sprintf( "%s.1.%s",
                                        attribute.c_str(),
                                        repeatName.c_str() );
                                if ( XMLSchema->GetAttributeProperty(
                                                repeatElement.c_str(),
                                                "datatype",
                                                datatype ) )
                                {
                                        const bool isStruct = ( datatype == "Struct" );
                                        buildTransactionSpecificationFieldValue(
                                                query,
                                                rootStructure,
                                                attribute,
                                                testScenario,
                                                transactionSpecification,
                                                ordinal,
                                                countChildren( attribute, isStruct ),
                                                transactions );
                                        if ( size >= 1 )
                                        {
                                                std::string repeatHandle;
                                                for ( int where = 1; where <= size; ++where )
                                                {
                                                        repeatElement.sprintf( "%s.%d.%s",
                                                                attribute.c_str(),
                                                                where,
                                                                repeatName.c_str() );
                                                        repeatHandle = repeatElement.c_str();
                                                        if ( isStruct )
                                                        {
                                                                buildTransactionSpecificationFieldValue(
                                                                        query,
                                                                        rootStructure,
                                                                        repeatHandle,
                                                                        testScenario,
                                                                        transactionSpecification,
                                                                        ordinal,
                                                                        countChildren( repeatHandle, isStruct ),
                                                                        transactions,
                                                                        where );
                                                                buildTransactionSpecificationValues(
                                                                        query,
                                                                        rootStructure,
                                                                        testScenario,
                                                                        transactionSpecification,
                                                                        repeatHandle,
                                                                        ordinal,
                                                                        transactions );
                                                        }
                                                        else
                                                        {
                                                                buildTransactionSpecificationFieldValue(
                                                                        query,
                                                                        rootStructure,
                                                                        repeatHandle,
                                                                        testScenario,
                                                                        transactionSpecification,
                                                                        ordinal,
                                                                        0,
                                                                        transactions,
                                                                        where );
                                                        }
                                                }
                                        }
                                }
                                else
                                {
                                        MTHROW( std::runtime_error, \
                                                "Cannot get datatype for schema element \"" \
                                                << repeatElement.c_str() \
                                                << "\"." );
                                }
                        }
                        else
                        {
                                MTHROW( std::runtime_error, \
                                        "Cannot get name for schema element \"" \
                                        << attribute \
                                        << "\"." );
                        }
                }
                else
                {
                        MTHROW( std::runtime_error, \
                                "Cannot set size for schema element \"" \
                                << transactionStructureHandle + "." + refcountField \
                                << "\"." );
                }
        }
        else
        {
                MTHROW( std::runtime_error, \
                        "Cannot get repeat size for schema element \"" \
                        << attribute \
                        << "\"." );
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionSpecificationValues(
                                        TADOQuery &                                     query,
                                        const std::string &                     rootStructure,
                                        const int &                                     testScenario,
                                        const int &                                     transactionSpecification,
                                        const std::string &                     transactionStructureHandle,
                                        int &                                           ordinal,
                                        TransactionSpecification &      transactions )
{
        std::vector< std::string > attributes;

        if ( XMLSchema->GetAttributes( transactionStructureHandle, attributes ) )
        {
                std::string elementType;

                for ( std::vector< std::string >::iterator
                                where = attributes.begin();
                          where != attributes.end();
                          ++where )
                {
                        if ( XMLSchema->GetAttributeProperty( *where, "type", elementType ) )
                        {
                                std::string elementDatatype;

                                if ( elementType == "field" )
                                {
                                        if ( XMLSchema->GetAttributeProperty( *where, "datatype", elementDatatype ) )
                                        {
                                                const isStruct = ( elementDatatype == "Struct" );

                                                buildTransactionSpecificationFieldValue(
                                                        query,
                                                        rootStructure,
                                                        *where,
                                                        testScenario,
                                                        transactionSpecification,
                                                        ordinal,
                                                        ( isStruct ? countChildren( *where, false ) : 0 ),
                                                        transactions );
                                                if ( isStruct )
                                                {
                                                        buildTransactionSpecificationValues(
                                                                query,
                                                                rootStructure,
                                                                testScenario,
                                                                transactionSpecification,
                                                                *where,
                                                                ordinal,
                                                                transactions );
                                                }
                                        }
                                        else
                                        {
                                                MTHROW( std::runtime_error, \
                                                        "Cannot get datatype for schema element \"" \
                                                        << *where \
                                                        << "\"." );
                                        }
                                }
                                else if ( elementType == "repeat" )
                                {
                                        buildTransactionSpecificationRepeatValue(
                                                query,
                                                rootStructure,
                                                *where,
                                                testScenario,
                                                transactionSpecification,
                                                transactionStructureHandle,
                                                ordinal,
                                                transactions );
                                }
                        }
                        else
                        {
                                MTHROW( std::runtime_error, \
                                        "Cannot get type for schema element \"" \
                                        << *where \
                                        << "\"." );
                        }
                }
        }
        else
        {
                MTHROW( std::runtime_error, \
                        "Cannot get attributes for schema element \"" \
                        << transactionStructureHandle \
                        << "\"." );
        }
}
//---------------------------------------------------------------------------

const unsigned __fastcall TMainForm::countChildren( const std::string & transactionStructureHandle, const bool & isStructureRepeat )
{
        unsigned                                        childCount = 0;
        std::vector< std::string >      attributes;

        if ( XMLSchema->GetAttributes( transactionStructureHandle, attributes ) )
        {
                std::string elementType;
                std::string elementDatatype;

                for ( std::vector< std::string >::iterator
                                where = attributes.begin();
                          where != attributes.end();
                          ++where )
                {
                        if ( XMLSchema->GetAttributeProperty( *where, "type", elementType ) )
                        {
//                              if ( !isStructureRepeat )
//                              {
                                        ++childCount;
//                              }
                                if ( elementType == "field" )
                                {
                                        if ( XMLSchema->GetAttributeProperty( *where, "datatype", elementDatatype ) )
                                        {
                                                if ( elementDatatype == "Struct" )
                                                {
                                                        childCount += countChildren( *where, false );
                                                }
                                        }
                                        else
                                        {
                                                MTHROW( std::runtime_error, \
                                                        "Cannot get datatype for schema element \"" \
                                                        << *where \
                                                        << "\"." );
                                        }
                                }
                                else if ( elementType == "repeat" )
                                {
                                        childCount += countChildren( *where, transactionStructureHandle );
                                }
                        }
                        else
                        {
                                MTHROW( std::runtime_error, \
                                        "Cannot get type for schema element \"" \
                                        << *where \
                                        << "\"." );
                        }
                }
        }
        else
        {
                MTHROW( std::runtime_error, \
                        "Cannot get attributes for schema element \"" \
                        << transactionStructureHandle \
                        << "\"." );
        }

        return ( childCount );
}
//---------------------------------------------------------------------------

const unsigned __fastcall TMainForm::countChildren(
                                        const std::string &     attribute,
                                        const std::string &             transactionStructureHandle,
                                        const int &                     repeatLimit )
{
        unsigned        childCount = 0;
        std::string     refcountField;
        std::string     repeatSize;

        /**
         *      Find the upper bound of the repeat by looking for the "max" property
         *      of the "refcountfield" (possibly an xPath), and then for our
         *      "maxOccurs" property.
         */
        XMLSchema->GetAttributeProperty( attribute, "refcountfield", refcountField );
        if ( refcountField.length() )
        {
                XMLSchema->GetAttributeProperty(
                        transactionStructureHandle + "." + refcountField,
                        "max",
                        repeatSize );
        }

        if ( !repeatSize.length() )
        {
                XMLSchema->GetAttributeProperty(
                        attribute,
                        "maxOccurs",
                        repeatSize );
        }

        if ( repeatSize.length() )
        {
                /**
                 *      Now instantiate the array so that we may traverse it, but limit it to
                 *      repeatLimit elements.
                 */
                const int       size = std::min< int >( atoi( repeatSize.c_str() ), repeatLimit );
                std::string             repeatName;

                if ( ( refcountField.length() == 0 ) ||
                         XMLSchema->SetAttributeValue( transactionStructureHandle, refcountField, size ) )
                {
                        if ( XMLSchema->GetAttributeProperty( attribute, "name", repeatName ) )
                        {
                                if ( size >= 1 )
                                {
                                        AnsiString      repeatElement;
                                        std::string             datatype;
                                        repeatElement.sprintf( "%s.1.%s",
                                                attribute.c_str(),
                                                repeatName.c_str() );
                                        if ( XMLSchema->GetAttributeProperty(
                                                        repeatElement.c_str(),
                                                        "datatype",
                                                        datatype ) )
                                        {
                                                const isStruct = ( datatype == "Struct" );
                                                for ( int where = 1; where <= size; ++where )
                                                {
                                                        repeatElement.sprintf( "%s.%d.%s",
                                                                attribute.c_str(),
                                                                where,
                                                                repeatName.c_str() );
                                                        if ( !isStruct )
                                                        {
                                                                ++childCount;
                                                        }
                                                        else
                                                        {
                                                                childCount += countChildren( repeatElement.c_str(), false ) + 1;
                                                        }
                                                }
                                        }
                                        else
                                        {
                                                MTHROW( std::runtime_error, \
                                                        "Cannot get datatype for schema element \"" \
                                                        << repeatElement.c_str() \
                                                        << "\"." );
                                        }
                                }
                        }
                        else
                        {
                                MTHROW( std::runtime_error, \
                                        "Cannot get name for schema element \"" \
                                        << attribute \
                                        << "\"." );
                        }
                }
                else
                {
                        MTHROW( std::runtime_error, \
                                "Cannot set size for schema element \"" \
                                << transactionStructureHandle + "." + refcountField \
                                << "\"." );
                }
        }
        else
        {
                MTHROW( std::runtime_error, \
                        "Cannot get repeat size for schema element \"" \
                        << attribute \
                        << "\"." );
        }
        return ( childCount );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::clearTransactionSpecificationValueTree( TDBAdvGrid & grid )
{
#if TDBADVGRID_FIXED
        grid.RemoveAllNodes();
#endif
}
//---------------------------------------------------------------------------

const int TMainForm::countChildNodes( TDBAdvGrid & grid, TADOQuery & query, const int & row, const int & rows )
{
        query.RecNo = row;      // Move the cursor to the row we're looking at.

        int                                     count           = 0;
        const AnsiString        parentPath      = query.FieldByName( "XPATH" )->AsString;

        for ( int where = row + 1; where <= rows; ++where )
        {
                query.RecNo = where;

                if ( parentPath == query.FieldByName( "XPATH" )
                                                                ->AsString.SubString( 1, parentPath.Length() ) )
                {
                        ++count;
                }
                else
                {
                        break;
                }
        }

        return ( count );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildTransactionSpecificationValueTree( TDBAdvGrid & grid, TADOQuery & query )
{
#if TDBADVGRID_FIXED
        grid.BeginUpdate();
        const int currentRow = query.RecNo;
        try
        {
                int children    = 0;
                const int rows  = query.RecordCount;
                for ( int where = 1; where <= rows; ++where )
                {
                        if ( ( children = countChildNodes( grid, query, where, rows ) ) > 0 )
                        {
                                grid.AddNode( where, 1 + children );
                        }
                }
        }
        __finally
        {
                grid.ContractAll();
                query.RecNo = currentRow;
                grid.EndUpdate();
        }
#endif
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::getParentOrdinals( std::vector< int > & parents )
{
        TADOQuery * query = 0;
        try
        {
                parents.clear();

                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString      sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "ORDINAL "
                        "FROM "
                                "TXNSPEC_VALUES "
                        "WHERE "
                                "TESTSCENARIO_NO=%d AND "
                                "TXNSPEC_NO=%d AND "
                                "CHILD_COUNT > 0",
                        m_testscenario_no,
                        m_txnspec_no );
                query->SQL->Text = sqlStatement;
                query->Open();
                while ( !query->Eof )
                {
                        parents.push_back( query->FieldByName( "ORDINAL" )->AsInteger );
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::populatePayloadStructureTab( const AnsiString & structure )
{
        AnsiString      sqlStatement;

        PayloadStructureTabSheet->TabVisible = true;
        PayloadStructureTabSheet->Caption = structure;
        
        TxnValuesQuery->Close();
#if TDBADVGRID_FIXED
        clearTransactionSpecificationValueTree( *NewPayloadStructureGrid );
#endif
        sqlStatement.sprintf(
                "SELECT "
                        "* "
                "FROM "
                        "TXNSPEC_VALUES "
                "WHERE "
                        "TESTSCENARIO_NO=%d AND "
                        "TXNSPEC_NO=%d AND "
                        "XPATH LIKE \'/%s/%%\' AND "
                        "OBSOLETE=\'N\' "
#if !INCLUDE_PARENTS
                        "AND CHILD_COUNT=0 "
#endif
                "ORDER BY "
                        "ORDINAL,"
                        "FIELDNAME,"
                        "SUBSCRIPT",
                m_testscenario_no,
                m_txnspec_no,
                structure.c_str() );

        TxnValuesQuery->SQL->Text = sqlStatement;
        TxnValuesQuery->Open();

#if TDBADVGRID_FIXED
        buildTransactionSpecificationValueTree( *NewPayloadStructureGrid, *TxnValuesQuery );
#endif
#if INCLUDE_PARENTS
        getParentOrdinals( m_parents );
#endif
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::populateHeaderStructureTab( const AnsiString & structure )
{
        AnsiString sqlStatement;

//      HeaderStructureTabSheet->TabVisible = true;
        HeaderStructureTabSheet->Caption = structure;

        TxnHeaderValuesQuery->Close();

        sqlStatement.sprintf(
                "SELECT "
                        "* "
                "FROM "
                        "TXNSPEC_VALUES "
                "WHERE "
                        "TESTSCENARIO_NO=%d AND "
                        "TXNSPEC_NO=%d AND "
                        "XPATH LIKE \'/%s/%%\' AND "
                        "OBSOLETE=\'N\' "
                "ORDER BY "
                        "ORDINAL,"
                        "FIELDNAME,"
                        "SUBSCRIPT",
                m_testscenario_no,
                m_txnspec_no,
                structure.c_str() );

        TxnHeaderValuesQuery->SQL->Text = sqlStatement;
        TxnHeaderValuesQuery->Open();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::populateObsoleteStructureTab( void )
{
        AnsiString sqlStatement;

        TxnObsoleteValuesQuery->Close();
        sqlStatement.sprintf(
                "SELECT "
                        "* "
                "FROM "
                        "TXNSPEC_VALUES "
                "WHERE "
                        "TESTSCENARIO_NO=%d AND "
                        "TXNSPEC_NO=%d AND "
                        "OBSOLETE=\'Y\'"
                "ORDER BY "
                        "ORDINAL,"
                        "FIELDNAME,"
                        "SUBSCRIPT",
                m_testscenario_no,
                m_txnspec_no );

        TxnObsoleteValuesQuery->SQL->Text = sqlStatement;
        TxnObsoleteValuesQuery->Open();

        ObsoleteFieldTabSheet->TabVisible = !TxnObsoleteValuesQuery->IsEmpty();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewChange(TObject *Sender,
          TTreeNode *Node)
{
        TestCaseTreeViewEnter(Sender);

        AnsiString      sql_statement;

    // Only update when TestCase nodes
    if (Node->Level == 0)
    {
        // ----------------- TEST CASE -----------------

                TestCasePanel->Caption = Node->Text;

                m_testscenario_no = (int)(Node->Data);
                m_txnspec_no = 0;
                m_structure_name="";

                TxnValuesQuery->Close();
                TxnHeaderValuesQuery->Close();
                TxnObsoleteValuesQuery->Close();

//              TransactionStructurePageControl->ActivePage = PayloadStructureTabSheet;
                PayloadStructureTabSheet->Caption = "Payload Structure";
                HeaderStructureTabSheet->Caption = "Header Structure";
//              HeaderStructureTabSheet->TabVisible = false;
                ObsoleteFieldTabSheet->TabVisible = false;

                m_parents.clear();

                TxnStepsQuery->Close();
                sql_statement="";
                sql_statement.sprintf("SELECT NAME,DESCRIPTION,EXPECTED_RESULT FROM TXNSPEC_STEPS "
                                                          "WHERE TESTSCENARIO_NO=%d "
                                                          "ORDER BY NAME",
                                                          m_testscenario_no);
                TxnStepsQuery->SQL->Text = sql_statement;
                TxnStepsQuery->Open();

                // ---------------------------------------------
        }
        else
        if (Node->Level == 1)
        {
                // ---------------- TRANSACTION ----------------

                TestCasePanel->Caption = Node->Parent->Text;

                m_testscenario_no       = (int)(Node->Parent->Data);
                m_txnspec_no            = (int)(Node->Data);
                m_structure_name        = Node->Text.c_str();

//              TransactionStructurePageControl->ActivePage = PayloadStructureTabSheet;
                if ( !m_transactionCache.isContained( m_txnspec_no ) )
                {
                        const TCursor Save_Cursor = Screen->Cursor;
                        try
                        {
                                Screen->Cursor = crHourGlass;

                                AnsiString message;
                                message.sprintf(
                                        " Building %s ...",
                                        Node->Text.c_str() );
                                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message;
                                Application->ProcessMessages();

                                buildTransactionSpecificationValues(
                                        m_transactionCache,
                                        m_testscenario_no,
                                        m_txnspec_no,
                                        Node->Text.c_str(),
                                        g_headerStructure,
                                        m_schema_handle,
                                        m_currentiteration );
                        }
                        __finally
                        {
                                Screen->Cursor = Save_Cursor;
                        }
                }
                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "";
                
                populateHeaderStructureTab( g_headerStructure );
                populatePayloadStructureTab( Node->Text );
                populateObsoleteStructureTab();

                TxnStepsQuery->Close();
                sql_statement="";
                sql_statement.sprintf("SELECT NAME,DESCRIPTION,EXPECTED_RESULT FROM TXNSPEC_STEPS "
                                                          "WHERE TESTSCENARIO_NO=%d "
                                                          "ORDER BY NAME",
                                                          m_testscenario_no);
                TxnStepsQuery->SQL->Text = sql_statement;
                TxnStepsQuery->Open();

                // ---------------------------------------------
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::NewTransactionActionExecute(TObject *Sender)
{
        TTreeNode       *current_node = TestCaseTreeView->Selected;

    if (current_node != NULL)
    {
        if (current_node->Level == 0)   // Add Txn
                {
                AnsiString      testcase_text = current_node->Text;

                int     testscenario_no = (int)(current_node->Data);

                        if ( TxnConfig->ShowForm(m_currentproject, m_currentiteration, testcase_text) == true)
            {
                TxnSpecQuery->Close();

                TADOQuery *     query = new TADOQuery(this);
                AnsiString      sql_statement;
                query->Connection = Data_Module->IntegrationDBConnection;

                try
                {
                    Data_Module->IntegrationDBConnection->BeginTrans();

                    sql_statement="";
                    sql_statement.sprintf("SELECT MAX(SEQ_NO) AS MAXSEQ_NO "
                                                                  "FROM TRANSACTION_SPECIFICATION "
                                          "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND TESTSCENARIO_NO=%d",
                                          m_currentproject.c_str(),
                                                                                  m_currentiteration,
                                          testscenario_no);

                    query->SQL->Text = sql_statement;
                    query->Open();

                    int seq_no = query->FieldByName("MAXSEQ_NO")->AsInteger;

                    seq_no++;

                                        vector<unsigned int>                    selected_txns = TxnConfig->getSelectedTxns();
                    vector<unsigned int>::iterator      selected_txn_itr = selected_txns.begin();

                    while (selected_txn_itr != selected_txns.end())
                                        {
                        unsigned int   txnindex = (*selected_txn_itr);
                        unsigned short udtype    = txnindex >> 16;
                        unsigned short udsubtype = txnindex & 0xffff;

                        sql_statement="";
                                                sql_statement.sprintf("INSERT INTO TRANSACTION_SPECIFICATION (PROJECT_CODE,ITERATION,TESTSCENARIO_NO,UDTYPE,UDSUBTYPE,SEQ_NO) "
                                              "VALUES ('%s',%d,%d,%d,%d,%d) ",
                                              m_currentproject.c_str(),
                                              m_currentiteration,
                                              testscenario_no,
                                              udtype,
                                              udsubtype,
                                              seq_no);

                        query->SQL->Text = sql_statement;
                        query->ExecSQL();

                        seq_no++;

                        selected_txn_itr++;
                    }

                    Data_Module->IntegrationDBConnection->CommitTrans();
                }
                catch(...)
                {
                    Data_Module->IntegrationDBConnection->RollbackTrans();
                }

                delete query;

                TxnSpecQuery->Open();

                LoadTestCaseNodes(current_node);
            }
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::DeleteTransactionActionExecute(TObject *Sender)
{
        bool            refresh_testcases = false;

        for (unsigned selected_item=0; selected_item<TestCaseTreeView->SelectionCount; selected_item++)
        {
                TTreeNode       *current_node = TestCaseTreeView->Selections[selected_item];

                if (current_node!= NULL)
                {
                        if (current_node->Level == 1)   // Remove Test Case Transaction
                        {
                                // Confirm deletion
                                AnsiString      message;
                                message.sprintf( "Are you sure you want to delete this transaction?" );

                                if ( MessageDlg( message, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mrYes )
                                {
                                        int     testscenario_no = (int)(current_node->Parent->Data);
                                        int     txnspec_no = (int)(current_node->Data);

                                        TADOQuery       *query = new TADOQuery(this);
                                        AnsiString      sql_statement;
                                        query->Connection = Data_Module->IntegrationDBConnection;

                                        try
                                        {
                                                Data_Module->IntegrationDBConnection->BeginTrans();

                                                sql_statement.sprintf("DELETE FROM TXNSPEC_VALUES "
                                                                                          "WHERE TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d",
                                                                                          testscenario_no,
                                                                                          txnspec_no);

                                                query->SQL->Text = sql_statement;
                                                query->ExecSQL();

                                                sql_statement="";
                                                sql_statement.sprintf("DELETE FROM TRANSACTION_SPECIFICATION "
                                                                                          "WHERE PROJECT_CODE='%s' AND ITERATION=%d "
                                                                                          "AND   TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d ",
                                                                                          m_currentproject.c_str(),
                                                                                          m_currentiteration,
                                                                                          testscenario_no,
                                                                                          txnspec_no);

                                                query->SQL->Text = sql_statement;
                                                query->ExecSQL();

                                                Data_Module->IntegrationDBConnection->CommitTrans();

                                                refresh_testcases = true;

                                                ResequenceTransactions(current_node->Parent);
                                        }
                                        catch(...)
                                        {
                                                Data_Module->IntegrationDBConnection->RollbackTrans();
                                        }

                                        delete query;
                                }
                        }
                }
        }

        if (refresh_testcases)
        {
                bool allow;
                TestCaseGridRowChanging(Sender, 0, 1, allow = true);
        }
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::TestCaseZoomInClick(TObject *Sender)
{
        TestCaseTreeView->FullExpand();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseZoomOutClick(TObject *Sender)
{
        TestCaseTreeView->FullCollapse();       
}
//---------------------------------------------------------------------------

AnsiString & TMainForm::getNameFromNode( AnsiString & name, const AnsiString & string )
{
    char const *p = string.c_str();

    name = string;
    if ( *p && *p == '(' )
    {
        ++p;
        while ( *p && isdigit( *p ) )
        {
            ++p;
        }
        if ( *p && *p == ')' )
        {
            ++p;
            while ( *p && isspace( *p ) )
            {
                ++p;
            }
            if ( *p )
            {
                name = p;
            }
        }
    }

        return ( name );
}

// Add a New Use Case

void __fastcall TMainForm::AddTestCaseNodeClick(TObject *Sender)
{
    TADOQuery   *query = new TADOQuery(this);
    AnsiString  sql_statement;
    query->Connection = Data_Module->IntegrationDBConnection;

    try
    {
        Data_Module->IntegrationDBConnection->BeginTrans();

        sql_statement="";
        sql_statement.sprintf("SELECT MAX(TESTCASE_SEQNO) MAX_SEQNO FROM TEST_SCENARIOS "
                                                  "WHERE PROJECT_CODE='%s' AND ITERATION=%d",
                              m_currentproject.c_str(),
                              m_currentiteration);

        query->SQL->Text = sql_statement;
        query->Open();
                int max_testcase_seqno = query->FieldByName("MAX_SEQNO")->AsInteger;

        sql_statement="";
        sql_statement.sprintf("INSERT INTO TEST_SCENARIOS (PROJECT_CODE,ITERATION,USECASE,TESTCASE_ID,DESCRIPTION,TESTCASE_SEQNO) "
                              "VALUES ('%s',%d,'%s','%s','%s',%d) ",
                              m_currentproject.c_str(),
                              m_currentiteration,
                                                          Utilities::EscapeString( TestCaseQuery->FieldByName("USECASE_ID")->AsString ).c_str(),
                                                          Utilities::EscapeString( TestCaseQuery->FieldByName("TESTCASE_ID")->AsString ).c_str(),
                              Utilities::EscapeString( TestCaseQuery->FieldByName("DESCRIPTION")->AsString ).c_str(),
                              max_testcase_seqno+1);

        query->SQL->Text = sql_statement;
        query->ExecSQL();

                Data_Module->IntegrationDBConnection->CommitTrans();
    }
    catch(...)
    {
        Data_Module->IntegrationDBConnection->RollbackTrans();
    }

    delete query;

        bool allow;
        TestCaseGridRowChanging(Sender, 0, 1, allow = true);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewEndDrag(TObject *Sender,
      TObject *Target, int X, int Y)
{
    TTreeNode* target_node = TestCaseTreeView->GetNodeAt(X, Y);
    if (target_node != NULL)
    {
        if (target_node->Level == 0)    // Test Case Movement
        {
                        TestCaseTreeView->Items->BeginUpdate();

            AnsiString  source_node_text = m_startnode->Text;
            TTreeNode *newnode = TestCaseTreeView->Items->Insert(target_node, source_node_text);
            newnode->Data = m_startnode->Data;

            TestCaseTreeView->Items->Delete(m_startnode);
            m_startnode = NULL;

            TestCaseTreeView->Items->EndUpdate();

            // Test Case Node
            TTreeNode *testcase_node = target_node;

            ResequenceTestCases(testcase_node);

                        bool allow;
                        TestCaseGridRowChanging(Sender, 0, 1, allow = true);
        }
        else
                if (target_node->Level == 1)    // Test Scenario Movement
        {
            TestCaseTreeView->Items->BeginUpdate();

            AnsiString  source_node_text = m_startnode->Text;
            TTreeNode *newnode = TestCaseTreeView->Items->Insert(target_node, source_node_text);
            newnode->Data = m_startnode->Data;

            TestCaseTreeView->Items->Delete(m_startnode);
            m_startnode = NULL;

            TestCaseTreeView->Items->EndUpdate();

            // Test Case Node
            TTreeNode *testcase_node = target_node->Parent;

            ResequenceTransactions(testcase_node);

                        LoadTestCaseNodes(testcase_node);
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ResequenceTestCases(TTreeNode *testcase_node)
{
    // Resequence Subtree nodes
    TADOQuery   *query = new TADOQuery(this);
    AnsiString  sql_statement;
    query->Connection = Data_Module->IntegrationDBConnection;

    try
    {
        Data_Module->IntegrationDBConnection->BeginTrans();

        int testcaseseqno = 1;
        for (int i=0; i<TestCaseTreeView->Items->Count; i++)
                {
                TTreeNode*      childnode = TestCaseTreeView->Items->Item[i];

            if (childnode->Level == 0)  // Only consider TestCase Nodes
            {
                int                     testscenario_no = (int)(childnode->Data);

                sql_statement="";
                sql_statement.sprintf("UPDATE TEST_SCENARIOS SET TESTCASE_SEQNO=%d "
                                      "WHERE TESTSCENARIO_NO=%d",
                                      testcaseseqno,
                                      testscenario_no);

                query->SQL->Text = sql_statement;
                query->ExecSQL();

                testcaseseqno++;
            }
        }

                Data_Module->IntegrationDBConnection->CommitTrans();
    }
    catch(...)
    {
        Data_Module->IntegrationDBConnection->RollbackTrans();
    }

    delete query;
}

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

void __fastcall TMainForm::ResequenceTransactions(TTreeNode *testcase_node)
{
    // Resequence Subtree nodes
    TADOQuery   *query = new TADOQuery(this);
    AnsiString  sql_statement;
    query->Connection = Data_Module->IntegrationDBConnection;

    try
    {
        Data_Module->IntegrationDBConnection->BeginTrans();

        int     testscenario_no = (int)(testcase_node->Data);

        for (int i=0; i<testcase_node->Count; i++)
        {
            sql_statement="";
            sql_statement.sprintf("UPDATE TRANSACTION_SPECIFICATION SET SEQ_NO=%d "
                                  "WHERE PROJECT_CODE='%s' AND ITERATION=%d "
                                  "AND   TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d",
                                  i+1,
                                                                  m_currentproject.c_str(),
                                                                  m_currentiteration,
                                  testscenario_no,
                                  testcase_node->Item[i]->Data);

                        query->SQL->Text = sql_statement;
            query->ExecSQL();
        }

        Data_Module->IntegrationDBConnection->CommitTrans();
    }
    catch(...)
    {
        Data_Module->IntegrationDBConnection->RollbackTrans();
    }

    delete query;
}

//---------------------------------------------------------------------------
void __fastcall TMainForm::TestCaseTreeViewStartDrag(TObject *Sender,
      TDragObject *&DragObject)
{
        m_startnode = TestCaseTreeView->Selected;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewDragOver(TObject *Sender,
      TObject *Source, int X, int Y, TDragState State, bool &Accept)
{
    if (dynamic_cast<TTreeView *>(Source) != NULL)
    {
                Accept = true;
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ApplyTemplatesClick(TObject *Sender)
{
        const TCursor Save_Cursor = Screen->Cursor;
        try
        {
                Screen->Cursor = crHourGlass;
                try
                {
                        TADOQuery * query = 0;
                        try
                        {
                                const unsigned count = countTransactionsInIteration(
                                        m_currentproject.c_str(),
                                        m_currentiteration );
                                m_progressBar->open( count * 2 + 1 );

                                // Rebuild the transaction templates, they may have changed.
                                buildTransactionTemplates(
                                        m_transactionTemplates,
                                        m_currentproject,
                                        m_currentiteration );
                                m_progressBar->increment();

                                buildTransactionsForIteration(
                                        m_transactionCache,
                                        *m_progressBar,
                                        m_schema_handle,
                                        m_currentproject.c_str(),
                                        m_currentiteration );

                                query = new TADOQuery( this );
                                query->Connection = Data_Module->IntegrationDBConnection;

                                AnsiString sqlStatement;
                                sqlStatement.sprintf(
                                        "SELECT "
                                                "TESTSCENARIO_NO "
                                                ""
                                        "FROM "
                                                "TEST_SCENARIOS "
                                        "WHERE "
                                                "PROJECT_CODE=\'%s\' AND "
                                                "ITERATION=%d",
                                        m_currentproject.c_str(),
                                        m_currentiteration );
                                query->SQL->Text = sqlStatement;
                                query->Open();

                                try
                                {
                                        Data_Module->IntegrationDBConnection->BeginTrans();
                                        while ( !query->Eof )
                                        {
                                                applyTemplatesToScenario(
                                                        *m_progressBar,
                                                        query->FieldByName( "TESTSCENARIO_NO" )->AsInteger );
                                                query->Next();
                                        }
                                        Data_Module->IntegrationDBConnection->CommitTrans();

                                        if ( TxnValuesQuery->State != dsInactive )
                                        {
                                                TxnValuesQuery->Refresh();
                                                HeaderStructureGrid->Invalidate();
                                        }
                                        if ( TxnHeaderValuesQuery->State != dsInactive )
                                        {
                                                TxnHeaderValuesQuery->Refresh();
                                                TransactionValueGrid->Invalidate();
                                        }
                                        if ( TxnObsoleteValuesQuery->State != dsInactive )
                                        {
                                                TxnObsoleteValuesQuery->Refresh();
                                                ObsoleteFieldGrid->Invalidate();
                                        }
                                }
                                catch ( ... )
                                {
                                        Data_Module->IntegrationDBConnection->RollbackTrans();
                                        throw;
                                }
                        }
                        __finally
                        {
                                delete query;
                                query = 0;

                                m_progressBar->close();
                        }
                }
                catch ( const std::exception & exception )
                {
                        MessageDlg(
                                exception.what(),
                                mtError, TMsgDlgButtons() << mbOK, 0 );
                }
                catch ( ... )
                {
                        MessageDlg(
                                "Unknown exception applying templates to this scenario.",
                                mtError, TMsgDlgButtons() << mbOK, 0 );
                }
        }
        __finally
        {
                Screen->Cursor = Save_Cursor;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::InitialiseMASSTxns()
{
        AnsiString      sql_statement;

        TADOQuery       *query = new TADOQuery(this);
    query->Connection = Data_Module->IntegrationDBConnection;

        m_mass_txns.clear();

        try
    {
        sql_statement="";
        sql_statement.sprintf("SELECT NAME,UDTYPE,UDSUBTYPE "
                              "FROM MASS_TXNS "
                              "WHERE PROJECTCODE='%s' "
                              "AND       ITERATION=%d ",
                              m_currentproject.c_str(),
                              m_currentiteration);

        query->SQL->Text = sql_statement;
        query->Open();
        while (!query->Eof)
        {
            unsigned short      udtype          = query->FieldByName("UDTYPE")->AsInteger;
            unsigned short      udsubtype       = query->FieldByName("UDSUBTYPE")->AsInteger;
            unsigned int        udindex         = (udtype << 16) + udsubtype;

            TXNIndexPair        pair(udindex, query->FieldByName("NAME")->AsString);

            m_mass_txns.insert(pair);

            query->Next();
        }
    }
    __finally
    {
        delete query;
    }
}

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

void __fastcall TMainForm::InitialiseTxnParams(unsigned int schema_format_version, IterationParams &iteration_params, IterationSequences &iteration_sequences)
{
        AnsiString      sql_statement;

    // Format Version only encodes Major/Minor numbers, and not Patch Level
        AnsiString      formatversion;
    formatversion.sprintf("0x%08X", schema_format_version);

    IterationParamsPair         pair("#0_@FORMATVERSION", formatversion.c_str());
    iteration_params.insert(pair);

    TADOQuery   *query = new TADOQuery(this);
    query->Connection = Data_Module->IntegrationDBConnection;

    TADOQuery   *seqquery = new TADOQuery(this);
        seqquery->Connection = Data_Module->IntegrationDBConnection;

    try
    {
        sql_statement="";
        sql_statement.sprintf("SELECT * FROM ITERATION_PARAMS "
                              "WHERE PROJECT_CODE='%s' AND ITERATION=%d",
                              m_currentproject.c_str(), m_currentiteration);

                query->SQL->Text = sql_statement;
        query->Open();
                while (!query->Eof)
        {
            int                 testscenario_no = 0;

            string              fieldvalue      = query->FieldByName("FIELDVALUE")->AsString.c_str();

            if ( !query->FieldByName("TESTSCENARIO_NO")->IsNull )
            {
                testscenario_no = query->FieldByName("TESTSCENARIO_NO")->AsInteger;
            }

            // Format is: @SEQ(<name>,<start>,<inc>,<limit>)
            if (fieldvalue.substr(0,4) == "@SEQ")
            {
                int lpos = fieldvalue.find("(")+1;
                int rpos = fieldvalue.rfind(")");

                string  seqargs = fieldvalue.substr( lpos, rpos );
                string  seqname;
                string  seqstart;
                string  seqinc;
                string  seqlimit;

                const char *p = seqargs.c_str();
                while ( (*p != '\0') && (*p == ' ') ) p++;              // Skip Whitespace

                while ( (*p != '\0') && (*p != ',') && (*p != ' ') )
                {
                    seqname += *p;
                    p++;
                }
                if (*p != '\0') p++;

                while ( (*p != '\0') && (*p == ' ') )
                                {
                    p++;                // Skip Whitespace
                }
                while ( (*p != '\0') && (*p != ',') && (*p != ' ') )
                {
                    seqstart += *p;
                    p++;
                }
                if (*p != '\0') p++;

                while ( (*p != '\0') && (*p == ' ') )
                {
                    p++;                // Skip Whitespace
                }

                while ( (*p != '\0') && (*p != ',') && (*p != ' ') )
                {
                    seqinc += *p;
                    p++;
                }
                                if (*p != '\0') p++;

                while ( (*p != '\0') && (*p == ' ') )
                {
                    p++;                // Skip Whitespace
                }

                while (*p != '\0')
                {
                    seqlimit += *p;
                    p++;
                }

                IterationSequence       sequence;
                sequence.name   = seqname;

                                if (seqstart.length() > 0)
                {
                    sequence.initial_value = atoi(seqstart.c_str());
                }
                else
                {
                    sequence.initial_value = 0;
                }

                if (seqname[0] == '#')
                {
                    string      seqgenname = seqname.substr(1,seqname.length()-1);

                    sql_statement="";
                    sql_statement.sprintf("SELECT SEQVALUE FROM SEQGEN WHERE PROJECT_CODE='%s' AND ITERATION=%d AND SEQNAME='%s'",
                                          m_currentproject.c_str(),
                                          m_currentiteration,
                                          seqgenname.c_str()
                                          );
                    seqquery->SQL->Text = sql_statement;
                    seqquery->Open();
                                        if (seqquery->RecordCount == 0)
                    {
                        sql_statement="";
                        sql_statement.sprintf("INSERT INTO SEQGEN (PROJECT_CODE,ITERATION,SEQNAME,SEQVALUE) VALUES ('%s',%d,'%s',%d)",
                                              m_currentproject.c_str(),
                                              m_currentiteration,
                                              seqgenname.c_str(),
                                              sequence.initial_value
                                              );
                        seqquery->SQL->Text = sql_statement;
                        seqquery->ExecSQL();
                    }
                    else
                    {
                        sequence.initial_value = seqquery->FieldByName("SEQVALUE")->AsInteger;
                    }
                }
                        
                sequence.value = sequence.initial_value;

                                if (seqinc.length() > 0)
                {
                    sequence.increment  = atoi(seqinc.c_str());
                }
                else
                {
                    sequence.increment  = 1;
                }

                                if (seqlimit.length() > 0)
                {
                    sequence.reset_at   = atoi(seqlimit.c_str());
                }
                else
                {
                    sequence.reset_at   = 0;
                }

                sequence.reset_at = 0;

                IterationSequencesPair  seqpair(sequence.name, sequence);
                iteration_sequences.insert(seqpair);
            }

            AnsiString  param_name;
                        param_name.sprintf("#%d_%s", testscenario_no, query->FieldByName("NAME")->AsString.c_str());

            IterationParamsPair pair2(param_name.c_str(), fieldvalue.c_str());
            iteration_params.insert(pair2);

            query->Next();
        }
        }
    __finally
    {
        delete query;
        delete seqquery;
        }
}

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

void __fastcall TMainForm::InitialiseTestScenario(unsigned int testscenario_no, TxnSpecValueMap &txnSpecValueMap, FoundTxnSpecValueMap &foundTxnSpecValueMap, IterationSequences &iteration_sequences, IterationParams &iteration_params)
{
        AnsiString      sql_statement;

    TADOQuery   *query = new TADOQuery(this);
    query->Connection = Data_Module->IntegrationDBConnection;

    TADOQuery   *values_query = new TADOQuery(this);
    values_query->Connection = Data_Module->IntegrationDBConnection;

    try
    {
        sql_statement="";
        sql_statement.sprintf("select txnspec_no,udtype,udsubtype "
                                                  "from transaction_specification "
                                                          "where testscenario_no=%d order by seq_no",
                              testscenario_no);
        query->SQL->Text = sql_statement;
        query->Open();
        while (!query->Eof)
        {
            // For each transaction

            unsigned int        txnspec_no      = query->FieldByName("TXNSPEC_NO")->AsInteger;
            unsigned short  udtype              = query->FieldByName("UDTYPE")->AsInteger;
            unsigned short  udsubtype   = query->FieldByName("UDSUBTYPE")->AsInteger;
            unsigned int        udindex         = (udtype << 16) + udsubtype;

                        TXNIndexMap::iterator   txn_itr = m_mass_txns.find(udindex);

                        if (txn_itr != m_mass_txns.end())
                        {
                                string  structure_name;
                                string  structure_handle;

                                structure_name  = (*txn_itr).second.c_str();

                                // Create a Transaction Instance
                                if (XMLSchema->Create(m_schema_handle.c_str(), structure_name.c_str(), m_currentiteration, structure_handle, NULL))
                                {
                                        ProcessTxnStructure(structure_handle, udtype, udsubtype, testscenario_no, txnspec_no, values_query, txnSpecValueMap, foundTxnSpecValueMap, iteration_params, iteration_sequences, 0);

                                        XMLSchema->Destroy(structure_handle);
                                }
                                else
                                {
                                        AnsiString      msg;

                                        msg.sprintf("Failed to create schema object for Schema: '%s' Structure: '%s'",
                                                                m_schema_handle.c_str(),
                                                                structure_name.c_str());

                                        MessageDlg(msg,
                                                           mtError, TMsgDlgButtons() << mbOK, 0);
                                }

                        } // Found Transaction declaration in MASS TXNS

                        query->Next();
                }
        }
        __finally
        {
                delete query;
                delete values_query;
        }
}

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

void __fastcall TMainForm::ProcessTxnStructure(string structure_handle, unsigned short udtype, unsigned short udsubtype, int testscenario_no, int txnspec_no, TADOQuery *query, TxnSpecValueMap &txnSpecValueMap, FoundTxnSpecValueMap &foundTxnSpecValueMap, IterationParams &iteration_params, IterationSequences &iteration_sequences, unsigned int nested_subscript)
{
        vector<string>                          structure_attributes;
    vector<string>::iterator    s_itr;
    AnsiString                                  sql_statement;

    XMLSchema->GetAttributes(structure_handle, structure_attributes);

    s_itr = structure_attributes.begin();
    while (s_itr != structure_attributes.end())
    {
        string  attribute_handle = (*s_itr);

        string  elementtype;

        XMLSchema->GetAttributeProperty(attribute_handle, "type", elementtype);

        if (elementtype == "field")
        {
            string      datatype;

            XMLSchema->GetAttributeProperty(attribute_handle, "datatype", datatype);

            if (datatype == "Struct")
            {
                ProcessTxnStructure(attribute_handle, udtype, udsubtype, testscenario_no, txnspec_no, query, txnSpecValueMap, foundTxnSpecValueMap, iteration_params, iteration_sequences, 0);
            }
            else
            {
                string  fieldname;
                string  tagvalue;
                string  xpath;

                XMLSchema->GetAttributeProperty(attribute_handle, "tag", tagvalue);

                if (tagvalue.length() > 0)
                {
                    XMLSchema->GetAttributeProperty(attribute_handle, "name", fieldname);
                    XMLSchema->GetAttributeProperty(attribute_handle, "xpath", xpath);

                    AnsiString  lookup_fieldname;
                    AnsiString  display_fieldname;

                    if (nested_subscript == 0)
                    {
                            lookup_fieldname.sprintf("$%s", fieldname.c_str());
                            display_fieldname = fieldname.c_str();
                    }
                    else
                    {
                        lookup_fieldname.sprintf("$%s#%d", fieldname.c_str(), nested_subscript);
                        display_fieldname.sprintf("%s#%d", fieldname.c_str(), nested_subscript);
                    }

                    AnsiString  field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, lookup_fieldname.c_str(), udtype, udsubtype);

                    AnsiString  key;

                    if (nested_subscript == 0)
                                        {
                        key.sprintf("%d_%d_%s",
                                    testscenario_no,
                                    txnspec_no,
                                    fieldname.c_str());
                                        }
                    else
                    {
                        key.sprintf("%d_%d_%s#%d",
                                    testscenario_no,
                                    txnspec_no,
                                    fieldname.c_str(),
                                    nested_subscript);
                    }

                        FoundTxnSpecValuePair   foundpair(key, 0);
                    foundTxnSpecValueMap.insert(foundpair);

                    TxnSpecValueIterator        txnspec_value_itr = txnSpecValueMap.find(key);
                    TxnSpecValue                        &existing_value = (*txnspec_value_itr).second;

                    // Either no existing entry OR the current entry is NOT User supplied
                    // (ie. Ignore field values for existing user supplied items)
                    if ( (txnspec_value_itr == txnSpecValueMap.end()) ||
                         (existing_value.user_supplied == 'N') )
                    {
                            if ( (existing_value.fieldtag       != atoi(tagvalue.c_str()) ||
                                 (existing_value.fieldvalue     != field_value) ||
                                 (existing_value.xpath          != AnsiString(xpath.c_str()))) )
                                                {
                                // Remove the existing value
                                if (txnspec_value_itr != txnSpecValueMap.end())
                            {
                                sql_statement="";
                                sql_statement.sprintf("DELETE FROM TXNSPEC_VALUES WHERE "
                                                      "TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d AND FIELDNAME='%s'",
                                                      testscenario_no,
                                                                                                          txnspec_no,
                                                      fieldname.c_str() );
                                query->SQL->Text = sql_statement;
                                query->ExecSQL();
                                                        }

                            // Add the new value
                            sql_statement="";
                            if (field_value.Length() > 0)
                            {
                                sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, FIELDVALUE, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, XPATH, SUBSCRIPT, USER_SUPPLIED) "
                                                      "VALUES (%s,'%s',%d,%d,'%s','%s','%s',%d,'N')",
                                                      tagvalue.c_str(),
                                                      field_value.c_str(),
                                                      testscenario_no,
                                                      txnspec_no,
                                                      fieldname.c_str(),
                                                      display_fieldname.c_str(),
                                                      xpath.c_str(),
                                                      nested_subscript);
                                                        }
                            else
                            {
                                sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, XPATH, SUBSCRIPT, USER_SUPPLIED) "
                                                      "VALUES (%s,%d,%d,'%s','%s','%s',%d,'N')",
                                                      tagvalue.c_str(),
                                                      testscenario_no,
                                                      txnspec_no,
                                                      fieldname.c_str(),
                                                      display_fieldname.c_str(),
                                                      xpath.c_str(),
                                                      nested_subscript);
                            }

                                query->SQL->Text = sql_statement;
                                query->ExecSQL();
                        }
                    }
                }
                }
                }
        else
        if (elementtype == "repeat")
        {
                string  refcountfield;
                string  maxOccursStr;
            string      refcountAttribute;

            XMLSchema->GetAttributeProperty(attribute_handle, "refcountfield", refcountfield);

            if (!refcountfield.empty())
            {
                    string              refcountAttribute = structure_handle+"."+refcountfield;

                XMLSchema->GetAttributeProperty(refcountAttribute, "max", maxOccursStr);
            }

                        if (maxOccursStr.empty())
            {
                    XMLSchema->GetAttributeProperty(attribute_handle, "maxOccurs", maxOccursStr);
            }

            int maxOccurs = atoi(maxOccursStr.c_str());

            // Limit to 100 elements
            if (maxOccurs > 100)
            {
                    maxOccurs = 100;
            }

            string      repeat_name;
            XMLSchema->GetAttributeProperty(attribute_handle, "name", repeat_name);

            XMLSchema->SetAttributeValue(structure_handle, refcountfield, maxOccurs);

            for (int occurrence=1; occurrence<=maxOccurs; occurrence++)
            {
                                string          repeat_attribute_handle;
                AnsiString      temp;

                temp.sprintf("%s.%d.%s",
                             attribute_handle.c_str(),
                             occurrence,
                             repeat_name.c_str());

                repeat_attribute_handle = temp.c_str();

                string  repeat_attribute_datatype;
                XMLSchema->GetAttributeProperty(repeat_attribute_handle, "datatype", repeat_attribute_datatype);

                if (repeat_attribute_datatype != "Struct")
                {
                    string      fieldname;
                    string      xpath;
                    string      tagvalue;

                    XMLSchema->GetAttributeProperty(repeat_attribute_handle, "tag", tagvalue);

                    if (tagvalue.length() > 0)
                    {
                        XMLSchema->GetAttributeProperty(repeat_attribute_handle, "name", fieldname);
                        XMLSchema->GetAttributeProperty(repeat_attribute_handle, "xpath", xpath);

                        string  lookup_fieldname = "$"+fieldname;
                        AnsiString      field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, lookup_fieldname, udtype, udsubtype);

                        AnsiString      key;

                        key.sprintf("%d_%d_%s.%d",
                                    testscenario_no,
                                    txnspec_no,
                                    fieldname.c_str(),
                                    occurrence);

                                                FoundTxnSpecValuePair   foundpair(key, 0);
                        foundTxnSpecValueMap.insert(foundpair);

                        TxnSpecValueIterator    txnspec_value_itr = txnSpecValueMap.find(key);
                        TxnSpecValue                    &existing_value = (*txnspec_value_itr).second;

                        // Either no existing entry OR the current entry is NOT User supplied
                        // (ie. Ignore field values for existing user supplied items)
                        if ( (txnspec_value_itr == txnSpecValueMap.end()) ||
                             (existing_value.user_supplied == 'N') )
                        {
                            if ( (existing_value.fieldtag       != atoi(tagvalue.c_str()) ||
                                 (existing_value.fieldvalue     != field_value) ||
                                 (existing_value.xpath          != AnsiString(xpath.c_str()))) )
                            {
                                // Remove the existing value
                                if (txnspec_value_itr != txnSpecValueMap.end())
                                {
                                    sql_statement="";
                                    sql_statement.sprintf("DELETE FROM TXNSPEC_VALUES WHERE "
                                                                                                                  "TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d AND FIELDNAME='%s' AND SUBSCRIPT=%d",
                                                          testscenario_no,
                                                          txnspec_no,
                                                          fieldname.c_str(),
                                                          occurrence );
                                    query->SQL->Text = sql_statement;
                                    query->ExecSQL();
                                }

                                AnsiString      subscripted_fieldname;
                                subscripted_fieldname.sprintf("%s#%d", fieldname.c_str(), occurrence);

                                // Add the new value
                                sql_statement="";
                                if (field_value.Length() > 0)
                                {
                                    sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, FIELDVALUE, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, SUBSCRIPT, XPATH, USER_SUPPLIED) "
                                                          "VALUES (%s,'%s',%d,%d,'%s','%s',%d,'%s','N')",
                                                          tagvalue.c_str(),
                                                          field_value.c_str(),
                                                          testscenario_no,
                                                          txnspec_no,
                                                          fieldname.c_str(),
                                                          subscripted_fieldname.c_str(),
                                                          occurrence,
                                                          xpath.c_str());
                                }
                                else
                                {
                                    sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, SUBSCRIPT, XPATH, USER_SUPPLIED) "
                                                          "VALUES (%s,%d,%d,'%s','%s',%d,'%s','N')",
                                                          tagvalue.c_str(),
                                                          testscenario_no,
                                                          txnspec_no,
                                                          fieldname.c_str(),
                                                          subscripted_fieldname.c_str(),
                                                          occurrence,
                                                                                                                  xpath.c_str());
                                }

                                query->SQL->Text = sql_statement;
                                query->ExecSQL();
                            }
                        }
                    } // if (tagvalue.length() > 0)
                } // if (repeat_attribute_datatype != "Struct")
                else
                {
                        ProcessTxnStructure(repeat_attribute_handle, udtype, udsubtype, testscenario_no, txnspec_no, query, txnSpecValueMap, foundTxnSpecValueMap, iteration_params, iteration_sequences, occurrence);
                }
            } // for (int i=1; i<=occurrence; i++)
        }

        s_itr++;
    } // while
}

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

AnsiString TMainForm::LookupParameter(IterationParams &iteration_params, IterationSequences &iteration_sequences, TADOQuery *query, int testscenario_no, const string &param, unsigned short udtype, unsigned short udsubtype)
{
        AnsiString      field_value;
    AnsiString  param_lookup;

    param_lookup.sprintf("#%d_%s", testscenario_no, param.c_str());

        IterationParams::iterator       param_itr = iteration_params.find(param_lookup.c_str());

    if (param_itr == iteration_params.end())
    {
        param_lookup="";
            param_lookup.sprintf("#%d_%s", 0, param.c_str());
            param_itr = iteration_params.find(param_lookup.c_str());
        }

    if (param_itr != iteration_params.end())
    {
        string  param_value = (*param_itr).second;

        if (param_value == "@FORMATVERSION")
        {
            field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, param_value, udtype, udsubtype);
        }
        else
        if (param_value == "@NOW")
        {
            TDateTime   current_time = TDateTime::CurrentDateTime();

            field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy hh:nn:ss").c_str());
        }
        else
        if (param_value == "@UTCNOW")
        {
            TDateTime   current_time = TDateTime::CurrentDateTime() + ((_timezone/3600.0)/24.0);

            field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy hh:nn:ss").c_str());
        }
        else
        if (param_value == "@TODAY")
        {
            TDateTime   current_time = TDateTime::CurrentDateTime();

            field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy").c_str());
        }
        else
        if (param_value == "@YESTERDAY")
        {
            TDateTime   current_time = TDateTime::CurrentDateTime() - 1;

            field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy").c_str());
        }
        else
        if (param_value.substr(0,5) == "@RAND")
        {
                        int     lpos = param_value.find("(")+1;

            string      rand_args = param_value.substr(lpos, param_value.rfind(")")-1);
                        string  lower_bound;
                        string  upper_bound;

            const char *p = rand_args.c_str();
            while ( (*p != '\0') && (*p != ',') )
            {
                lower_bound += *p;
                
                p++;
            }
            if ( *p == ',' )
            {
                p++;
            }
            while ( (*p != '\0') && (*p != ')') )
            {
                upper_bound += *p;

                p++;
            }

            int         lower_int = atoi(lower_bound.c_str());
            int         upper_int = atoi(upper_bound.c_str());
            double  rand_key = (double)rand() / (double)RAND_MAX;

            int rand_value = (rand_key * (upper_int - lower_int)) + lower_int;

            field_value.sprintf("%d", rand_value);
        }
        else
        if (param_value == "@UDTYPE")
        {
            field_value.sprintf("%d", udtype);
        }
                else
        if (param_value == "@UDSUBTYPE")
        {
            field_value.sprintf("%d", udsubtype);
        }
        else
        if (param_value == "@ACCOUNTTYPE")
        {
                int     account_format = 0;
                switch(udtype)
            {
            case 1:     // Card
                account_format = 2;
                break;
            case 2:     // Application
                account_format = 1;
                break;
            case 3:     // Product
                account_format = 3;
                break;
                        case 4: // Other
                account_format = 4;
                break;
            case 5:     // Audit
                account_format = 4;
                break;
            case 6:     // Event
                account_format = 4;
                break;
                        case 7: // Project
                account_format = 4;
                break;
                } // switch

            field_value.sprintf("%d", account_format);
        }
        else
        if (param_value.substr(0,4) == "@SEQ")
        {
            int         lpos = param_value.find("(")+1;
            int         comma_pos = param_value.find(",");
                        string  seqname = param_value.substr( lpos, comma_pos-lpos );

            IterationSequences::iterator s_itr = iteration_sequences.find( seqname );
            if (s_itr != iteration_sequences.end())
            {
                IterationSequence &sequence = (*s_itr).second;

                field_value.sprintf("%d", sequence.value);
                sequence.value += sequence.increment;

                if (sequence.reset_at != 0)
                {
                    if (sequence.value >= sequence.reset_at)
                    {
                        sequence.value = sequence.initial_value;
                    }
                                }

                if (seqname[0] == '#')
                {
                    AnsiString  sql_statement;
                    string              seqgenname = seqname.substr(1,seqname.length()-1);

                    sql_statement.sprintf("UPDATE SEQGEN SET SEQVALUE=%d where PROJECT_CODE='%s' AND ITERATION=%d AND SEQNAME='%s'",
                                                          sequence.value,
                                          m_currentproject.c_str(),
                                          m_currentiteration,
                                          seqgenname.c_str()
                                          );
                    query->SQL->Text = sql_statement;
                    query->ExecSQL();
                }
            }
        }
        else
        if (param_value[0] == '@')
                {
            field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, param_value, udtype, udsubtype);
        }
        else
        {
            field_value.sprintf("%s", param_value.c_str());
        }
    }

    return field_value;
}

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

void __fastcall TMainForm::ImportTestDirectorClick(TObject *Sender)
{
        TestDirectorImportForm->ShowForm( m_currentproject.c_str(), m_currentiteration );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TxnHdrValuesQueryAfterInsert(TDataSet *DataSet)
{
        DataSet->FieldByName("PROJECT_CODE")->AsString  = m_currentproject;
        DataSet->FieldByName("ITERATION")->AsInteger    = m_currentiteration;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ScenarioParametersClick(TObject *Sender)
{
        ScenarioParamsForm->ShowForm(m_currentproject, m_currentiteration, m_testscenario_no);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
        if (Button == mbRight)
        {
        TTreeNode* target_node = TestCaseTreeView->GetNodeAt(X, Y);
        if (target_node != NULL)
        {
                target_node->Selected = true;
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TxnValuesQueryBeforePost(TDataSet *DataSet)
{
//      DataSet->FieldByName( "USER_SUPPLIED" )->AsString = "Y";
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::RemoveUserSuppliedValueClick(TObject *Sender)
{
        if (TxnValuesQuery->FieldByName("USER_SUPPLIED")->AsString == "Y")
    {
            Data_Module->IntegrationDBConnection->BeginTrans();

                TxnValuesQuery->Delete();

        Data_Module->IntegrationDBConnection->CommitTrans();
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::CopyValuesToClipboardBtnClick(TObject *Sender)
{
    AnsiString  clipboard_text;

    Clipboard()->Clear();

    AnsiString  sql_statement;
    TADOQuery   *query = new TADOQuery(this);
    query->Connection = Data_Module->IntegrationDBConnection;

    sql_statement.sprintf("SELECT * FROM TXNSPEC_VALUES "
                          "WHERE TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d "
                                                  "AND (FIELDVALUE IS NOT NULL OR FIELDVALUE<>'') "
                          "ORDER BY FIELDNAME",
                          m_testscenario_no, m_txnspec_no);

        query->SQL->Text = sql_statement;
    query->Open();

    while (!query->Eof)
        {
        AnsiString      clipboard_line;

        clipboard_line.sprintf("%-30.30s\t%s\r\n",
                                                   query->FieldByName("FIELDNAME")->AsString.c_str(),
                                                   query->FieldByName("FIELDVALUE")->AsString.c_str()
                               );

                clipboard_text += clipboard_line;

        query->Next();
    }

        query->Close();

        Clipboard()->SetTextBuf( clipboard_text.c_str() );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildExecutionSchedule( TransactionSpecification & transactionSpecification )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "XPATH,"
                                "FIELDVALUE "
                        "FROM "
                                "TXNSPEC_VALUES "
                        "WHERE "
                                "TXNSPEC_NO=%d AND "
                                "FIELDVALUE IS NOT NULL AND "
                                "OBSOLETE=\'N\' "
                        "ORDER BY "
                                "ORDINAL",
                        transactionSpecification.getTransactionSpecificationNumber() );
                query->SQL->Text = sqlStatement;
                query->Open();

                TransactionSpecificationValue * value = 0;
                while ( !query->Eof )
                {
                        value = &transactionSpecification.getTransactionField(
                                query->FieldByName( "XPATH" )->AsString.c_str() );

                        value->setExpression( query->FieldByName( "FIELDVALUE" )->AsString.c_str() );

                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildExecutionSchedule( TestScenario & testScenario )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "TRANSACTION_SPECIFICATION.TXNSPEC_NO AS TXNSPEC_NO,"
                                "TRANSACTION_SPECIFICATION.UDTYPE AS UDTYPE,"
                                "TRANSACTION_SPECIFICATION.UDSUBTYPE AS UDSUBTYPE,"
                                "MASS_TXNS.NAME AS NAME "
                        "FROM "
                                "TRANSACTION_SPECIFICATION,"
                                "MASS_TXNS "
                        "WHERE "
                                "TESTSCENARIO_NO=%d AND "
                                "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND "
                                "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND "
                                "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND "
                                "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE "
                        "ORDER BY "
                                "SEQ_NO",
                        testScenario.getScenarioNumber() );
                query->SQL->Text = sqlStatement;
                query->Open();

                TransactionSpecification * transaction = 0;
                while ( !query->Eof )
                {
                        transaction = &testScenario.getTransactionSpecification(
                                        query->FieldByName( "TXNSPEC_NO" )->AsInteger,
                                        query->FieldByName( "NAME" )->AsString.c_str() );
                        transaction->setUdType(
                                query->FieldByName( "UDTYPE" )->AsInteger );
                        transaction->setUdSubtype(
                                query->FieldByName( "UDSUBTYPE" )->AsInteger );

                        buildExecutionSchedule( *transaction );

                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::buildExecutionSchedule(
                                        Iteration &                     iteration,
                                        const std::string &     testcaseId )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "TESTSCENARIO_NO,"
                                "REPEAT_COUNT,"
                                "BATCH_SIZE,"
                                "NAME "
                        "FROM "
                                "TEST_SCENARIOS "
                        "WHERE "
                                "TESTCASE_ID=\'%s\' AND "
                                "PROJECT_CODE=\'%s\' AND "
                                "ITERATION=%d "
                        "ORDER BY "
                                "TESTCASE_SEQNO",
                        Utilities::EscapeString( testcaseId ).c_str(),
                        Utilities::EscapeString( iteration.getProjectCode() ).c_str(),
                        iteration.getIterationId() );
                query->SQL->Text = sqlStatement;
                query->Open();

                TestScenario * scenario = 0;
                while ( !query->Eof )
                {
                        scenario = &iteration.getTestScenario(
                                query->FieldByName( "TESTSCENARIO_NO" )->AsInteger );
                        scenario->setBatchSize(
                                !query->FieldByName( "BATCH_SIZE" )->IsNull
                                        ? query->FieldByName( "BATCH_SIZE" )->AsInteger
                                        : 0 );
                        scenario->setRepeatCount(
                                !query->FieldByName( "REPEAT_COUNT" )->IsNull
                                        ? query->FieldByName( "REPEAT_COUNT" )->AsInteger
                                        : 1 );
                        scenario->setScenarioName(
                                query->FieldByName( "NAME" )->AsString.c_str() );

                        buildExecutionSchedule( *scenario );

                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::loadLegacyVariables( DefinedVariableTable & variables, const AnsiString & project, Iteration & iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "NAME,"
                                "FIELDVALUE,"
                                "TESTSCENARIO_NO "
                        "FROM "
                                "ITERATION_PARAMS "
                        "WHERE "
                                "PROJECT_CODE=\'%s\' AND "
                                "ITERATION=%d",
                        project.c_str(),
                        iteration.getIterationId() );
                query->SQL->Text = sqlStatement;
                query->Open();

                AnsiString                      fieldName;
                AnsiString                      xpath;
                AnsiString                      value;
                bool                            qualified;
                DefinedVariable *       variable;
                while ( !query->Eof )
                {
                        fieldName       = query->FieldByName( "NAME" )->AsString;
                        value           = query->FieldByName( "FIELDVALUE" )->AsString;

                        if ( !value.IsEmpty() )
                        {
                                if ( value[ 1 ] == '=' )
                                {
                                        value.Delete( 1, 1 );
                                }

                                if ( !value.IsEmpty() )
                                {
                                        switch ( value[ 1 ] )
                                        {
                                                case '@':
                                                        value[ 1 ] = '=';
                                                        if ( FieldExpression::isFunctor(
                                                                        value.c_str() + 1 ) )
                                                        {
                                                                value += "()";
                                                        }
                                                        break;
                                                default:
                                                        break;
                                        }
                                }
                        }

                        if ( !fieldName.IsEmpty() )
                        {
                                qualified = !query->FieldByName( "TESTSCENARIO_NO" )->IsNull;

                                switch ( fieldName[ 1 ] )
                                {
                                case '$':       // We don't worry about fields here.
                                        break;
                                case '@':
                                        if ( qualified )
                                        {
                                                variable = &variables.defineVariable(
                                                        fieldName.c_str() + 1,
                                                        iteration.getTestScenario(
                                                                query->FieldByName( "TESTSCENARIO_NO" )
                                                                        ->AsInteger ) );
                                        }
                                        else
                                        {
                                                variable = &variables.defineVariable(
                                                        fieldName.c_str() + 1 );
                                        }
                                        variable->setExpression( value.c_str() );
                                        break;
                                default:
                                        break;
                                }
                        }
                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::readSequences( SequenceCollection & sequences, const std::string & project, const int & iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "SEQNAME,"
                                "SEQVALUE "
                        "FROM "
                                "SEQGEN "
                        "WHERE "
                                "PROJECT_CODE=\'%s\' AND "
                                "ITERATION=%d",
                        Utilities::EscapeString( project ).c_str(),
                        iteration );
                query->SQL->Text = sqlStatement;
                query->Open();

                std::string     sequenceName;
                int                     value;
                Sequence *      sequence;
                while ( !query->Eof )
                {
                        sequenceName    = query->FieldByName( "SEQNAME" )->AsString.c_str();
                        value                   = query->FieldByName( "SEQVALUE" )->AsInteger;

                        sequence = &sequences.getSequence( sequenceName, true, 0 );
                        sequence->setValue( value );
                        sequence->setUpdate( true );
                        sequence->setDirty( false );

                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::writeSequences( const SequenceCollection & sequences, const std::string & project, const int & iteration )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                for ( std::map< std::string, Sequence * >::const_iterator
                                sequence = sequences.getCollection().begin();
                                sequence != sequences.getCollection().end();
                                ++sequence )
                {
                        std::stringstream stream;
                        if ( sequence->second->isPersisted() && sequence->second->isDirty() )
                        {
                                if ( sequence->second->isUpdate() )
                                {
                                        stream
                                                << "UPDATE SEQGEN SET "
                                                        << "SEQVALUE=" << sequence->second->getValue()
                                                << " WHERE "
                                                        << "PROJECT_CODE=\'" << Utilities::EscapeString( project ) << "\' AND "
                                                        << "ITERATION=" << iteration << " AND "
                                                        << "SEQNAME=\'" << Utilities::EscapeString( sequence->second->getName() ) << '\'';
                                }
                                else
                                {
                                        stream
                                                << "INSERT INTO SEQGEN ( "
                                                        "PROJECT_CODE,"
                                                        "ITERATION,"
                                                        "SEQNAME,"
                                                        "SEQVALUE "
                                                " ) VALUES ( "
                                                        << '\'' << Utilities::EscapeString( project ) << "\',"
                                                        << iteration << ",\'"
                                                        << Utilities::EscapeString( sequence->second->getName() ) << "\',"
                                                        << sequence->second->getValue()
                                                << " )";
                                }
                                
                                query->SQL->Text = stream.str().c_str();
                                if ( query->ExecSQL() != 1 )
                                {
                                        MTHROW( std::runtime_error, \
                                                "Cannot " \
                                                << ( sequence->second->isUpdate() ? "update" : "insert" ) \
                                                << " sequence \"" \
                                                << sequence->second->getName() \
                                                << "\"." );
                                }
                        }
                }
                SequenceGeneratorQuery->Refresh();              
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::GenerateTestTestCaseBtnClick(TObject *Sender)
{
        std::vector< int > scenarios;
        
        generateTransaction( scenarios );
}
//---------------------------------------------------------------------------

const unsigned __fastcall TMainForm::countTransactionsInIteration( const char * project, const int & iteration )
{
        unsigned count = 0;

        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "COUNT(*) AS COUNT "
                        "FROM "
                                "TRANSACTION_SPECIFICATION "
                        "WHERE "
                                "PROJECT_CODE=\'%s\' AND "
                                "ITERATION=%d",
                        project,
                        iteration );
                query->SQL->Text = sqlStatement;
                query->Open();

                count = ( !query->Eof ? query->FieldByName( "COUNT" )->AsInteger : 0 );
        }
        __finally
        {
                delete query;
                query = 0;
        }

        return ( count );
}
//---------------------------------------------------------------------------

const unsigned __fastcall TMainForm::countTransactionsInScenario( const int & scenario )
{
        unsigned count = 0;

        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "COUNT(*) AS COUNT "
                        "FROM "
                                "TRANSACTION_SPECIFICATION "
                        "WHERE "
                                "TESTSCENARIO_NO=%d",
                        scenario );
                query->SQL->Text = sqlStatement;
                query->Open();

                count = ( !query->Eof ? query->FieldByName( "COUNT" )->AsInteger : 0 );
        }
        __finally
        {
                delete query;
                query = 0;
        }

        return ( count );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::applyTemplatesToTransaction(
                                                                ProgressBar &                                   progressBar,
                                                                const int &                                             transaction,
                                                                const TestScenarioTemplate *    testScenario,
                                                                const TestScenarioTemplate *    all )
{
        TADOQuery * query = 0;
        try
        {
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;

                AnsiString sqlStatement;
                sqlStatement.sprintf(
                        "SELECT "
                                "XPATH,"
                                "FIELDVALUE "
                        "FROM "
                                "TXNSPEC_VALUES "
                        "WHERE "
                                "TXNSPEC_NO=%d AND "
                                "USER_SUPPLIED=\'N\' AND "
                                "CHILD_COUNT=0",
                        transaction );
                query->SQL->Text = sqlStatement;
                query->Open();

                std::string     xpath;
                std::string     value;
                unsigned        matchCount = 0;

                AnsiString fieldValue;
                while ( !query->Eof )
                {
                        xpath = query->FieldByName( "XPATH" )->AsString.c_str();
                        fieldValue = query->FieldByName( "FIELDVALUE" )->AsString;
                        matchCount = ( testScenario ? testScenario->findMatch( value, xpath ) : 0 );

                        if ( matchCount == 1 )
                        {
                                query->Edit();
                                query->FieldByName( "FIELDVALUE" )->AsString = value.c_str();
                                query->Post();
                        }
                        else if ( matchCount > 1 )
                        {
                                MTHROW( std::runtime_error, \
                                        "Ambigious scenario transaction template.  " \
                                        << matchCount \
                                        << " matches found for \"" \
                                        << xpath \
                                        << "\"." );
                        }
                        else
                        {
                                matchCount = ( all ? all->findMatch( value, xpath ) : 0 );
                                if ( matchCount == 1 )
                                {
                                        query->Edit();
                                        query->FieldByName( "FIELDVALUE" )->AsString = value.c_str();
                                        query->Post();
                                }
                                else if ( matchCount > 1 )
                                {
                                        MTHROW( std::runtime_error, \
                                                "Ambigious transaction template.  " \
                                                << matchCount \
                                                << " matches found for \"" \
                                                << xpath \
                                                << "\"." );
                                }
                        }

                        query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::applyTemplatesToScenario( ProgressBar & progressBar, const int & scenario )
{
        /**
         *      Iterate through the collection of transactions defined for this scenario
         *      and for each field attempt to apply every field template defined.  When
         *      multiple fields match, raise an exception and roll any template
         *      applications back.
         */
        TestScenarioTemplate *  testScenario    = m_transactionTemplates.findTestScenarioTemplate( scenario );
        TestScenarioTemplate *  all                             = m_transactionTemplates.findTestScenarioTemplate( 0 );

        if ( testScenario || all )
        {
                TADOQuery * query = 0;
                try
                {
                        query = new TADOQuery( this );
                        query->Connection = Data_Module->IntegrationDBConnection;

                        AnsiString sqlStatement;
                        sqlStatement.sprintf(
                                "SELECT "
                                        "TXNSPEC_NO,"
                                        "NAME "
                                "FROM "
                                        "TRANSACTION_SPECIFICATION,"
                                        "MASS_TXNS "
                                "WHERE "
                                        "TESTSCENARIO_NO=%d AND "
                                        "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND "
                                        "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND "
                                        "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND "
                                        "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE "
                                "ORDER BY "
                                        "TESTSCENARIO_NO,"
                                        "TXNSPEC_NO",
                                scenario );
                        query->SQL->Text = sqlStatement;
                        query->Open();

                        AnsiString message;
                        while ( !query->Eof )
                        {
                                message.sprintf(
                                        " Applying template to %s ...",
                                        query->FieldByName( "NAME" )->AsString.c_str() );
                                MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message;
                                Application->ProcessMessages();

                                applyTemplatesToTransaction(
                                        progressBar,
                                        query->FieldByName( "TXNSPEC_NO" )->AsInteger,
                                        testScenario,
                                        all );
                                progressBar.increment();
                                query->Next();
                        }
                }
                __finally
                {
                        delete query;
                        query = 0;

                        MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "";
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ApplyTemplatesToScenarioClick(TObject *Sender)
{
        // The scenario, our context, is kept in the tag of our parent menu.
        TPopupMenu * menu
                = dynamic_cast< TPopupMenu * >(
                        dynamic_cast< TMenuItem * >( Sender )->GetParentMenu() );
        if ( menu )
        {
                const int scenario = menu->Tag;
                try
                {
                        const TCursor Save_Cursor = Screen->Cursor;
                        try
                        {
                                Screen->Cursor = crHourGlass;

                                const unsigned count = countTransactionsInScenario( scenario );
                                m_progressBar->open( count * 2 );
                                buildTransactionsForScenario(
                                        m_transactionCache,
                                        *m_progressBar,
                                        scenario,
                                        m_schema_handle,
                                        m_currentiteration );
                                
                                try
                                {
                                        Data_Module->IntegrationDBConnection->BeginTrans();
                                        applyTemplatesToScenario( *m_progressBar, scenario );
                                        Data_Module->IntegrationDBConnection->CommitTrans();
                                }
                                catch ( ... )
                                {
                                        Data_Module->IntegrationDBConnection->RollbackTrans();
                                        throw;
                                }
                                m_progressBar->update( count );
                        }
                        __finally
                        {
                                m_progressBar->close();
                                Screen->Cursor = Save_Cursor;
                        }
                }
                catch ( const std::exception & exception )
                {
                        MessageDlg(
                                exception.what(),
                                mtError, TMsgDlgButtons() << mbOK, 0 );
                }
                catch ( ... )
                {
                        MessageDlg(
                                "Unknown exception applying templates to this scenario.",
                                mtError, TMsgDlgButtons() << mbOK, 0 );
                }
        }
}
//---------------------------------------------------------------------------


string __fastcall TMainForm::FindField(const string &structure_handle, int fieldtag)
{
        string                                          field_path;
        vector<string>                          structure_attributes;
        vector<string>::iterator        s_itr;

        XMLSchema->GetAttributes(structure_handle, structure_attributes);

    s_itr = structure_attributes.begin();
    while (s_itr != structure_attributes.end())
    {
        string  elementtype;
        string  datatype;

        XMLSchema->GetAttributeProperty((*s_itr), "type", elementtype);

        if (elementtype == "field")
        {
                XMLSchema->GetAttributeProperty((*s_itr), "datatype", datatype);

                        if (datatype == "Struct")
            {
                field_path = FindField((*s_itr), fieldtag);

                if (!field_path.empty())
                {
                        break;
                }
                        }
                        else
            {
                string  xml_fieldtag;
                XMLSchema->GetAttributeProperty((*s_itr), "tag", xml_fieldtag);

                if ( fieldtag == atoi(xml_fieldtag.c_str()) )
                {
                    field_path = (*s_itr);
                                        break;
                }
            }
                }
        else
        if (elementtype == "repeat")
        {
            string      repeatname;
                        XMLSchema->GetAttributeProperty((*s_itr), "name", repeatname);

            string              repeatAttribute = (*s_itr)+".1";

                        field_path = FindField(repeatAttribute, fieldtag);

            if (!field_path.empty())
            {
                break;
            }
        }

        s_itr++;
        }

    return field_path;
}

void __fastcall TMainForm::FieldEnumValuesDblClick(TObject *Sender)
{
        TADOQuery * query = 0;

        if ( TransactionStructurePageControl->ActivePage == PayloadStructureTabSheet )
        {
                query = TxnValuesQuery;
        }
        else if ( TransactionStructurePageControl->ActivePage == HeaderStructureTabSheet )
        {
                query = TxnHeaderValuesQuery;
        }
        else if ( TransactionStructurePageControl->ActivePage == ObsoleteFieldTabSheet )
        {
                query = TxnObsoleteValuesQuery;
        }

        if ( query )
        {
                if ( query->State != dsEdit )
                {
                        query->Edit();
                }

                query->FieldByName( "FIELDVALUE" )->AsString = FieldEnumValues->Items->Strings[ FieldEnumValues->ItemIndex ];
        }
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
        XMLSchema->Active = false;

        m_Registry->CloseKey();
    delete m_Registry;  
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SetGenerationDirectoryClick(TObject *Sender)
{
        AnsiString      directory;

        if ( SelectDirectory("Select Generation Directory", "c:\\", directory) )
    {
        if (m_Registry != NULL)
                {
            m_Registry->WriteString("MRUGenerationDir", directory);
        }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseGridRowChanging(TObject *Sender,
          int OldRow, int NewRow, bool &Allow)
{
        TCursor Save_Cursor = Screen->Cursor;
        Screen->Cursor = crHourGlass;    // Show hourglass cursor

        try
        {
                TestCasesTabSheet->TabVisible = true;
        MainPageControl->ActivePage = TestCasesTabSheet;
                TestScenariosTabSheet->TabVisible = false;

                if ( (m_currentproject.Length() > 0) && (m_currentiteration != 0) )
        {
                        TestCaseTreeView->Items->BeginUpdate();

            TestCaseTreeView->Items->Clear();

                        AnsiString      sql_statement;

            TADOQuery   *query = new TADOQuery(this);
            query->Connection = Data_Module->IntegrationDBConnection;

            AnsiString  testcase_id = TestCaseQuery->FieldByName("TESTCASE_ID")->AsString;

            sql_statement.sprintf("SELECT * FROM TEST_SCENARIOS "
                                  "WHERE PROJECT_CODE='%s' AND ITERATION=%d "
                                  "AND   TESTCASE_ID='%s' "
                                  "ORDER BY TESTCASE_SEQNO",
                                  m_currentproject.c_str(),
                                  m_currentiteration,
                                                                  testcase_id.c_str());

            query->SQL->Text = sql_statement;
                        query->Open();

                        int count = 0;
                        while (!query->Eof)
                        {
                                AnsiString      testcase_desc;

                                testcase_desc.sprintf("(%d) %s",
                                                                          query->FieldByName("TESTCASE_SEQNO")->AsInteger,
                                                                          query->FieldByName("NAME")->AsString.c_str()
                                                                          );

                                int     testscenario_no = query->FieldByName("TESTSCENARIO_NO")->AsInteger;

                                TTreeNode *testcase_node = TestCaseTreeView->Items->AddObject(NULL, testcase_desc, (void *)testscenario_no);
                                LoadTestCaseNodes(testcase_node);

                                ++count;
                                query->Next();
                        }
                        GenerateTestTestCaseBtn->Enabled = ( count > 0 );

                        delete query;

            TestCaseTreeView->Items->EndUpdate();
        }
    }
        __finally
    {
            Screen->Cursor = Save_Cursor;
    }

    Allow = true;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseQueryAfterClose(TDataSet *DataSet)
{
        TestScenarioToolBar->Enabled = false;
    AddTestCaseNode->Enabled = false;
//      InitTxnBtn->Enabled = false;
//      GenerateAllTxnsBtn->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseQueryAfterOpen(TDataSet *DataSet)
{
        TestScenarioToolBar->Enabled = true;

        AddTestCaseNode->Enabled = true;
//      InitTxnBtn->Enabled = true;
//      GenerateAllTxnsBtn->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SequenceGeneratorQueryAfterInsert(
      TDataSet *DataSet)
{
    DataSet->FieldByName("PROJECT_CODE")->AsString = m_currentproject;
    DataSet->FieldByName("ITERATION")->AsInteger = m_currentiteration;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseQueryBeforePost(TDataSet *DataSet)
{
        DataSet->FieldByName("USECASE_ID")->AsString = DataSet->FieldByName("TESTCASE_ID")->AsString;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewEditing(TObject *Sender,
      TTreeNode *Node, bool &AllowEdit)
{
    if (Node->Level == 0)
    {
                AllowEdit = true;
    }
    else
    {
        AllowEdit = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewEdited(TObject *Sender,
          TTreeNode *Node, AnsiString &S)
{
        // We've enable editing of the root level only, but we'll check anyway.
        if (Node->Level == 0)
        {
                const int   testscenario_no = (int)(Node->Data);
                TADOQuery * query           = 0;

                try
        {
            query = new TADOQuery( this );
                        query->Connection = Data_Module->IntegrationDBConnection;

            AnsiString  sql_statement;
            AnsiString  name;
            sql_statement.sprintf(
                "UPDATE TEST_SCENARIOS SET NAME='%s' WHERE TESTSCENARIO_NO=%d",
                                Utilities::EscapeString( getNameFromNode( name, S ) ).c_str(),
                testscenario_no );
            query->SQL->Text = sql_statement;

            Data_Module->IntegrationDBConnection->BeginTrans();
            try
            {
                query->ExecSQL();
                Data_Module->IntegrationDBConnection->CommitTrans();
            }
            catch ( ... )
            {
                Data_Module->IntegrationDBConnection->RollbackTrans();
                        }
        }
        __finally
        {
            delete query;
        }

    }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestScenarioPropertiesClick(TObject *Sender)
{
        TestScenarioPropertiesForm->ShowForm( m_testscenario_no );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TestCaseTreeViewContextPopup(TObject *Sender,
          TPoint &MousePos, bool &Handled)
{
        TTreeView * view = dynamic_cast< TTreeView * >( Sender );
        if ( view )
        {
                TTreeNode *             Node    = view->GetNodeAt( MousePos.x, MousePos.y );
                const TPoint    screen  = TestCaseTreeView->ClientToScreen( MousePos );

                if ( Node )
                {
                        switch ( Node->Level )
                        {
                        case 0:
                                // Rebuild the transaction templates, they may have changed.
                                buildTransactionTemplates(
                                        m_transactionTemplates,
                                        m_currentproject,
                                        m_currentiteration );

                                ApplyTemplatesToScenario->Enabled = (
                                        m_transactionTemplates.haveTemplatesForScenario(
                                                reinterpret_cast< int >( Node->Data ) ) );

                                ScenarioPopupMenu->Tag = reinterpret_cast< int >( Node->Data );
                                ScenarioPopupMenu->Popup( screen.x, screen.y );
                                break;
                        case 1:
                                TransactionPopupMenu->Popup( screen.x, screen.y );
                                break;
                        }
                }
        }
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::DeleteScenarioClick(TObject *Sender)
{
        bool refresh_testcases = false;

        for ( unsigned selected_item=0;
                  selected_item<TestCaseTreeView->SelectionCount;
                  selected_item++ )
        {
                TTreeNode *     current_node = TestCaseTreeView->Selections[ selected_item ];
                if ( current_node != NULL )
                {
                        if (current_node->Level == 0)   // Remove Test Scenario
                        {
                                // Confirm deletion
                                AnsiString      message;
                                message.sprintf( "Are you sure you want to delete this test scenario?" );

                                if ( MessageDlg( message, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mrYes )
                                {
                                        int     testscenario_no = (int)(current_node->Data);

                                        TADOQuery       *query = new TADOQuery(this);
                                        AnsiString      sql_statement;
                                        query->Connection = Data_Module->IntegrationDBConnection;

                                        try
                                        {
                                                Data_Module->IntegrationDBConnection->BeginTrans();

                                                sql_statement.sprintf(
                                                        "DELETE FROM TXNSPEC_VALUES WHERE TESTSCENARIO_NO=%d",
                                                        testscenario_no );

                                                query->SQL->Text = sql_statement;
                                                query->ExecSQL();

                                                sql_statement="";
                                                sql_statement.sprintf(
                                                        "DELETE FROM TRANSACTION_SPECIFICATION WHERE TESTSCENARIO_NO=%d",
                                                        testscenario_no );

                                                query->SQL->Text = sql_statement;
                                                query->ExecSQL();

                                                sql_statement="";
                                                sql_statement.sprintf(
                                                        "DELETE FROM ITERATION_PARAMS WHERE TESTSCENARIO_NO=%d",
                                                        testscenario_no );

                                                query->SQL->Text = sql_statement;
                                                query->ExecSQL();

                                                sql_statement="";
                                                sql_statement.sprintf(
                                                        "DELETE FROM TEST_SCENARIOS WHERE TESTSCENARIO_NO=%d",
                                                        testscenario_no );

                                                query->SQL->Text = sql_statement;
                                                query->ExecSQL();

                                                Data_Module->IntegrationDBConnection->CommitTrans();

                                                refresh_testcases = true;

                                                ResequenceTestCases(current_node);
                                        }
                                        catch(...)
                                        {
                                                Data_Module->IntegrationDBConnection->RollbackTrans();
                                        }

                                        delete query;
                                }
                        }
                }
        }

        if (refresh_testcases)
        {
                bool allow;
                TestCaseGridRowChanging(Sender, 0, 1, allow = true);
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::InitialiseTransactionActionExecute(TObject *Sender)
{
        TCursor Save_Cursor = Screen->Cursor;
        Screen->Cursor = crHourGlass;    // Show hourglass cursor

        try
        {
                TTreeNode * current_node = TestCaseTreeView->Selected;

                if ( current_node != NULL )
                {
                        if ( current_node->Level == 1 ) // Initialise Txn
                        {
//                              int testscenario_no     = (int)(current_node->Parent->Data);
//                              int txnspec_no          = (int)(current_node->Data);
//
                                MessageDlg("Not supported yet", mtInformation, TMsgDlgButtons() << mbOK, 0);
                        }
                }
        }
        __finally
        {
                Screen->Cursor = Save_Cursor;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::InitialiseCopyParametersTabSheet(TObject *Sender)
{
        TADOQuery * query = 0;

        AnsiString sqlStatement;
        AnsiString iteration;
        try
        {
                SourceIterationComboBox->Clear();
                query = new TADOQuery( this );
                query->Connection = Data_Module->IntegrationDBConnection;
                sqlStatement.sprintf(
                        "SELECT * FROM ITERATIONS WHERE PROJECT_CODE='%s' ORDER BY ITERATION",
                        m_currentproject.c_str() );
                query->SQL->Text = sqlStatement;
                query->Open();
                while ( !query->Eof )
                {
                        if ( query->FieldByName( "ITERATION" )->AsInteger != m_currentiteration )
                        {
                                iteration.sprintf( "%d", query->FieldByName( "ITERATION" )->AsInteger );
                                SourceIterationComboBox->AddItem(
                                        iteration,
                                        ( TObject * )( query->FieldByName( "ITERATION" )->AsInteger ) );
                        }
                query->Next();
                }
        }
        __finally
        {
                delete query;
                query = 0;
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::CopyClick(TObject *Sender)
{
        /*
         *      Copy the given iteration into this iteration.  We do not clear this
         *      iteration first.
         */

        CopyIterationProcedure->Parameters->ParamValues[ "projectCode" ]        = m_currentproject;
        CopyIterationProcedure->Parameters->ParamValues[ "fromIteration" ]      = (int)(SourceIterationComboBox->Items->Objects[SourceIterationComboBox->ItemIndex]);
        CopyIterationProcedure->Parameters->ParamValues[ "toIteration" ]        = m_currentiteration;
        CopyIterationProcedure->ExecProc();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TransactionValueGrid1BeforeContractNode(
          TObject *Sender, int ARow, int ARowReal, bool &Allow)
{
        Allow = ( TransactionValueGrid->RealRow <= ARowReal );
}
//---------------------------------------------------------------------------

const bool __fastcall TMainForm::isParent( const int & ordinal )
{
        return ( std::find(
                                m_parents.begin(),
                                m_parents.end(),
                                ordinal ) != m_parents.end() );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TransactionValueGridCanEditCell(TObject *Sender,
          int ARow, int ACol, bool &CanEdit)
{
#if INCLUDE_PARENTS
        /**
         *       Use the real row as the ordinal number into the dataset.  When the row
         *       has children, it cannot be edited, otherwise it can.
         */
        CanEdit = !isParent( TransactionValueGrid->RealRowIndex( ARow ) );
#endif
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TransactionValueGridGetDisplText(
          TObject *Sender, int ACol, int ARow, AnsiString &Value)
{
#if INCLUDE_PARENTS
        const int row = TransactionValueGrid->RealRowIndex( ARow );
        if ( row > 0 )
        {
                switch ( TransactionValueGrid->RealColIndex( ACol ) )
                {
                case 2: // The value column.
                        /**
                         *      Use the real row as the ordinal number into the dataset.  When
                         *      the row has children, it cannot be edited, otherwise it can.
                         */
                        if ( isParent( row ) )
                        {
                                Value = "{...}";
                        }
                        break;
                case 3: // The checkbox column.
                        if ( isParent( row ) )
                        {
                                Value = "";
                        }
                        break;
                }
        }
#endif
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TransactionGridRowChanging( TADOQuery & query, const char * structureName )
{
        TxnFieldComments->Lines->Clear();
        FieldEnumValues->Clear();
        FieldDatatype->Clear();
        DocDataType->Clear();
        IncludedInMac->Checked = false;

        if ( query.State != dsInactive && query.RecordCount )
        {
                if (!m_schema_handle.empty())
                {
                        const int       fieldtag = query.FieldByName("FIELDTAG")->AsInteger;
                        string          structure_handle;

                        try
                        {
                                XMLSchema->Create(m_schema_handle.c_str(), structureName, m_currentiteration, structure_handle, NULL);

                                string  field_path = FindField(structure_handle, fieldtag);

                                if (!field_path.empty())
                                {
                                        std::string     fieldcomments;
                                        std::string     datatype;
                                        std::string     docdatatype;
                                        std::string     includedInMac;

                                        XMLSchema->GetAttributeProperty(field_path, "comments", fieldcomments);
                                        TxnFieldComments->Lines->Add(fieldcomments.c_str());

                                        XMLSchema->GetAttributeProperty(field_path, "datatype", datatype);
                                        FieldDatatype->Text = datatype.c_str();

                                        XMLSchema->GetAttributeProperty(field_path, "docdatatype", docdatatype );
                                        DocDataType->Text = docdatatype.c_str();

                                        XMLSchema->GetAttributeProperty(field_path, "inMac", includedInMac );
                                        IncludedInMac->Checked = ( includedInMac == "true" );

                                        string valuemap;

                                        XMLSchema->GetAttributeProperty(field_path, "valuemap", valuemap);

                                        if (!valuemap.empty())
                                        {
                                                vector<string>                          enum_values;
                                                if (XMLSchema->GetEnumerationValues(m_schema_handle, valuemap.c_str(), enum_values))
                                                {
                                                        vector<string>::iterator        eitr = enum_values.begin();
                                                        while (eitr != enum_values.end())
                                                        {
                                                                FieldEnumValues->AddItem( (*eitr).c_str(), NULL);

                                                                ++eitr;
                                                        }
                                                }
                                        }
                                }
                        }
                        __finally
                        {
                                XMLSchema->Destroy( structure_handle );
                        }
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TransactionValueGridRowChanging(TObject *Sender,
          int OldRow, int NewRow, bool &Allow)
{
        TransactionGridRowChanging( *TxnValuesQuery, m_structure_name.c_str() );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ObsoleteFieldGridRowChanging(TObject *Sender,
          int OldRow, int NewRow, bool &Allow)
{
        TransactionGridRowChanging( *TxnObsoleteValuesQuery, m_structure_name.c_str() );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::HeaderStructureGridRowChanging(TObject *Sender,
          int OldRow, int NewRow, bool &Allow)
{
        TransactionGridRowChanging( *TxnHeaderValuesQuery, g_headerStructure );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::HeaderStructureTabSheetShow(TObject *Sender)
{
        TransactionGridRowChanging( *TxnHeaderValuesQuery, g_headerStructure );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::PayloadStructureTabSheetShow(TObject *Sender)
{
        TransactionGridRowChanging( *TxnValuesQuery, m_structure_name.c_str() );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ObsoleteFieldTabSheetShow(TObject *Sender)
{
        TransactionGridRowChanging( *TxnObsoleteValuesQuery, m_structure_name.c_str() );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::MainStatusBarResize(TObject *Sender)
{
        if ( m_progressBar )
        {
                RECT Rect;
                MainStatusBar->Perform( SB_GETRECT, 0, (LPARAM)&Rect );

                const int progressPanel = 1;
                int offset = 0;
                for ( int i = 0; i < progressPanel; i++ )
                {
                        offset += MainStatusBar->Panels->Items[ i ]->Width;
                }

                m_progressBar->resize(
                        Rect.top,
                        Rect.left + offset,
                        MainStatusBar->Panels->Items[ progressPanel ]->Width,
                        Rect.bottom - Rect.top );
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TransactionValueGridKeyDown(TObject *Sender,
      WORD &Key, TShiftState Shift)
{
        if ( Key == 'F' )
        {
                TShiftState mask;
                mask << ssCtrl;

                if ( Shift * mask == mask )
                {
                        TransactionValueGridFindDialog->Execute();
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::HeaderStructureGridKeyDown(TObject *Sender,
      WORD &Key, TShiftState Shift)
{
        if ( Key == 'F' )
        {
                TShiftState mask;
                mask << ssCtrl;

                if ( Shift * mask == mask )
                {
                        HeaderStructureGridFindDialog->Execute();
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ObsoleteFieldGridKeyDown(TObject *Sender,
          WORD &Key, TShiftState Shift)
{
        if ( Key == 'F' )
        {
                TShiftState mask;
                mask << ssCtrl;

                if ( Shift * mask == mask )
                {
                        ObsoleteFieldGridFindDialog->Execute();
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ImportTransactionActionExecute(TObject *Sender)
{
        TTreeNode * currentNode = TestCaseTreeView->Selected;

        if ( currentNode )
        {
                // Are we importing a scenario, or a single transaction?
                if ( currentNode->Level == 0 )
                {
                        const int testScenarioNumber
                                = reinterpret_cast< int >( currentNode->Data );

                        if ( ImportTransactionParametersForm->ShowModal() == mrOk )
                        {
                                for ( int i=0; i<ImportTransactionParametersForm->ImportFileListBox->Items->Count; i++ )
                                {
                                        if ( ImportTransactionParametersForm->ImportFileListBox->Selected[ i ] )
                                        {
                                                importTransaction(
                                                        testScenarioNumber,
                                                        ImportTransactionParametersForm
                                                                ->ImportProfileComboBox->Text,
                                                        ImportTransactionParametersForm
                                                                ->ImportFileListBox->Items->Strings[ i ] );
                                        }
                                }
                        }
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::importTransaction( const int & testScenarioNumber, const AnsiString & profile, const AnsiString & file )
{
        UdDrainFile drainFile(
                *XMLSchema->GetSchemaWrapperFactory(),
                *XMLSchema->GetSchema() );

        if ( drainFile.read( profile == "TDS", m_currentiteration, file.c_str() ) )
        {
                const unsigned int count = drainFile.getTransactionCount();
                for ( unsigned int transaction=0; transaction<=count; ++transaction )
                {
                        // add each transaction to the identified test scenario number.
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::IterationCopyButtonClick(TObject *Sender)
{
        if ( !m_currentproject.IsEmpty() && m_currentiteration )
        {
                CopyIterationForm->ShowForm( m_currentproject, m_currentiteration );
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::generateTransaction( std::vector< int > & scenarios )
{
        if ( GenerationPropertiesForm->ShowModal() == mrOk )
        {
                const bool                              generateHeaders = GenerationPropertiesForm->GenerateHeadersCheckBox->Checked;
                const std::string               folder                  = GenerationPropertiesForm->GenerationFolderDirectoryEdit->Text.c_str();
                const std::string               batchPrefix             = GenerationPropertiesForm->DrainFilePrefixEdit->Text.c_str();
                const std::string               batchSuffix             = GenerationPropertiesForm->DrainFileSuffixEdit->Text.c_str();
                const bool                              buildManifest   = GenerationPropertiesForm->BuildManifestCheckBox->Checked;
                const std::string               manifestPrefix  = GenerationPropertiesForm->ManifestPrefixEdit->Text.c_str();
                const std::string               manifestSuffix  = GenerationPropertiesForm->ManifestSuffixEdit->Text.c_str();
                const std::string               securityServer  = GenerationPropertiesForm->SecurityServerPipeEdit->Text.c_str();
                const unsigned short    keyNumber               = GenerationPropertiesForm->KeyNumberEdit->Text.ToInt();
                const unsigned short    keyVersion              = GenerationPropertiesForm->KeyVersionEdit->Text.ToInt();
                const std::string               pathmapTarget   = GenerationPropertiesForm->PathmapTargetEdit->Text.c_str();
                const int                               macAlgorithm    = GenerationPropertiesForm->MacAlgorithmComboBox->ItemIndex;

                /**
                        Create a transaction stream into our generation folder, and generate
                        the transactions into it.  We need to know whether we have to prepend
                        header (i.e., whether it is a .xdr which has a header, or a .devud which
                        doesn't).
                 */

                const TCursor                           Save_Cursor                                     = Screen->Cursor;
                bool                                            transactionOpen                         = false;
                ICryptographicServerProxy *     cryptographicServerProxy        = 0;
                IMessageDigest *                        messageDigest                           = 0;
                IHash *                                         hash                                            = 0;

                try
                {
                        if ( m_securityWrapperFactory )
                        {
                                cryptographicServerProxy = m_securityWrapperFactory
                                        ->createCryptographicServerProxy( securityServer.c_str() );
                                if ( cryptographicServerProxy )
                                {
                                        if ( cryptographicServerProxy->getModuleCount() )
                                        {
                                                /**
                                                 *      We don't know which module will be used to compute the
                                                 *      MAC (security doesn't tell us), so until they do we
                                                 *      assume its the first module.
                                                 */
                                                const unsigned int serialNumber =
                                                        cryptographicServerProxy->getSerialNumber( 0 );

                                                /**
                                                        We now need to turn the 4-byte serial number into an
                                                        8-byte diversifier.  Apparently, we must do this by
                                                        writing the serial number into the lower 4-bytes in big
                                                        endian.  An API is being added to crypto to do this:
                                                        until it is there we need to do it ourselves.
                                                 */
                                                unsigned char buffer[ 8 ];

                                                buffer[ 0 ] = 0;
                                                buffer[ 1 ] = 0;
                                                buffer[ 2 ] = 0;
                                                buffer[ 3 ] = 0;
                                                buffer[ 4 ] = ( serialNumber >> 24 ) & 0xFF;
                                                buffer[ 5 ] = ( serialNumber >> 16 ) & 0xFF;
                                                buffer[ 6 ] = ( serialNumber >>  8 ) & 0xFF;
                                                buffer[ 7 ] = ( serialNumber       ) & 0xFF;

                                                messageDigest = m_securityWrapperFactory
                                                        ->createMessageDigest(
                                                                *cryptographicServerProxy,
                                                                keyNumber,
                                                                keyVersion,
                                                                buffer,
                                                                sizeof( buffer ) );
                                                /**
                                                 *      If we need to compute the MAC by computing the MAC
                                                 *      of the SHA-1 hash, then we create the hash object
                                                 *      here.
                                                 */
                                                if ( macAlgorithm == 1 )
                                                {
                                                        hash = m_securityWrapperFactory->createHash();
                                                }
                                        }
                                        else
                                        {
                                                MWARNING( "Cryptographic server has no modules." );
                                        }
                                }
                        }

                        Screen->Cursor = crHourGlass;
                        Data_Module->IntegrationDBConnection->BeginTrans();
                        transactionOpen = true;

                        TransactionStream stream(
                                folder,
                                batchPrefix,
                                batchSuffix,
                                buildManifest,
                                manifestPrefix,
                                manifestSuffix,
                                pathmapTarget );
                        Iteration iteration(
                                m_currentproject.c_str(),
                                m_currentiteration,
                                *XMLSchema->GetSchemaWrapperFactory(),
                                *XMLSchema->GetSchema(),
                                m_schema_handle );
                        DefinedVariableTable    definedVariableTable;
                        SequenceCollection              sequences;
                        TimeEstimate                    timeEstimate( *MainStatusBar->Panels->Items[ 0 ] );
                        EvaluationContext               context(
                                definedVariableTable,
                                sequences,
                                *m_progressBar,
                                messageDigest,
                                hash,
                                cryptographicServerProxy,
                                timeEstimate );

                        buildExecutionSchedule(
                                iteration,
                                TestCaseQuery->FieldByName( "TESTCASE_ID" )->AsString.c_str() );
                        loadLegacyVariables(
                                definedVariableTable,
                                m_currentproject.c_str(),
                                iteration );
                        readSequences(
                                sequences,
                                m_currentproject.c_str(),
                                m_currentiteration );

                        try
                        {
                                int             count           = 0;
                                bool    generated       = false;
                                
                                if ( scenarios.empty() )
                                {
                                        count = iteration.getTransactionCount();

                                        m_progressBar->open( count );
                                        timeEstimate.start( count );

                                        generated = iteration.generate(
                                                stream,
                                                generateHeaders,
                                                context );
                                }
                                else
                                {
                                        std::vector< int >::const_iterator where = scenarios.begin();
                                        for ( where = scenarios.begin();
                                                  where != scenarios.end();
                                                  ++where )
                                        {
                                                count += iteration.
                                                        findTestScenario( *where ).getTransactionCount();
                                        }

                                        m_progressBar->open( count );
                                        timeEstimate.start( count );

                                        generated = true;
                                        for ( where = scenarios.begin();
                                                  where != scenarios.end();
                                                  ++where )
                                        {
                                                if ( !iteration.findTestScenario( *where ).generate(
                                                                stream,
                                                                generateHeaders,
                                                                context ) )
                                                {
                                                        generated = false;
                                                        break;
                                                }
                                        }
                                }

                                if ( generated )
                                {
                                        writeSequences(
                                                sequences,
                                                m_currentproject.c_str(),
                                                m_currentiteration );

                                        Data_Module->IntegrationDBConnection->CommitTrans();
                                        transactionOpen = false;
                                }
                        }
                        __finally
                        {
                                timeEstimate.stop();
                                m_progressBar->close();
                        }
                }
                __finally
                {
                        if ( hash )
                        {
                                m_securityWrapperFactory->destroyHash( *hash );
                                hash = 0;
                        }
                        if ( messageDigest )
                        {
                                m_securityWrapperFactory
                                        ->destroyMessageDigest( *messageDigest );
                                messageDigest = 0;
                        }
                        if ( cryptographicServerProxy )
                        {
                                m_securityWrapperFactory
                                        ->destroyCryptographicServerProxy( *cryptographicServerProxy );
                                cryptographicServerProxy = 0;
                        }

                        if ( transactionOpen )
                        {
                                Data_Module->IntegrationDBConnection->RollbackTrans();
                        }
                        Screen->Cursor = Save_Cursor;
                }
        }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::GenerateActionExecute(TObject *Sender)
{
        TTreeNode *                     currentNode = 0;
        std::vector< int >      scenarios;

        for ( unsigned selection=0;
                  selection<TestCaseTreeView->SelectionCount;
                  selection++ )
        {
                currentNode = TestCaseTreeView->Selections[ selection ];
                if ( currentNode )
                {
                        scenarios.push_back( reinterpret_cast< int >( currentNode->Data ) );
                }
        }
        generateTransaction( scenarios );
}
//---------------------------------------------------------------------------