<?php
/*
 *  $Id$
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information, see
 * <http://www.phpdoctrine.com>.
 */
/**
 * Doctrine_Node
 *
 * @package     Doctrine
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @category    Object Relational Mapping
 * @link        www.phpdoctrine.com
 * @since       1.0
 * @version     $Revision$
 * @author      Joe Simms <joe.simms@websites4.com>
 */
class Doctrine_Node implements IteratorAggregate
{
  /**
   * @param object    $record   reference to associated Doctrine_Record instance
   */
  protected $record;

  /**
   * @param array     $options
   */
  protected $options;

  /**
   * @param string     $iteratorType  (Pre | Post | Level)
   */
  protected $iteratorType;

  /**
   * @param array     $iteratorOptions
   */
  protected $iteratorOptions;

	/**
	 * contructor, creates node with reference to record and any options
	 *
	 * @param object $record		instance of Doctrine_Record
	 * @param array $options		options				
	 */ 
  public function __construct(&$record, $options)
  {
    $this->record = $record;
    $this->options = $options;
  }

	/**
	 * factory method to return node instance based upon chosen implementation
	 *
	 * @param object $record		instance of Doctrine_Record
	 * @param string $impName		implementation (NestedSet, AdjacencyList, MaterializedPath)
	 * @param array $options		options
	 * @return object $options	instance of Doctrine_Node	 				
	 */ 
  public static function factory(&$record, $implName, $options = array()) {

      $class = 'Doctrine_Node_'.$implName;

      if(!class_exists($class))
        throw new Doctrine_Node_Exception("The class $class must exist and extend Doctrine_Node");

      return new $class($record, $options);
  }

	/**
	 * setter for record attribute
	 *
	 * @param object $record		instance of Doctrine_Record				
	 */ 
  public function setRecord(&$record)
  {
    $this->record = $record;
  }

	/**
	 * getter for record attribute
	 *
	 * @return object 		instance of Doctrine_Record				
	 */   
  public function getRecord() {
    return $this->record;
  }

	/**
	 * convenience function for getIterator
	 *
	 * @param string  $type   type of iterator (Pre | Post | Level)
	 * @param array   $options  options			
	 */ 
  public function traverse($type = 'Pre', $options = array()) {
    return $this->getIterator($type, $options);
  }

	/**
	 * get iterator
	 *
	 * @param string  $type   type of iterator (Pre | Post | Level)
	 * @param array   $options  options			
	 */ 
  public function getIterator($type = null, $options = null)
  {
		if ($type === null)
			$type = (isset($this->iteratorType) ? $this->iteratorType : 'Pre');
				
		if ($options === null)
			$options = (isset($this->iteratorOptions) ? $this->iteratorOptions : array());
			
		$iteratorClass = 'Doctrine_Node_'.$this->record->getTable()->getTreeImplName().'_'.ucfirst(strtolower($type)).'OrderIterator';
		
		return new $iteratorClass($this->record, $options);
  }

	/**
	 * sets node's iterator type
	 *
	 * @param int			
	 */  
  public function setIteratorType($type) {
    $this->iteratorType = $type;
  }

	/**
	 * sets node's iterator options
	 *
	 * @param int			
	 */  
  public function setIteratorOptions($options) {
    $this->iteratorOptions = $options;
  }
} // END class