<?PHP

#
#   FILE:  SPT--Vocabulary.php
#
#   METHODS PROVIDED:
#       Vocabulary()
#           - constructor
#       SomeMethod($SomeParameter, $AnotherParameter)
#           - short description of method
#
#   AUTHOR:  Edward Almasy
#
#   Part of the Collection Workflow Integration System
#   Copyright 2007 Edward Almasy and Internet Scout
#   http://scout.wisc.edu
#

/**
* controlled vocabulary
*/
class Vocabulary {

    # ---- PUBLIC INTERFACE --------------------------------------------------

    /**
    * constructor
    * @param FileName Name of .voc file containing vocabulary to load.
    * @note Check Status() to determine if constructor succeeded
    */
    function Vocabulary($FileName)
    {
        # save file name
        $this->FileName = $FileName;

        # attempt to load vocabulary from file
        $this->Xml = simplexml_load_file($FileName);

        # set error code if load failed
        $this->StatusString = ($this->Xml === FALSE) ? "XML Load Failed" : "OK";
        $this->Xml = isset($this->Xml->vocabulary) ? $this->Xml->vocabulary : $this->Xml;
    }

    /**
    * return string indicate status of last action
    */
    function Status() {  return $this->StatusString;  }

    /**
    * return hash string for vocabulary (generated from file name)
    * @return 32-character hash string.
    */
    function Hash() 
    {
        return self::HashForFile($this->FileName);
    }

    /**
    * return hash string for specified vocabulary file name
    * @param FileName Name of .voc file containing vocabulary.
    * @return 32-character hash string.
    */
    static function HashForFile($FileName = NULL) 
    {
        return strtoupper(md5($FileName));
    }

    /**
    * return vocabulary name
    */
    function Name() {  return $this->XmlVal("name");  }

    /**
    * return vocabulary description
    */
    function Description() {  return $this->XmlVal("description");  }

    /**
    * return URL attached to vocabulary
    */
    function Url() {  return $this->XmlVal("url");  }

    /**
    * return version number for vocabulary
    */
    function Version() {  return $this->XmlVal("version");  }

    /**
    * indicate whether vocabulary has associated qualifier
    */
    function HasQualifier()
    {
        return strlen($this->QualifierName())
                && (strlen($this->QualifierNamespace()) 
                        || strlen($this->QualifierUrl()));
    }

    /**
    * return qualifier name
    */
    function QualifierName()
    {
        return isset($this->Xml->qualifier->name)
                ? (string)$this->Xml->qualifier->name : "";
    }

    /**
    * return qualifier namespace
    */
    function QualifierNamespace()
    {
        return isset($this->Xml->qualifier->namespace)
                ? (string)$this->Xml->qualifier->namespace : "";
    }

    /**
    * return qualifier URL
    */
    function QualifierUrl()
    {
        return isset($this->Xml->qualifier->url)
                ? (string)$this->Xml->qualifier->url : "";
    }

    /**
    * Get name of owning (maintaining) organization.
    * @return Name of owner or empty string if no owner name available.
    */
    function OwnerName()
    {
        return isset($this->Xml->owner->name)
                ? (string)$this->Xml->owner->name : "";
    }

    /**
    * Get primary URL for owning (maintaining) organization.
    * @return URL for owner or empty string if no owner URL available.
    */
    function OwnerUrl()
    {
        return isset($this->Xml->owner->url)
                ? (string)$this->Xml->owner->url : "";
    }

    /**
    * retrieve vocabulary terms as multi-dimensional array
    */
    function TermArray()
    {
        $Terms = $this->ExtractTermSet($this->Xml);

        # return array of terms to caller
        return $Terms;
    }

    /**
    * retrieve vocabulary terms as flat array with double-dash separators
    */
    function TermList()
    {
        $TermTree = $this->TermArray();
        $Terms = $this->BuildTermList("", $TermTree);
        return $Terms;
    }

    # ---- PRIVATE INTERFACE -------------------------------------------------

    var $FileName;
    var $StatusString;
    var $Xml;

    function XmlVal($ValueName)
    {
        return isset($this->Xml->{$ValueName})
                ? (string)$this->Xml->{$ValueName} : "";
    }

    function ExtractTermSet($Tree)
    {
        $Terms = array();
        foreach ($Tree->term as $Term)
        {
            if (isset($Term->value))
            {
                $Terms[(string)$Term->value] = $this->ExtractTermSet($Term);
            }
            else
            {
                $Terms[(string)$Term] = array();
            }
        }
        return $Terms;
    }

    # build double-dash separated term list from hierarchical array
    function BuildTermList($Prefix, $TermTree)
    {
        $Terms = array();
        foreach ($TermTree as $Term => $Children)
        {
            $Term = trim($Term);
            $NewTerm = strlen($Prefix) ? $Prefix." -- ".$Term : $Term;
            $Terms[] = $NewTerm;
            $Terms = array_merge($Terms, $this->BuildTermList($NewTerm, $Children));
        }
        return $Terms;
    }
}


?>
