// Purpose.?Composite, Builder, Iterator, Memento, Visitor demo
//
// Discussion.?Composite is a fairly fundamental pattern - it uses, or is
// used by, many other patterns.?Iterator can be used to traverse a
// Composite [GOF, p173].?Visitor can be used to apply an operation over
// an object structure defined by Composite [GOF, p344].?Builder often
// builds a Composite [GOF, p106].?Iterator can use Memento to capture
// the state of an iteration [GOF, p271].
//
// Input (composit.dat):
//牋?a 1 2 b 6 d 13 14 15 d 7 8 b 3 4 5 c 9 10 11
//牋? e 16 17 g 20 g 18 e 12 f 19 f c a
//
// In-memory structures:
//牋?a:12?^b345? ^c
//牋?b:6? ^d78
//牋?c:9?10?11?^e?12? ^f
//牋?d:?13? 14?15牋牋牋牋牋牋牋牋牋
//牋? e:?16?17?^g?18
//牋?f:?19
//牋?g:? 20
//
// Output:
//牋? 1 2 6 13 14 15 7 8 3 4 5 9 10 11 16 17 20 18 12 19
//牋?a 1 2 b 6 d 13 14 15 7 8 3 4 5 c 9 10 11 e 16 17 g 20 18 12 f 19
//牋? composites = 7.?primitives = 20.?total value = 210.?average value = 10

#include <stdio.h>
#include <iostream.h>
#include <fstream.h>

class Composite;
class Primitive;

class Visitor {
public:
virtual void visit( Composite* ) = 0;
virtual void visit( Primitive* ) = 0;
};

class ListVisitor : public Visitor {
public:
/* virtual */ void visit( Composite* );
/* virtual */ void visit( Primitive* );
};

class TotalVisitor : public Visitor {
public:
TotalVisitor() { totalComposites = totalPrimitives = totalValue = 0; }
/* virtual */ void visit( Composite* c ) { totalComposites++; }
/* virtual */ void visit( Primitive* );
void reportTotals()?{
牋牋? cout << "composites = " << totalComposites
牋牋牋牋 << ".?primitives = " << totalPrimitives
牋牋牋牋 << ".?total value = " << totalValue
牋牋牋牋 << ".?average value = " << totalValue / totalPrimitives << endl; }
private:
int? totalComposites;
int?totalPrimitives;
int? totalValue;
};

class Iterator;

class Component {
public:
enum ComponentType { PrimitiveT, CompositeT };
virtual void traverse()牋牋牋牋 = 0;
virtual void add( Component* )?{ }
virtual ComponentType getType() = 0;
virtual void accept( Visitor& ) = 0;
};

class Primitive : public Component {
public:
Primitive( int _value )牋牋牋牋牋牋牋牋 { value_ = _value; }
void traverse()牋牋牋牋牋牋牋牋牋牋牋牋 { cout << value_ << " "; }
ComponentType getType()牋牋牋牋牋牋牋牋 { return PrimitiveT; }
int getValue()牋牋牋牋牋牋牋牋牋牋牋牋?{ return value_; }
/* virtual */ void accept( Visitor& v ) { v.visit( this ); }
private:
int牋? value_;
};

class Composite : public Component {
public:
friend Iterator;
Composite( char _name )牋牋牋牋牋牋牋牋 { name_ = _name;?index_ = 0; }
void add( Component* ele )牋牋牋牋牋牋?{ children_[index_++] = ele; }
ComponentType getType()牋牋牋牋牋牋牋牋 { return CompositeT; }
void printName()牋牋牋牋牋牋牋牋牋牋牋?{ cout << name_ << " "; }
/* virtual */ void accept( Visitor& v ) { v.visit( this ); }
void traverse();
Iterator*? createIterator();
private:
? ?/span>char牋牋牋?name_;
int牋牋牋牋 index_;
Component*? children_[99];
};

void Composite::traverse() {
for (int i=0; i < index_; i++)
牋牋?children_[i]->traverse(); }

/* virtual */ void ListVisitor::visit( Composite* c ) { c->printName(); }
/* virtual */ void ListVisitor::visit( Primitive* p ) { p->traverse(); }
/* virtual */ void TotalVisitor::visit( Primitive* p ) {
totalPrimitives++;
totalValue += p->getValue(); }

class Memento {
public:
void initialize( Composite* _root ) {
牋牋? compArr_[0] = _root;
牋牋? indxArr_[0] = -1;
牋牋? index_ = 0; }
void pushCurrent( Composite* _composite, int _index ) {
牋牋?compArr_[index_+1] = _composite;
牋牋?indxArr_[++index_] = _index; }
int popCurrent() {
牋牋?if (index_ == 0) return 1;
牋牋?index_--;
牋牋?return 0; }
void getAndIncrement( Composite** _composite, int* _index ) {
牋牋? *_composite = compArr_[index_];
牋牋?*_index = indxArr_[index_];
牋牋?(*_index)++;
牋牋? indxArr_[index_]++; }
private:
Composite*? compArr_[10];
int牋牋牋牋 indxArr_[10];
int牋牋牋牋 index_;
};

