Source for file Branch.class.php

Documentation is available at Branch.class.php

  1. <?php
  2. /**
  3.  * Gumbo Library Framework
  4.  *
  5.  * LICENSE
  6.  * This library is being released under the terms of the New BSD License.  A
  7.  * copy of the license is packaged with the software (LICENSE.txt).  If no
  8.  * copy is found, a copy of the license template can be found at:
  9.  * http://www.opensource.org/licenses/bsd-license.php
  10.  * 
  11.  * @category Gumbo
  12.  * @package Composite
  13.  * @copyright Copyright (c) 2007, iBayou, Michael Luster
  14.  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  15.  * @author Michael Luster <mluster79@yahoo.com>
  16.  * @link http://sourceforge.net/projects/phpgumbo
  17.  * @version 0.0.1
  18.  */
  19.  
  20. /**
  21.  * Composite Pattern Branch Class
  22.  * 
  23.  * The Branch class can hold any number of Composite objects.  It will provide a
  24.  * reference to each Composite based on the name.  Simply add or remove Composite
  25.  * objects to the Branch to populate.
  26.  * 
  27.  * If a Branch holds Composite elements
  28.  * with the same name, each individual Composite can be accessed by a numerical
  29.  * reference.  This feature will automatically be initiated when it finds another
  30.  * Composite with the same name.  However, this only works on one level.  This means
  31.  * if Composites of name 'last' are added, the numerical reference will work only
  32.  * with the 'last' Composites.  If multiple Composites of another name 'first' are
  33.  * added, the numerical references will be reset, and will reference the 'first'
  34.  * Composites.  Use additional Branches to hold numerical references, separating the
  35.  * responsibility from the parent.
  36.  * 
  37.  * To add Composites:
  38.  * <pre>
  39.  * $branch->add (new Gumbo_Leaf ("USA", "country"));
  40.  * $branch->country = new Gumbo_Leaf ("USA");
  41.  * </pre>
  42.  * 
  43.  * To remove a Composite:
  44.  * <pre>
  45.  * $branch->remove ("country");
  46.  * $branch->country = null;
  47.  * </pre>
  48.  * 
  49.  * To access Composite elements inside the Branch:
  50.  * <pre>
  51.  * $branch->get ("country")->value;
  52.  * $branch->country->value;
  53.  * </pre>
  54.  * 
  55.  * To access Composite elements using a numerical reference:
  56.  * <pre>
  57.  * $branch->get (0)->value; // for first element
  58.  * $branch->{0}->value; // for first element
  59.  * </pre>
  60.  * 
  61.  * The Branch implements the IteratorAggregate interface, which allows easy looping
  62.  * through the elements inside the Branch.  The first method will loop through
  63.  * every element inside the Branch.  The second will only loop through the numerical
  64.  * referenced elements.
  65.  * <pre>
  66.  * foreach ($branch as $obj) {
  67.  *         // do something
  68.  *         ...
  69.  * }
  70.  * </pre>
  71.  * 
  72.  * <pre>
  73.  * for ($x = 0;$x < $branch->getCount ();$x++) {
  74.  *         if (!isset ($branch->get ($x)) { continue; } // checks if element still exists
  75.  *         $obj = $branch->get ($x);
  76.  *         // do something
  77.  *         ...
  78.  * }
  79.  * </pre>
  80.  *
  81.  * @category Gumbo
  82.  * @package Composite
  83.  * @copyright Copyright (c) 2007, iBayou, Michael Luster
  84.  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  85.  * @author Michael Luster <mluster79@yahoo.com>
  86.  * @link http://sourceforge.net/projects/phpgumbo
  87.  * @desc Composite Pattern Branch Class
  88.  * @version 0.0.1
  89.  */
  90.  
  91. gumbo_load ("Tree");
  92.  
  93. class Gumbo_Branch extends Gumbo_Tree implements IteratorAggregate {
  94.     
  95.     /** @var array $_list array of Composite objects */
  96.     private $_list = array ();
  97.     /** @var int $_count number of numerical referenced Composites */
  98.     private $_count = 0;
  99.     
  100.     
  101.     
  102.     /**
  103.      * Constructor
  104.      * @param int|string$name name of the Branch
  105.      */
  106.     public function __construct ($name=null{
  107.         $this->setName ($name);
  108.     }
  109.     
  110.     /**
  111.      * Returns the value of the given element
  112.      * 
  113.      * This method will be responsible for returning the element
  114.      * object located inside the list.  It will check for the key
  115.      * inside the array, and return the object.  If the key is not
  116.      * found, it will return null.
  117.      * 
  118.      * If the parameter is equal to "name", then it will return the
  119.      * name of the object.  Be cautious, as the list could contain a
  120.      * key reference as "name".  If this occurs, the Composite object inside
  121.      * the array element will be returned.  Use the getName () method to
  122.      * ensure the Composite name is returned.
  123.      * 
  124.      * @param int|string$name 
  125.      * @return mixed 
  126.      * @throws Gumbo_Exception
  127.      */
  128.     public function __get ($name{
  129.         try {
  130.             // verify precondition
  131.             if (!is_string ($name&& !is_int ($name)) {
  132.                 throw new Gumbo_Exception ("Invalid Argument 'name:int|str' => {$name}:gettype ($name));
  133.             }
  134.             if (!isset ($this->{$name})) {
  135.                 throw new Gumbo_Exception ("Property Undefined: {$name}");
  136.             }
  137.             
  138.             return $this->get ($name);
  139.         catch (Gumbo_Exception $e{
  140.             $e->setFunction (__METHOD__);
  141.             gumbo_trigger ($e);
  142.         }
  143.         return null;
  144.     }
  145.     
  146.     /**
  147.      * Checks if the given key if referenced inside the list
  148.      * <pre>
  149.      * isset ($this->{test});
  150.      * </pre>
  151.      * @param int|string$name 
  152.      * @return bool 
  153.      * @throws Gumbo_Exception
  154.      */
  155.     public function __isset ($name{
  156.         try {
  157.             // verify preconditioin
  158.             if (!is_string ($name&& !is_int ($name)) {
  159.                 throw new Gumbo_Exception ("Invalid Argument 'name:int|str' => {$name}:gettype ($name));
  160.             }
  161.             
  162.             return isset ($this->_list [$name]);
  163.         catch (Gumbo_Exception $e{
  164.             $e->setFunction (__METHOD__);
  165.             gumbo_trigger ($e);
  166.         }
  167.         return false;
  168.     }
  169.     
  170.     /**
  171.      * Sets the value of the given element (only with a string key)
  172.      * 
  173.      * If the value is a Composite object, then it will set the key reference
  174.      * to the name of the Composite.
  175.      * <pre>
  176.      * $branch->any_string = new Gumbo_Leaf ("USA", "country");
  177.      * // similar to calling
  178.      * $branch->add (new Gumbo_Leaf ("USA", "country"));
  179.      * </pre>
  180.      * 
  181.      * If the value argument is 'null', it will remove the Composite.
  182.      * <pre>
  183.      * $branch->country = null;
  184.      * // similar to calling
  185.      * $branch->remove ("country");
  186.      * </pre>
  187.      * 
  188.      * The last option will create a new Leaf object with the 'name' and
  189.      * 'val' arguments as the Leaf 'name' and 'value'
  190.      * <pre>
  191.      * $branch->country = "USA";
  192.      * // similar to calling:
  193.      * $branch->add (new Gumbo_Leaf ("country", "USA"));
  194.      * </pre>
  195.      * 
  196.      * @param int|string$name 
  197.      * @param mixed $val 
  198.      */
  199.     public function __set ($name$val{
  200.         // sets a Composite object
  201.         if ($val instanceof Gumbo_Interface_Composite{
  202.             $this->add ($val);
  203.             return;
  204.         }
  205.         
  206.         // remove reference
  207.         if (is_null ($val)) {
  208.             $this->remove ($name);
  209.             return;
  210.         }
  211.         
  212.         // creates a new Leaf object based on the value except
  213.         if (is_string ($name|| is_int ($name)) {
  214.             $leaf new Gumbo_Leaf ($val$name);
  215.             $this->add ($leaf);
  216.         }
  217.     }
  218.     
  219.     /**
  220.      * Removes the Tree object references by the supplied key
  221.      * <pre>
  222.      * unset ($this->{test});
  223.      * </pre>
  224.      * @param int|string$name 
  225.      * @throws Gumbo_Exception
  226.      */
  227.     public function __unset ($name{
  228.         try {
  229.             if (!is_string ($name&& !is_int ($name)) {
  230.                 throw new Gumbo_Exception ("Invalid Argument 'name:int|str' => {$name}:gettype ($name));
  231.             }
  232.             if (!isset ($this->{$name})) {
  233.                 throw new Gumbo_Exception ("Property Undefined: {$name}");
  234.             }
  235.             
  236.             unset ($this->_list [$name]);
  237.         catch (Gumbo_Exception $e{
  238.             $e->setFunction (__METHOD__);
  239.             gumbo_trigger ($e);
  240.         }
  241.     }
  242.     
  243.     
  244.     
  245.     /** ACTION METHODS **/
  246.     /**
  247.      * Add a Composite object to the Branch
  248.      * @param Gumbo_Interface_Composite $tree 
  249.      * @param bool $replace replaces the Tree object
  250.      * @throws Gumbo_Exception
  251.      */
  252.     public function add (Gumbo_Interface_Composite $tree$replace=false{
  253.         // verify preconditions
  254.         try {
  255.             if (!is_bool ($replace)) {
  256.                 throw new Gumbo_Exception ("Invalid Argument 'replace:bool' => {$replace}:gettype ($replace));
  257.             }
  258.         catch (Gumbo_Exception $e{
  259.             $e->setFunction (__METHOD__);
  260.             gumbo_trigger ($e);
  261.             $replace false;
  262.         }
  263.         
  264.         $name $tree->getName ();
  265.         if (is_null ($name&& !is_string ($name)) {
  266.             $this->_list [$tree;
  267.             $this->_count++;
  268.         else {
  269.             if ($replace{
  270.                 $this->_list [$name$tree;
  271.             else {
  272.                 // if two Composites have the same name, new Composite appended to integer list
  273.                 if (isset ($this->_list [$name])) {
  274.                     if (!isset ($this->_list [0])) {
  275.                         $this->_list [$this->_list [$name];
  276.                         $this->_count++;
  277.                     }
  278.                     $this->_list [$tree;
  279.                     $this->_count++;
  280.                 else {
  281.                     $this->_list [$name$tree;
  282.                 }
  283.             }
  284.         }
  285.     }
  286.     
  287.     /**
  288.      * Removes a Tree object from the Branch based on the name value
  289.      * @param int|string$name Tree name
  290.      * @throws Gumbo_Exception
  291.      */
  292.     public function remove ($name{
  293.         try {
  294.         // verify preconditions
  295.             if (!is_string ($name&& !is_int ($name)) {
  296.                 throw new Gumbo_Exception ("Invalid Argument 'name:int|str' => {$name}:gettype ($name));
  297.             }
  298.             if (!isset ($this->{$name})) {
  299.                 throw new Gumbo_Exception ("Property Undefined: {$name}");
  300.             }
  301.             
  302.             unset ($this->_list [$name]);
  303.         catch (Gumbo_Exception $e{
  304.             $e->setFunction (__METHOD__);
  305.             gumbo_trigger ($e);
  306.         }
  307.     }
  308.     
  309.     
  310.     
  311.     /** MUTATOR METHODS **/
  312.     
  313.     
  314.     
  315.     /** ACCESSOR METHODS **/
  316.     /**
  317.      * Returns the Composite object referenced by the supplied key
  318.      * @param int|string$name 
  319.      * @return Gumbo_Interface_Composite 
  320.      * @throws Gumbo_Exception
  321.      */
  322.     public function get ($name=null{
  323.         if (is_null ($name)) return null}
  324.         try {
  325.             // verify precondition
  326.             if (!is_string ($name&& !is_int ($name)) {
  327.                 throw new Gumbo_Exception ("Invalid Argument 'name:int|str' => {$name}:gettype ($name));
  328.             }
  329.             if (!isset ($this->_list [$name])) {
  330.                 throw new Gumbo_Exception ("Property Undefined: {$name}");
  331.             }
  332.             
  333.             return $this->_list [$name];
  334.         catch (Gumbo_Exception $e{
  335.             $e->setFunction (__METHOD__);
  336.             gumbo_trigger ($e);
  337.         }
  338.         return null;
  339.     }
  340.     
  341.     /**
  342.      * Returns the number of numerical Composite references
  343.      * @return int 
  344.      */
  345.     public function getCount ({
  346.         return $this->_count;
  347.     }
  348.     
  349.     /**
  350.      * Returns an Iterator
  351.      * @return Iterator 
  352.      * @uses Gumbo_Iterator
  353.      */
  354.     public function getIterator ({
  355.         gumbo_load ("Iterator");
  356.         return new Gumbo_Iterator ($this->_list);
  357.     }
  358.     
  359. }
  360.  
  361. ?>