/* 
 * composite.cpp
 *
 * Composite Design Pattern example.  Compose objects into tree structures
 * to represent whole-part hierarchies in a manner that lets clients
 * treat objects and compositions uniformly.
 */

#include <iostream>
#include <vector>

class Component {

public:
  virtual void operation() = 0;

  virtual void Add(Component*)     {}
  virtual void Remove(Component)   {}
  virtual Component* getChild(int) { return 0; }
};

class Leaf: public Component {

public:

  Leaf(int id) : _id(id) {}

  virtual void operation() { std::cout << "Leaf " << _id << " operation.\n"; }

private:
  int _id;
};

class Composite: public Component {

public:
  Composite(int id) : _id(id) {}

  virtual void operation() {
    std::cout << "Composite " << _id << " operation start\n";

    for (std::vector<Component*>::iterator it = _components.begin();
	 it != _components.end(); ++it)
      (*it)->operation();

    std::cout << "Composite " << _id << " operation end\n";
  }

  virtual void Add(Component* c)   { _components.push_back(c); }
  virtual void Remove(Component* c){ /* TBD */ }

  virtual Component* getChild(int n) { std::cout << _components.size() << std::endl; return _components[n]; }

private:
  std::vector<Component*> _components;
  int _id;
};

class Client {

public:
  Client(Component& component) : _component(component) {}

  void create() {
    _component.Add(new Leaf(1));
    _component.Add(new Composite(2));

    _component.getChild(1)->Add(new Leaf(3));
    _component.getChild(1)->Add(new Leaf(4));
  }

  void process() {
    _component.operation();
  }

private:
  Component& _component;
};

int main() {

  Composite component(0);

  Client client(component);

  client.create();

  client.process();
}

