In our scenario we have non-typed composites (other than the fact they are Equipment) and concrete equipment types (HardDrive, PowerSupply).
We could have created concrete composites (Bus, Case, etc.) and added semantics to them. For example, is it semantically correct for a Case to have a hard-drive, or a Bus to have a power-supply? We leave that to the curious.
We use the TransparentComponent to reduce the amount of type checking. This has its drawbacks as can be seen in the recursion function "dumpComposites".
/*
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 <Common.hpp>
#include <TransparentComponent.hpp>
#include <EquipmentComposite.hpp>
#include <PowerSupply.hpp>
#include <HardDrive.hpp>
using namespace corelinux;
#include <iostream>
#include <exception>
//
// In module function prototypes
//
int main( void );
//
// Routine to walk tree
//
void dumpComposites( EquipmentRef );
//
// Functions that work with Engine types
//
void handleAssertion( AssertionCref );
void handleException( ExceptionCref );
int main( void )
{
//
// Practice gracefull exception management
//
cout << endl;
try
{
//
// Build up a part-whole hierarchy with
// some composites
//
EquipmentComposite aSystem("System");
EquipmentComposite aCase("Case");
EquipmentComposite aBus("Bus");
//
// And leafs
//
PowerSupply aPowerSupply("200 Watt Supply");
HardDrive aHardDrive("40 Gigabyte Drive");
//
// Build up the hierarchy
//
aSystem.addComponent( &aCase );
aCase.addComponent( &aPowerSupply );
aCase.addComponent( &aBus );
aBus.addComponent( &aHardDrive );
dumpComposites(aSystem);
//
// Our composits rid themselves during
// auto destruction.
//
}
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;
}
//
// A depth recursive routine which checks for
// exceptions based on leaf/composite
//
void dumpComposites( EquipmentRef aRef )
{
Iterator<EquipmentPtr> *aIterator( NULLPTR );
try
{
aIterator = aRef.createIterator();
cout << endl;
cout << "Composite : " << aRef.getName() << " has" ;
//
// If we have anything but the nul iterator, dig
// deeper.
//
if( aIterator->isValid() )
{
cout << " components " << " with a total power requirement of " <<
aRef.getPower() << " watts." << endl;
do
{
dumpComposites( *aIterator->getElement() );
aIterator->setNext();
} while( aIterator->isValid() );
}
else
{
cout << " no components." << endl;
}
//
// Because of the implementation, this step
// is optional as the composit maintains the
// list of iterators that it "loans" out. BUT
// this is memory friendly in larger scale
// scenarios
//
aRef.destroyIterator( aIterator );
}
//
// This shows how the transparent type implementation needs to
// watch for using leaves in a composit scenario.
//
catch( InvalidCompositeExceptionRef icExcp )
{
cerr << "Attempt to access a leaf as composite exception" << endl;
cerr << aRef.getName() << " is a Leaf not a composite!" << endl;
cout << aRef.getName() << " requires " << aRef.getPower() << " watts." << endl;
}
}
//
// Peform default (just show it)
//
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:01 $
$Locker: $
*/