Source for file ResList.php

Documentation is available at ResList.php

  1. <?php
  2. // ----------------------------------------------------------------------------------
  3. // Class: ResList
  4. // ----------------------------------------------------------------------------------
  5.  
  6. /**
  7. * Implementation of an rdf:Collection (rdf:List)
  8. * Provides a convenience encapsulation for lists formed from
  9. * chains of RDF statements arranged to form a head/tail cons-cell
  10. * structure.
  11. * A well-formed list has cells that are made up of three statements:
  12. * one denoting the rdf:type of the list cell, one denoting the link
  13. * to the value of the list at that point, and one pointing to the
  14. * list tail. If a list cell is not well-formed, list operations may
  15. * fail in unpredictable ways. However, to explicitly check that the
  16. * list is well-formed at all times is expensive, but you can call
  17. * the isValid() method to manually check, if the list is well formed.
  18. *
  19. *
  20. @version  $Id: fsource_resModel__resModelResList.php.html 443 2007-06-01 16:25:38Z cax $
  21. @author Daniel Westphal <mail at d-westphal dot de>
  22.  
  23. *
  24. @package resModel
  25. @access    public
  26. */
  27. class ResList extends ResResource 
  28. {
  29.     /**
  30.     * Holds a ResResource with the uri rdf:rest
  31.     * @var        ResResource 
  32.     * @access    private
  33.     */
  34.     var $rdfRestResource;
  35.     
  36.     /**
  37.     * Holds a ResResource with the uri rdf:first
  38.     * @var        ResResource 
  39.     * @access    private
  40.     */
  41.     var $rdfFirstResource;
  42.         
  43.     /**
  44.     * Holds a ResResource with the uri rdf:nil
  45.     * @var        ResResource 
  46.     * @access    private
  47.     */
  48.     var $rdfNilResource;
  49.     
  50.     
  51.     /**
  52.     * Constructor
  53.     * You can supply a URI
  54.     *
  55.     * @param string $uri 
  56.     * @access    public
  57.     */        
  58.     function ResList($uri null)
  59.     {
  60.         //call the parent's constructor
  61.         parent::ResResource($uri);
  62.         //initialize vars
  63.         $this->rdfRestResource new ResResource(RDF_NAMESPACE_URI.RDF_REST);
  64.         $this->rdfFirstResource new ResResource(RDF_NAMESPACE_URI.RDF_FIRST);
  65.         $this->rdfNilResource new ResResource(RDF_NAMESPACE_URI.RDF_NIL);
  66.     }
  67.  
  68.     /**
  69.     * Returns the value of the list element at the specified position or null.
  70.     *
  71.        * @param    integer    $position 
  72.        * @return    ResResource 
  73.        * @access    public
  74.        */
  75.     function get($position)
  76.     {
  77.         //init
  78.         $listElement=$this;
  79.         //walk through the list until the position in the list is reached
  80.         for ($i=0;$i<$position;$i++)
  81.         {
  82.             $listElement=$this->_getRestElement($listElement);
  83.             if($listElement===null)
  84.                 return null;    
  85.         }
  86.         //return the associated value
  87.         return $this->_getValue($listElement);    
  88.     }    
  89.  
  90.     /**
  91.     *  Add the given value to the end of the list.
  92.     *  it is only defined if this is not the empty list.
  93.     *
  94.        * @param    object ResResource    $resource 
  95.        * @return    boolean 
  96.        * @access    public
  97.        */
  98.     function add($resource)
  99.     {
  100.         //return false if this list is the empty list
  101.         if($this->uri==RDF_NAMESPACE_URI.RDF_NIL)
  102.             return false;
  103.         
  104.         //if this is the first value    
  105.         if ($this->isEmpty())
  106.         {
  107.             $newLastElement =$this;
  108.         else
  109.         //if there are other values in the list 
  110.         {
  111.             //get the last list element
  112.             $lastElement=$this->_getListElement();
  113.             //remove the rdf:rest property
  114.             $lastElement->removeAll($this->rdfRestResource);
  115.             //create a new list element
  116.             $newLastElement=$this->model->createResource();
  117.             //concatenate the new list element with the list
  118.             $lastElement->addProperty($this->rdfRestResource,$newLastElement);
  119.         }
  120.         //add the value
  121.         $newLastElement->addProperty($this->rdfFirstResource,$resource);
  122.         //ad the rdf:nil property to the last list element
  123.         $newLastElement->addProperty($this->rdfRestResource,$this->rdfNilResource);
  124.         
  125.         return true;
  126.     }
  127.     
  128.     /**
  129.     *  Update the head of the list to have the given value,
  130.     *  and return the previous value.
  131.     *
  132.        * @param    object ResResource    $value 
  133.        * @return    ResResource 
  134.        * @access    public
  135.        */
  136.     //todo: error handling, when empty list
  137.     function setHead($value)
  138.     {    
  139.         //save the old value    
  140.         $oldValue=$this->getHead();
  141.         //remove the old value
  142.         $this->removeAll($this->rdfFirstResource);
  143.         //add the new value
  144.         $this->addProperty($this->rdfFirstResource,$value);
  145.         
  146.         //return the old value
  147.         return $oldValue;
  148.     }
  149.     
  150.     /**
  151.     * Get the value that is associated with the head of the list.
  152.     *
  153.        * @return    ResResource 
  154.        * @access    public
  155.        */
  156.     //todo: error handling, falls empty list
  157.     function getHead()
  158.     {
  159.         return $this->_getValue($this);
  160.     }
  161.     
  162.     /**
  163.     *  Remove the head of the list. The tail of the list
  164.     *  remains in the model. Note that no changes are made to
  165.     *  list cells that point to this list cell as their tail.
  166.     *
  167.        * @return    ResList 
  168.        * @access    public
  169.        */
  170.     function removeHead()
  171.     {
  172.         //get the second list element
  173.         $rest=$this->_getRestElement($this);
  174.         //remove the first element
  175.         $this->removeAll($this->rdfFirstResource);
  176.         $this->removeAll($this->rdfRestResource);
  177.         //change this Resource URI to that of the second list element
  178.         //thus makin it the fist element
  179.         $this->uri=$rest->getURI();
  180.         
  181.         //return the new list
  182.         return $this;
  183.     }    
  184.  
  185.     /**
  186.     * Get the Position of the first occurrence of the given value in the list,
  187.     * or -1 if the value is not in the list.
  188.     * You can supply an offset to search for values. (First element has offset 0)
  189.     * Default is 0
  190.     *
  191.        * @param    object ResResource    $resource 
  192.     * @param    integer    $offset 
  193.        * @return    integer 
  194.        * @access    public
  195.        */
  196.     function indexOf($resource$offset 0)
  197.     {
  198.         //init
  199.         $element=$this;
  200.         $actualIndex=0;
  201.  
  202.         //walk through the list until the value is found and the position is higher than
  203.         //the offset
  204.         while ($actualIndex $offset || !$resource->equals($this->_getValue($element)))
  205.         {
  206.             //get next list element
  207.             $element=$this->_getRestElement($element);
  208.             $actualIndex++;
  209.             
  210.             //if the end of the list is reached and the value isn't found
  211.             if ($element===null)
  212.                 return null;
  213.         }
  214.         //return the index value
  215.         return $actualIndex;    
  216.     }
  217.     
  218.     /**
  219.     * Replace the value at the i'th position in the list with the given value
  220.     *
  221.        * @param    integer                $index 
  222.        * @param    object ResResource    $resource 
  223.        * @return    object ResResource 
  224.        * @access    public
  225.        */
  226.     function replace($index$resource)
  227.     {
  228.         //get the list element at the $index position
  229.         $listElement=$this->_getListElement($index);
  230.         //get the old value
  231.         $oldValue=$this->_getValue($listElement);
  232.         //remove the old value
  233.         $listElement->removeAll($this->rdfFirstResource);
  234.         //add the new value
  235.         $listElement->addProperty($this->rdfFirstResource,$resource);
  236.         //return the old value
  237.         return $oldValue;
  238.     }
  239.     
  240.     /**
  241.     * Answer true if the given node appears as the value of a value
  242.     * of any of the cells of this list.
  243.     *
  244.        * @param    object ResResource    $value 
  245.        * @return    boolean 
  246.        * @access    public
  247.        */
  248.     function contains($value)
  249.     {
  250.         //return true, if a position was found.
  251.         $result=$this->indexOf($value);
  252.         return ($result!==null);
  253.     }
  254.     
  255.     /**
  256.     * Get the list that is the tail of this list.
  257.     *
  258.        * @return    object ResList 
  259.        * @access    public
  260.        */
  261.     function getTail()
  262.     {
  263.         //get the second list element
  264.         $nextListElement$this->_getRestElement($this);
  265.         //return the second element as new list
  266.         return $this->model->createList($nextListElement->getURI());    
  267.     }
  268.     
  269.     /**
  270.     * Remove all of the components of this list from the model.
  271.     * Note that this is operation is only removing the list cells
  272.     * themselves, not the resources referenced by the list -
  273.     * unless being the object of an rdf:first  statement is the
  274.     * only mention of that resource in the model.
  275.     *
  276.        * @return    boolean 
  277.        * @access    public
  278.        */
  279.     function removeList()
  280.     {
  281.         $element=$this;
  282.  
  283.         while ($element!==null)
  284.         {
  285.             $nextElement=$this->_getRestElement($element);
  286.             
  287.             $element->removeAll($this->rdfFirstResource);
  288.             $element->removeAll($this->rdfRestResource);
  289.                     
  290.             if (($nextElement !== null&& ($nextElement->getURI()!==RDF_NAMESPACE_URI.RDF_NIL))
  291.             {
  292.                 $element=$nextElement;
  293.             else 
  294.             {
  295.                 return true;
  296.             }
  297.         }
  298.         return false;
  299.     }
  300.     
  301.     /**
  302.     * Returns true, if this list is empty
  303.     *
  304.        * @param    object Statement    $statement 
  305.        * @return    integer 
  306.        * @access    public
  307.        */
  308.     function isEmpty()
  309.     {
  310.         return !$this->hasProperty($this->rdfFirstResource);
  311.     }
  312.     
  313.     /**
  314.     * Get all values in the list as an array of ResResources
  315.     *
  316.        * @return    array 
  317.        * @access    public
  318.        */
  319.     function getContentInArray()
  320.     {
  321.         $result=array();
  322.         $element=$this;
  323.  
  324.         while ($element!==null)
  325.         {
  326.             //add the value of the current element to the result if is set.
  327.             $value=$this->_getValue($element);
  328.             if ($value!==null)
  329.                 $result[]=$value;
  330.             
  331.             //walk through the list until it's end        
  332.             $nextElement=$this->_getRestElement($element);
  333.             if (($nextElement !== null&& ($nextElement->getURI()!==RDF_NAMESPACE_URI.RDF_NIL))
  334.             {
  335.                 $element=$nextElement;
  336.             else 
  337.             {
  338.                 break;
  339.             }
  340.         }
  341.         //return the result
  342.         return $result;
  343.     }
  344.     
  345.     /**
  346.     * Change the tail of this list to point to the given list, so that this list
  347.     * becomes the list of the concatenation of the elements of
  348.     * both lists. This is a side-effecting operation on this list;
  349.     * for a non side-effecting alternative, see append.
  350.     * 
  351.     *
  352.        * @param    object ResList    $ResList 
  353.        * @access    public
  354.        */
  355.     function concatenate($ResList)
  356.     {
  357.         //get the last list element
  358.         $lastElement=$this->_getListElement();
  359.         //remove the old tail (rdf:nil)
  360.         $lastElement->removeAll($this->rdfRestResource);
  361.         //add the $ResList as new tail
  362.         $lastElement->addProperty($this->rdfRestResource,$ResList);
  363.     }
  364.     
  365.     /**
  366.     * Answer a new list that is formed by adding each element of
  367.     * this list to the head of the given list. This is a non
  368.     * side-effecting operation on either this list or the given
  369.     * list, but generates a copy of this list. For a more storage
  370.     * efficient alternative, see concatenate
  371.     *
  372.        * @param    object ResList    $ResList 
  373.        * @return    object ResList 
  374.        * @access    public
  375.        */
  376.     function append($resList)
  377.     {
  378.         //get a copy of this list
  379.         $newList=$this->copy();
  380.         
  381.         //add all values from the $resList to the new list
  382.         foreach ($resList->getContentInArray(as $value)
  383.         {
  384.             $newList->add($value);    
  385.         }
  386.         //return the new list
  387.         return $newList;
  388.     }
  389.     
  390.     /**
  391.     * Answer a list that contains all of the elements of this
  392.     * list in the same order, but is a duplicate copy in the
  393.     * underlying model.
  394.     *
  395.        * @return    object ResList 
  396.        * @access    public
  397.        */
  398.     function copy()
  399.     {
  400.         //create a new list in the model
  401.         $newList=$this->model->createList();
  402.         //add all values from this list to the new list
  403.         foreach ($this->getContentInArray(as $value)
  404.         {
  405.             $newList->add($value);    
  406.         }
  407.         //return the new list
  408.         return $newList;
  409.     }
  410.     
  411.     /**
  412.     * Return a reference to a new list cell whose head is value
  413.     * and whose tail is this list.
  414.     *
  415.        * @param    object ResResource    $value 
  416.        * @return    object ResList 
  417.        * @access    public
  418.        */
  419.     function cons($value)
  420.     {
  421.         //create a new list
  422.         $newList=$this->model->createList();
  423.         //add the new value
  424.         $newList->add($value);
  425.         //set this list as the tail of the new list
  426.         $newList->setTail($this);
  427.         
  428.         //return the new list
  429.         return $newList;
  430.     }
  431.     
  432.     /**
  433.     * Update the list cell at the front of the list to have the
  434.     * given list as tail. The old tail is returned, and remains
  435.     * in the model.
  436.     *
  437.        * @param    object ResList    $resList 
  438.        * @return    object Reslist 
  439.        * @access    public
  440.        */
  441.     function setTail($resList)
  442.     {
  443.         //save the old tail
  444.         $oldTail=$this->getTail();
  445.         //remove the old tail
  446.         $this->removeAll($this->rdfRestResource);
  447.         //add the $resList as new Tail
  448.         $this->addProperty($this->rdfRestResource,$resList);
  449.         
  450.         //return the old tail
  451.         return $oldTail;
  452.     }
  453.     
  454.     /**
  455.     * Answer true if this list has the same elements in the
  456.     * same order as the given list. Note that the standard equals
  457.     * test just tests for equality of two given list cells.
  458.     * While such a test is sufficient for many purposes, this
  459.     * test provides a broader equality definition, but is
  460.     * correspondingly more expensive to test.
  461.     *
  462.        * @param    object ResList    $resList 
  463.        * @return    boolean 
  464.        * @access    public
  465.        */
  466.     function sameListAs($resList)
  467.     {
  468.         //init
  469.         $indexPos=0;
  470.         do
  471.         {
  472.             //get the values for both lists at the actual position
  473.             $thisValue=$this->get($indexPos);
  474.             $thatValue=$resList->get($indexPos);
  475.             //if the values aren't equal, return false
  476.             if (($thisValue !== null&& !$thisValue->equals($thatValue))
  477.                 return false;
  478.                 
  479.             $indexPos++;
  480.             //walk until this list reaches a null value (end)    
  481.         while ($thisValue!==null);
  482.         
  483.         //if the other list has a null value at this position too, return true
  484.         //else return false
  485.         return ($thatValue===null);
  486.     }
  487.     
  488.     /**
  489.     * Remove the given value from this list.
  490.     * If value does not occur in the list, no action is taken. Since removing the
  491.     * head of the list will invalidate the list head cell, in
  492.     * general the list must return the list that results from
  493.     * this operation. However, in many cases the return value
  494.     * will be the same as the object that this method is invoked
  495.     * on.
  496.     *
  497.        * @param    object ResResource    $value 
  498.        * @return    object ResList 
  499.        * @access    public
  500.        */
  501.     function remove($value)
  502.     {
  503.         //if the value is the value of the first list element(head)
  504.         //call the remove head position and return the new head
  505.         if ($value->equals($this->_getValue($this)))
  506.             return $this->removeHead();
  507.     
  508.         $element=$this;
  509.         do
  510.         {    
  511.             $newElement=$this->_getRestElement($element);
  512.             
  513.             //if the value equals the value of the current list element
  514.             if ($newElement !== null && $value->equals($this->_getValue($newElement)))
  515.             {
  516.                 //remove the link to the list element to be removed
  517.                 $element->removeAll($this->rdfRestResource);
  518.                 //add a link to the list element AFTER the element to be deleted
  519.                 $element->addProperty($this->rdfRestResource,$this->_getRestElement($newElement));
  520.                 //remove the list element with values
  521.                 $newElement->removeAll($this->rdfFirstResource);
  522.                 $newElement->removeAll($this->rdfRestResource);
  523.                 //return this ResList
  524.                 return $this;    
  525.             }
  526.             $element=$newElement;
  527.         while ($element!==null);
  528.         //return this list
  529.         return $this;    
  530.     }
  531.     
  532.     /**
  533.     * Answer true if the list is well-formed, by checking that each
  534.     * node is correctly typed, and has a head and tail pointer from
  535.     * the correct vocabulary
  536.     *
  537.        * @return    boolean 
  538.        * @access    public
  539.        */
  540.     function isValid()
  541.     {
  542.         $element=$this;    
  543.         if ($this->_getValue($this)=== null && $this->_getRestElement($this=== null)
  544.             return true;
  545.         do 
  546.         {
  547.             //return true if the last element is a rdf:nil
  548.             if ($element->getURI(== RDF_NAMESPACE_URI.RDF_NIL)
  549.                 return true;
  550.             //return false, if the current element has no associated value
  551.             if ($this->_getValue($element=== null)
  552.                 return false;
  553.                         
  554.             $element=$this->_getRestElement($element);    
  555.         while ($element !== null);
  556.         //return false, if the current element has no rdf:rest property
  557.         return false;
  558.     }
  559.     
  560.     /**
  561.     * Get the associated rdf:rest Resource from the suplied ResList element
  562.     *
  563.        * @param    object ResList    $listElement 
  564.        * @return    object ResList 
  565.        * @access    private
  566.        */
  567.     function _getRestElement($listElement)
  568.     {
  569.         //get the rdf:rest property
  570.         $statement$this->model->getProperty($listElement,$this->rdfRestResource);
  571.         //return null, if this property isn't set
  572.         if ($statement === null)
  573.             return null;
  574.             
  575.         //return the value of the rdf:rest property    
  576.         return $statement->getObject();    
  577.     }
  578.     
  579.     /**
  580.     * Returns the list element at the $index position.
  581.     *
  582.     * If to $index is suplied, the last list element will be returned
  583.     
  584.        * @param    integer    $index 
  585.        * @return    object ResResource 
  586.        * @access    private
  587.        */
  588.     function _getListElement($index null)
  589.     {
  590.         $element=$this;
  591.         $actualIndex=0;
  592.  
  593.         while ($element!=null)
  594.         {
  595.             //return the current element if index matches the current index
  596.             if ($actualIndex === $index)
  597.                 return $element;
  598.             
  599.             //return the current element if it the last one        
  600.             if ($element->hasProperty($this->rdfRestResource,$this->rdfNilResource))
  601.                 return $element;
  602.             
  603.             $nextElement=$this->_getRestElement($element);
  604.             
  605.             if ($nextElement!==null)
  606.             {
  607.                 $element=$nextElement;
  608.                 $actualIndex++;
  609.             else 
  610.             {
  611.                 break;
  612.             }
  613.         }
  614.         return $element;
  615.     }
  616.     
  617.     /**
  618.     * Get the value associated to the $listResource by the rdf:first property
  619.     *
  620.        * @param    object ResList    $listResource 
  621.        * @return    object ResResource 
  622.        * @access    private
  623.        */
  624.     function _getValue($listResource)
  625.     {
  626.         //Return the value of the rdf:first property or null, if it isn't set
  627.         $statement=$this->model->getProperty($listResource,$this->rdfFirstResource);
  628.         if ($statement===null)
  629.             return null;
  630.  
  631.         return $statement->getObject();    
  632.     }
  633. }
  634. ?>

Documentation generated on Fri, 1 Jun 2007 16:51:29 +0200 by phpDocumentor 1.3.2