<?PHP
#
#   FILE:  Tags_ImmutableStruct.php
#
#   Struct data members should be declared as protected in subclasses.
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2011 Internet Scout Project
#   http://scout.wisc.edu/
#

abstract class Tags_ImmutableStruct implements IteratorAggregate
{

    /**
     * Populate the struct with the given array values. A value will only be
     * used if its key has the same name as one of the protected properties
     * of the subclass.
     * @param $Values array values with which to populate the struct
     */
    public function __construct(array $Values)
    {
        foreach ($Values as $Name => $Value)
        {
            if (property_exists($this, $Name))
            {
                $this->$Name = $Value;
            }
        }
    }

    /**
     * Allow access to a protected property value.
     * @param $Name protected property name
     * @return the value of the protected property
     * @throws Exception if the property doesn't exist
     */
    public function __get($Name)
    {
        if (!$this->HasProperty($Name))
        {
            throw new Exception("Property doesn't exist");
        }

        return $this->$Name;
    }

    /**
     * Allow iteration of the struct's values.
     * @return an ArrayIterator object containing the struct's properties
     */
    public function getIterator()
    {
        return new ArrayIterator(get_object_vars($this));
    }

    /**
     * Determine if the current object has the given property.
     * @param $Name property name
     * @return TRUE if the current object has the property or FALSE otherwise
     */
    protected function HasProperty($Name)
    {
        # isset() is used to avoid using property_exists() if possible
        return isset($this->$Name) || property_exists($this, $Name);
    }

}