class Iterator {
public:
Iterator( Composite* _root ) {
牋牋?root_ = _root;
牋牋?isDone_= 0; }
Component* first() {
牋牋?isDone_= 0;
牋牋?memento_.initialize( root_ );
牋牋?return root_; }
Component* next() {
牋牋?Composite* comp;
牋牋?int牋牋牋?indx;
牋牋? memento_.getAndIncrement( &comp, &indx );
牋牋?// if (and while) you are at end-of-composite, go back up
牋牋? while (indx == comp->index_)
牋牋?{
牋牋牋牋 int ret = memento_.popCurrent();
牋牋牋牋 if (ret) {
牋牋牋牋牋? isDone_ = 1;
牋牋牋牋牋? return 0; }
牋牋牋牋 memento_.getAndIncrement( &comp, &indx );
牋牋?}
牋牋?if (comp->children_[indx]->getType() == Component::CompositeT)
牋牋牋牋 memento_.pushCurrent( (Composite*) comp->children_[indx], -1 );
牋牋?return comp->children_[indx]; }
int isDone() { return isDone_; }
private:
Composite*? root_;
Memento牋牋 memento_;
int牋牋牋牋 isDone_;
};

Iterator*? Composite::createIterator() {
return new Iterator( this ); }

class Builder;

class Reader {
public:
Reader( Builder* _builder ) {
牋牋? builder_ = _builder;
牋牋? nextSlot_ = 0; }
void construct();
private:
Builder*?builder_;
char牋牋? compNames_[20];
int牋牋牋 nextSlot_;
int isLower_( char ch ) {
牋牋?if ((ch >= 'a') && (ch <= 'z')) return 1;
牋牋?else return 0; }
int findName_( char ch ) {
牋牋?for (int i=0; i < nextSlot_; i++)
牋牋牋牋 if (compNames_[i] == ch) return 1;
牋牋? compNames_[nextSlot_++] = ch;
牋牋? return 0; }
};

class Builder {
public:
/**/ Builder()牋牋牋牋 { nextSlot_ = 0; }
void buildComposite( char _name ) {
牋牋?// cout << _name << " at level " << nextSlot_ << endl;
牋牋? stack_[nextSlot_] = new Composite( _name );
牋牋?if (nextSlot_)
牋牋牋牋 stack_[nextSlot_ - 1]->add( stack_[nextSlot_] );
牋牋? nextSlot_++; }
void buildPrimitive( int _value ) {
牋牋? stack_[nextSlot_ - 1]->add( new Primitive( _value ) ); }
void closeComposite()?{ nextSlot_--; }
Composite* getResult() { return stack_[0]; }
private:
Composite* stack_[20];
int牋牋牋?nextSlot_;
};

void Reader::construct() {
char牋牋?buf[20];
int牋牋牋 value;
ifstream? inFile( "composit.dat", ios::in );

while ( inFile >> buf )
{
牋牋?if (isLower_( buf[0] ))
牋牋牋牋 if (findName_( buf[0] ))
牋牋牋牋牋?builder_->closeComposite();
牋牋牋牋 else
牋牋牋牋牋?builder_->buildComposite( buf[0] );
牋牋?else
牋牋?{
牋牋牋牋 sscanf( buf, "%d", &value );
牋牋牋牋 builder_->buildPrimitive( value );
牋牋?}
}
}

void main( void ) {
Builder 牋牋牋builder;
Reader牋牋牋?reader( &builder );
Composite*牋?root;
Iterator*牋牋 it;
ListVisitorlistV;
TotalVisitor?totalV;

reader.construct();
root = builder.getResult();

// Composite can traverse itself, but Composite nodes get "lost"
root->traverse();cout << endl;

// If you don't want Composite nodes "lost", use an Iterator for traversal
it = root->createIterator();
for (Component* c = it->first(); ! it->isDone(); c = it->next())
牋牋?c->accept( listV );
?/span>?cout << endl;

// Visitors can be designed to accumulate state over a Composite
for (c = it->first(); ! it->isDone(); c = it->next())
牋牋? c->accept( totalV );
totalV.reportTotals();
}

// ListVisitor replaces the following code:
// for (Component* c = it->first(); ! it->isDone(); c = it->next()) {
//牋?if (c->getType() == Component::PrimitiveT)
//牋牋牋 ((Primitive*) c)->traverse();
//牋?else
//牋牋牋 ((Composite*) c)->printName(); }