1. Create a command which converts a mixed case string to upper case. 2. Same as #1 but add a reverse command and intentionaly undo the change. 3. Add the command and reverse and a little nasty suprise to force the CommandFrame to roll-back the commands automatically because of a problem in the transaction.
/*
CoreLinux++
Copyright (C) 2000 CoreLinux Consortium
The CoreLinux++ Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The CoreLinux++ Library Library is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <corelinux/Common.hpp>
#if !defined(__COMMANDFRAME__HPP)
#include <corelinux/CommandFrame.hpp>
#endif
#include <UpperCaseCommand.hpp>
#include <RestoreCaseCommand.hpp>
using namespace corelinux;
#include <iostream>
#include <exception>
//
// In module function prototypes
//
int main( void );
//
// General Functions
//
void doTestOne( void );
void doTestTwo( void );
void doTestThree( void );
void handleAssertion( AssertionCref );
void handleException( ExceptionCref );
//
// Global data
//
//
// Main entry point
//
int main( void )
{
cout << endl;
//
// Practice graceful exception management
//
try
{
//
// Run the various tests
//
doTestOne();
doTestTwo();
doTestThree();
}
catch( CommandFrameException aException )
{
cerr << "Received CommandFrameException!" << endl;
handleException(aException);
}
catch( AssertionRef aAssert )
{
handleAssertion(aAssert);
}
catch( ExceptionRef aException )
{
handleException(aException);
}
catch( std::exception & e )
{
cerr << e.what() << endl;
}
catch( ... )
{
cerr << "Unknown exception." << endl;
}
return 0;
}
//
// Some utility functions
//
CommandFramePtr createTransaction( bool autoMode = true );
void destroyTransaction( CommandFramePtr );
void displayResults( CommandFramePtr );
CommandPtr createUpperCommand( void );
void cleanupCommands( CommandFramePtr );
// Test One Simple
void doTestOne( void )
{
cout << endl;
cout << "With the first test we create a command that " << endl;
cout << "converts a string to upper case." << endl;
cout << endl;
CommandFramePtr aTransaction(NULLPTR);
try
{
aTransaction = createTransaction( false );
aTransaction->addCommand( createUpperCommand() );
aTransaction->execute();
displayResults( aTransaction );
destroyTransaction( aTransaction );
}
catch( ExceptionRef aExcp )
{
if( aTransaction != NULLPTR )
{
destroyTransaction( aTransaction );
}
else
{
; // do nothing
}
throw;
}
}
CommandPtr createUpperAndReverseCommand( void );
// Test two (imagine a undo stack!!!
void doTestTwo( void )
{
cout << endl;
cout << "With the next test we create a command that " << endl;
cout << "converts a string to upper case. We also add " << endl;
cout << "an undo command, we execute and then undo the " << endl;
cout << "change displaying as we go. THINK UNDO STACK!!! " << endl;
cout << endl;
CommandFramePtr aTransaction(NULLPTR);
try
{
aTransaction = createTransaction( true );
aTransaction->addCommand( createUpperAndReverseCommand() );
aTransaction->execute();
displayResults( aTransaction );
aTransaction->executeReverse();
displayResults( aTransaction );
destroyTransaction( aTransaction );
}
catch( ExceptionRef aExcp )
{
if( aTransaction != NULLPTR )
{
destroyTransaction( aTransaction );
}
else
{
; // do nothing
}
throw;
}
}
// Bogus run on purpose!
//
// The nasty ugly that excercises the CommandFrame
// rollback
//
class UglyCommand : public Command
{
public:
UglyCommand( void )
:
Command()
{
; // do nothing
}
virtual ~UglyCommand( void )
{
; // do nothing
}
virtual void execute( void )
{
throw Exception("Candy gram for Mungo",LOCATION);
}
};
void doTestThree( void )
{
cout << endl;
cout << "In this test, we put a nasty little command that " << endl;
cout << "forces the CommandFrame to rollback itself AFTER " << endl;
cout << "the UpperCaseCommand. The resulting output should " << endl;
cout << "show that the original string is restored." << endl;
cout << endl;
CommandFramePtr aTransaction(NULLPTR);
try
{
aTransaction = createTransaction( true );
aTransaction->addCommand( createUpperAndReverseCommand() );
aTransaction->addCommand( new UglyCommand );
aTransaction->execute();
displayResults( aTransaction );
destroyTransaction( aTransaction );
}
catch( ExceptionRef aExcp )
{
if( aTransaction != NULLPTR )
{
destroyTransaction( aTransaction );
}
else
{
; // do nothing
}
throw;
}
}
//
// Allocate a CommandFrame
//
CommandFramePtr createTransaction( bool autoMode )
{
return new CommandFrame( autoMode );
}
//
// Destroy the command frame
//
void destroyTransaction( CommandFramePtr aTransaction )
{
cleanupCommands( aTransaction );
delete aTransaction;
}
//
// Iterate the results
//
void displayResults( CommandFramePtr aTransaction )
{
REQUIRE( aTransaction != NULLPTR );
Commands aCollection;
WorkState aRunFlag( aTransaction->getState() );
cout << "Transaction state = " <<
( aRunFlag == COMPLETED ? "Success" :
( aRunFlag == REVERSED ? "Rolled back" : "Invalid" ) ) << endl;
aTransaction->getCommands(aCollection);
CommandsIterator begin( aCollection.begin() );
while( begin != aCollection.end() )
{
if( dynamic_cast<UpperCaseCommandPtr>((*begin)) != NULLPTR )
{
cout << "Upper case results = " <<
dynamic_cast<UpperCaseCommandPtr>((*begin))->getNewValue() << endl;
}
++begin;
}
cout << endl;
}
//
// Create the to UpperCase command
//
CommandPtr createUpperCommand( void )
{
string aString;
cout << "Enter a mixed case string : ";
cin >> aString;
return new UpperCaseCommand( aString );
}
//
// Create the Upper command and the ability
// to restore it.
//
CommandPtr createUpperAndReverseCommand( void )
{
CommandPtr baseCmd( createUpperCommand() );
CHECK( baseCmd != NULLPTR );
CommandPtr undoCmd( new RestoreCaseCommand );
CHECK( undoCmd != NULLPTR );
baseCmd->setReverseCommand( undoCmd );
return baseCmd;
}
//
// Iterates through the transaction and deletes
// the commands and reverse commands
//
void cleanupCommands( CommandFramePtr aTransaction )
{
REQUIRE( aTransaction != NULLPTR );
Commands aCollection;
aTransaction->getCommands(aCollection);
CommandsIterator begin( aCollection.begin() );
while( begin != aCollection.end() )
{
CommandPtr aCmdPtr( static_cast<CommandPtr>(*begin) );
if( aCmdPtr->getReverseCommand() != NULLPTR )
{
delete aCmdPtr->getReverseCommand();
aCmdPtr->setReverseCommand( NULLPTR );
}
else
{
; // do nothing
}
delete aCmdPtr;
++begin;
}
}
//
// Error handlers
//
void handleAssertion( AssertionCref aAssert )
{
cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" <<
"Assertion: ";
if( aAssert.getType() == Assertion::NEVERGETHERE )
{
cerr << "NEVER_GET_HERE";
}
else
{
if( aAssert.getType() == Assertion::REQUIRE )
{
cerr << "REQUIRE";
}
else if( aAssert.getType() == Assertion::ENSURE )
{
cerr << "ENSURE";
}
else if( aAssert.getType() == Assertion::CHECK )
{
cerr << "CHECK";
}
else
{
cerr << "ASSERT";
}
cerr << "( " << aAssert.getWhy() << " )";
}
cerr << endl;
}
void handleException( ExceptionCref aExcp )
{
cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
"Exception: " << aExcp.getWhy() << endl;
}
/*
Common rcs information do not modify
$Author: prudhomm $
$Revision: 1.2 $
$Date: 2000/08/31 22:49:02 $
$Locker: $
*/