<?php
/**
 * This set of classes implements a Flyweight pattern
 * (http://en.wikipedia.org/wiki/Flyweight_pattern). Refactor/rename
 * some based on this fact?
 *
 * @package Horde_RDO
 */

/**
 * @package Horde_RDO
 */
interface Horde_RDO_Decorating_Iterator_Lens {

    
/**
     */
    
public function decorate($target);

}

/**
 * @package Horde_RDO
 */
class Horde_RDO_Lens implements Horde_RDO_Decorating_Iterator_LensIteratorAggregate {

    
/**
     */
    
protected $target;

    
/**
     */
    
public function decorate($target)
    {
        
$this->target $target;
        return 
$this;
    }

    
/**
     * Implement the IteratorAggregate pattern. When a single RDO
     * object is iterated over, we return an iterator that loops over
     * each property of the object.
     *
     * @return ArrayIterator The Iterator instance.
     */
    
public function getIterator()
    {
        return new 
Horde_RDO_Iterator($this);
    }

    
/**
     */
    
public function __get($key)
    {
        return 
$this->target->$key;
    }

    
/**
     */
    
public function __set($key$value)
    {
        
$this->target->$key $value;
        return 
$this;
    }

    
/**
     */
    
public function __call($func$params)
    {
        return 
call_user_func_array(array($this->target$func), $params);
    }

}

/**
 */
class Horde_RDO_Decorating_Iterator implements OuterIterator {

    
/**
     * The Iterator to decorate.
     * @var Iterator
     */
    
private $_i;

    
/**
     * The Decorator that will observe each element of the iterator.
     * @var Horde_RDO_Decorating_Iterator_Lens
     */
    
protected $_d;

    
/**
     * Constructs a decorator around an iterator using a single
     * Horde_RDO_Decorating_Iterator_Lens object, which decorates the current()
     * element of the iterator. The decorator is like a lens,
     * decotrating one element at a time, instead of having a
     * decorator for every element in the list.
     *
     * @param Iterator $i The iterator to decorate.
     */
    
public function __construct(Iterator $i$d null)
    {
        
$this->_i $i;
        if (
$d !== null) {
            
$this->setLens($d);
        }
    }

    
/**
     * Set or change the Lens modifying the inner iterator. Sets the
     * current object of the lens automatically and returns the lens.
     */
    
public function setLens(Horde_RDO_Decorating_Iterator_Lens $d)
    {
        
$this->_d $d;
        return 
$this->current();
    }

    
/**
     * Rewind the inner iterator.
     */
    
function rewind()
    {
        
$this->_i->rewind();
    }

    
/**
     * Move to next element.
     *
     * @return void
     */
    
function next()
    {
        
$this->_i->next();
    }

    
/**
     * @return Whether more elements are available.
     */
    
function valid()
    {
        return 
$this->_i->valid();
    }

    
/**
     * @return The current key.
     */
    
function key()
    {
        return 
$this->_i->key();
    }

    
/**
     * @return The current value.
     */
    
function current()
    {
        return 
$this->_d->decorate($this->_i->current());
    }

    
/**
     * @return Iterator The inner iterator.
     */
    
function getInnerIterator()
    {
        return 
$this->_i;
    }

    
/**
     * Aggregate the inner iterator.
     *
     * @param func    Name of method to invoke.
     * @param params  Array of parameters to pass to method.
     */
    
function __call($func$params)
    {
        return 
call_user_func_array(array($this->_i$func), $params);
    }

}