fruffl icon

Strict Array

fruffl | 02/23/13 12:18:52 PM UTC | 0 ⭐ | 267 👁️ | Never ⏰ | []
PHP |

10.84 KB

|

None

|

0 👍

/

0 👎

<?PHP
    NAMESPACE ILLI\Core\Std\Def;
    USE ILLI\Core\Std\Exception\ArgumentExpectedException;
    USE ILLI\Core\Std\Def;
    USE ILLI\Core\Std\Def\__const_Type;
    USE ILLI\Core\Std\Def\ADV;
    USE ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentMethodCallException;
    USE ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentInitializationException;
    USE ILLI\Core\Std\Spl\FsbCollection;
    USE ILLI\Core\Util\Spl;
    
    CLASS ADVArrayKeyValue EXTENDS \ILLI\Core\Std\Def\ADV
    {
        /**
         * cache ADT for key and value
         *
         * :index<long>
         *  0   key
         *  1   value
         *
         * :hashAddr<string>
         *  instance of get_called_class(): ILLI\Core\Std\Def\ADV*
         *  instance of __CLASS__:      ILLI\Core\Std\Def\ADVArrayKeyValue<hash>
         *
         * :ADT<ILLI\Core\Std\Def\ADT>
         *  the ADT for {:index}
         *
         * @var     array [{:hashAddr} => ILLI\Core\Std\Spl\FsbCollection[{:index} => ILLI\Core\Std\Spl\FsbCollection[long offset => {:ADT}]]]
         */
        private static $__kvgc = NULL;
        
        #:ILLI\Core\Std\Def\ADV:
        /**
         * Instantiate a new ADVArray with ADT for key and value.
         *
         * The base-type for this ADV is an array. The difference to ADVArray is an ADT definition for offset-key and -value.
         *
         * @param   string  $__defineKeyType    {:gcType}
         * @param   array   $__defineKeyType    [{:offset} => {:gcType}]
         * @param   string  $__defineValType    {:gcType}
         * @param   array   $__defineValType    [{:offset} => {:gcType}]
         * @param   array   $__data         initial-array
         * @catchable   ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentInitializationException
         * @see     ILLI\Core\Std\Def\ADV::__construct()
         * @see     ILLI\Core\Std\Def::types()
         */
        public function __construct($__defineKeyType = NULL, $__defineValType = NULL, $__data = NULL)
        {
            try
            {
                parent::__construct([__const_Type::SPL_ARRAY]);
                
                $t = &self::$__kvgc[$this->getName()];
                
                if(FALSE === isset($t))
                {
                    $t = FsbCollection::fromArray([
                        FsbCollection::fromArray(NULL === $__defineKeyType ? [] : Def::types((array) $__defineKeyType)),
                        FsbCollection::fromArray(NULL === $__defineValType ? [] : Def::types((array) $__defineValType))]);
                }
                
                if(NULL !== $__data)
                    $this->set($__data);
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentInitializationException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentInitializationException($E, ['class' => get_called_class()])
                    : new $e($E, ['class' => get_called_class()]);
            }
        }
        
        /**
         * Destroy anonymous ATV definitions
         *
         * @catchable   ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentMethodCallException ComponentMethodCallException::ERROR_DTOR
         * @void
         */
        public function __destruct()
        {
            try
            {
                if(($c = get_called_class()) === __CLASS__)
                    unset(self::$__kvgc[$this->getName()]);
                
                parent::__destruct();
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_DTOR, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_DTOR, ['method' => __METHOD__]);
            }
        }
        
        /**
         * value-validation, offset-validation
         *
         * use gc-ADT to validate the value; use kvgc-ADT to validate the offset-name and the offset-value
         *
         * @param   mixed $__value
         * @return  boolean
         * @catchable   ILLI\Core\Std\Exception\ADVArrayKeyValue\ComponentMethodCallException
         * @see     ILLI\Core\Std\Def\ADT::validate()
         * @see     ILLI\Core\Std\Def\ADV::validate()
         */
        public function validate($__value)
        {
            try
            {
                if(FALSE === $this->getGC()->evaluate('validate', [$__value]))
                    return FALSE;
                
                foreach($__value as $k => $v)
                {
                    if(FALSE === $this->validateKey($k))
                        return FALSE;
                        
                    if(FALSE === $this->validateVal($v))
                        return FALSE;
                }
            
                return TRUE;
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_VALIDATE, ['method' => __METHOD__]);
            }
        }
        
        /**
         * store data when value-type equals with gc-ADT, when offset-type equals with kvgc-ADT and when offset-value equals with kvgc-ADT
         *
         * @param   mixed $__value
         * @return  this
         * @throws  ILLI\Core\Std\Exception\ArgumentExpectedException on validation-fail
         * @catchable   ILLI\Core\Std\Exception\ADV\ComponentMethodCallException
         * @see     ::validate()
         */
        public function set($__value)
        {
            $c = get_called_class();
            $e = $c.'\ComponentMethodCallException';
                
            try
            {
                if(FALSE === parent::validate($__value))
                {
                    $E = new ArgumentExpectedException
                    ([
                        'target'    => get_called_class(),
                        'expected'  => implode('|', array_unique($this->getGC()->invoke('toString'))),
                        'detected'  => $t = getType($v = $__value),
                        'value'     => is_object($v) ? get_class($v) : (is_scalar($v) ? $v : NULL)
                    ]);
                    
                    throw ($c === __CLASS__ || FALSE === class_exists($e))
                        ? new ComponentMethodCallException($E, ['method' => __METHOD__], ComponentMethodCallException::ERROR_SET_TYPE_EXPECTED)
                        : new $e($E, ['method' => __METHOD__], $e::ERROR_SET_TYPE_EXPECTED);
                }
                
                $i = 0;
                foreach($__value as $k => $v)
                {
                    if(FALSE === $this->validateKey($k))
                    {
                        $E = new ArgumentExpectedException([
                            'target'    => $this->getName().'['.$i.']',
                            'expected'  => implode('|', array_unique($this->getKeyGC()->invoke('toString'))), 
                            'detected'  => $t = getType($k),
                            'value'     => is_object($k) ? get_class($k) : (is_scalar($k) ? $k : NULL)
                        ]);
                        
                        $a =
                        [
                            'offset'    => $i,
                            'class'     => get_called_class()
                        ];
                        
                        throw ($c === __CLASS__ || FALSE === class_exists($e))
                            ? new ComponentMethodCallException($E, $a, ComponentMethodCallException::SET_OFFSET_KEY_TYPE_EXPECTED)
                            : new $e($E, $a, $e::SET_OFFSET_KEY_TYPE_EXPECTED);
                    }
                        
                    if(FALSE === $this->validateVal($v))
                    {
                        $E = new ArgumentExpectedException([
                            'target'    => $this->getName().'['.$i.']',
                            'expected'  => implode('|', array_unique($this->getValGC()->invoke('toString'))), 
                            'detected'  => $t = getType($v),
                            'value'     => is_object($v) ? get_class($v) : (is_scalar($v) ? $v : NULL)
                        ]);
                        
                        $a =
                        [
                            'offset'    => $i,
                            'class'     => get_called_class()
                        ];
                        
                        throw ($c === __CLASS__ || FALSE === class_exists($e))
                            ? new ComponentMethodCallException($E, $a, ComponentMethodCallException::SET_OFFSET_VAL_TYPE_EXPECTED)
                            : new $e($E, $a, $e::SET_OFFSET_VAL_TYPE_EXPECTED);
                    }
                    
                    $i++;
                }
            
                $this->__data = $__value;
                return $this;
                
            }
            catch(ComponentMethodCallException $E)
            {
                throw $E;
            }
            catch(\Exception $E)
            {
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_SET, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_SET, $e::ERROR_SET,  ['method' => __METHOD__]);
            }
        }
        
        protected function createHashAddr(array $__defineTypes = [])
        {
            try
            {
                #~ performanced ADT: cache request by called-class; otherwise by hash
                return ($c = get_called_class()) === __CLASS__ ? Spl::nameWithHash($c, $this) : $c;
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_CREATE_HASH_ADDR, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_CREATE_HASH_ADDR, ['method' => __METHOD__]);
            }
        }
        #::
        
        /**
         * offset key validation
         *
         * use kvgc-ADT to validate the offset-name
         *
         * @param   mixed $__value
         * @return  boolean
         * @catchable   ILLI\Core\Std\Exception\ADVArrayKeyValue\ComponentMethodCallException
         * @see     ILLI\Core\Std\Def\ADT::validate()
         */
        public function validateKey($__value)
        {
            try
            {
                return $this->getKeyGC()->evaluate('validate', [$__value]);
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE_OFFSET_KEY, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_VALIDATE_OFFSET_KEY, ['method' => __METHOD__]);
            }
        }
        
        /**
         * offset value validation
         *
         * use kvgc-ADT to validate the offset-value
         *
         * @param   mixed $__value
         * @return  boolean
         * @catchable   ILLI\Core\Std\Exception\ADVArrayKeyValue\ComponentMethodCallException
         * @see     ILLI\Core\Std\Def\ADT::validate()
         */
        public function validateVal($__value)
        {
            try
            {
                return $this->getValGC()->evaluate('validate', [$__value]);
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE_OFFSET_VAL, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_VALIDATE_OFFSET_VAL, ['method' => __METHOD__]);
            }
        }
        
        /**
         * get ADT definition for offset-key
         *
         * @return  ILLI\Core\Std\Spl\FsbCollection
         * @catchable   ILLI\Core\Std\Exception\ADV\ComponentMethodCallException
         */
        public function getKeyGC()
        {
            try
            {
                return self::$__kvgc[$this->getName()]->offsetGet(0);
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_GET_GC_KEY, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_GET_GC_KEY, ['method' => __METHOD__]);
            }
        }
        
        /**
         * get ADT definition for offset-value
         *
         * @return  ILLI\Core\Std\Spl\FsbCollection
         * @catchable   ILLI\Core\Std\Exception\ADV\ComponentMethodCallException
         */
        public function getValGC()
        {
            try
            {
                return self::$__kvgc[$this->getName()]->offsetGet(1);
            }
            catch(\Exception $E)
            {
                $c = get_called_class();
                $e = $c.'\ComponentMethodCallException';
                throw ($c === __CLASS__ || FALSE === class_exists($e))
                    ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_GET_GC_VAL, ['method' => __METHOD__])
                    : new $e($E, $e::ERROR_GET_GC_VAL, ['method' => __METHOD__]);
            }
        }
    }

Comments