fruffl icon

AbstractDataType Builder

fruffl | 02/20/13 02:17:16 AM UTC | 0 ⭐ | 289 👁️ | Never ⏰ | []
PHP |

7.32 KB

|

None

|

0 👍

/

0 👎

<?PHP
    NAMESPACE ILLI\Core\Std\Def;
    USE ILLI\Core\Std\Def\__const_Type;
    USE ILLI\Core\Std\Def\ADT\ComponentInitializationException;
    USE ILLI\Core\Std\Def\ADT\ComponentMethodCallException;
    USE ILLI\Core\Std\Exception\ArgumentExpectedException;
    USE ILLI\Core\Std\Exception\ArgumentLengthZeroException;
    USE ILLI\Core\Std\Exception\ArgumentInUseException;
    USE ILLI\Core\Std\Exception\NotSupportedException;
    USE ILLI\Core\Std\Spl\Fsb;
    USE ILLI\Core\Util\Spl;
    
    CLASS ADT EXTENDS \ILLI\Core\Std\Spl\Fsb
    {
        /**
         * cache typedef request
         *
         * :hashAddr<string>
         *  instance of get_called_class(): ILLI\Core\Std\Def\ADT*
         *  instance of __CLASS__:      ILLI\Core\Std\Def\ADT<hash>
         *
         * :adtDef<ILLI\Core\Std\Spl\Fsb>
         *  collection of defined __const_Type(s)
         *
         * @var     array [{:hashAddr} => {:adtDef}]
         */
        private static $__gc = [];
        
        /**
         * Instantiate a new Abstract Data Type.
         *
         * define ADT
         *
         * :offset<long>
         *  zero-based index
         *
         * :gcType<string>
         *  a valid __const_Type
         *
         * @param   array $__defineTypes [{:offset} => {:gcType}]
         * @throws  ILLI\Core\Std\Exception\ADT\ComponentInitializationException
         * @see     ILLI\Core\Std\Def\__const_Type
         * @see     ILLI\Core\Std\Def\ADTInstance
         * @see     ILLI\Core\Std\Spl\Fsb
         */
        public function __construct(array $__defineTypes = [])
        {
            try
            {
                if([] === $__defineTypes)
                    throw new ArgumentLengthZeroException;
                
                $n = $this->createHashAddr($__defineTypes);
                $t = &self::$__gc[$n];      
                
                parent::setSize(1);
                parent::offsetSet(0, $n);
                
                if(FALSE === isset($t))
                    $t = Fsb::fromArray($this->parseDef($__defineTypes));
            }
            catch(\Exception $E)
            {
                throw new ComponentInitializationException($E, ['class' => get_called_class()]);
            }
        }
        
        /**
         * value validation
         *
         * The type of given value equals with one of the registered gc-types
         *
         * @param   mixed $__value
         * @return  boolean
         * @see     ILLI\Core\Std\Def\__const_Type
         */
        public function validate($__value)
        {
            try
            {
                $v = &$__value;
                $t = getType($v);
                
                foreach($this->getGC() as $h)
                {
                    if($t === $h
                    ||($t === __const_Type::SPL_OBJECT && (class_exists($h) || interface_exists($h)) && (is_subclass_of($v, $h) || $v instanceOf $h)))
                        return TRUE;
                }
                
                return FALSE;
            }
            catch(\Exception $E)
            {
                throw new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE, ['method' => __METHOD__]);
            }
        }
        
        /**
         * get ADT-gc hash address
         *
         * @return  string
         * @see     ::$__gc
         */
        public function getName()
        {
            try
            {
                return parent::offsetGet(0);
            }
            catch(\Exception $E)
            {
                throw new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_GET_NAME, ['method' => __METHOD__]);
            }
        }
        
        /**
         * get ADT-gc
         *
         * @return  ILLI\Core\Std\Spl\Fsb
         * @see     ::$__gc
         */
        public function getGC()
        {
            try
            {
                return self::$__gc[$this->getName()];
            }
            catch(\Exception $E)
            {
                throw new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_GET_GC, ['method' => __METHOD__]);
            }
        }
        
        /**
         * join registered gc-type(s)
         *
         * @return  ILLI\Core\Std\Spl\Fsb
         * @see     ::$__gc
         * @see     ILLI\Core\Std\Def\__const_Type
         */
        public function toString()
        {
            try
            {
                return implode('|', $this->getGC()->toArray());
            }
            catch(\Exception $E)
            {
                throw new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_TO_STRING, ['method' => __METHOD__]);
            }
        }
        
        /**
         * generate gc-hash-address from called-class or from spl_object_hash
         *
         * :offset<long>
         *  zero-based index
         *
         * :gcType<string>
         *  a valid __const_Type
         *
         * @param   array $__defineTypes [{:offset} => {:gcType}]
         * @return  string
         * @see     ::$__gc
         */
        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)
            {
                throw new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_CREATE_HASH_ADDR, ['method' => __METHOD__]);
            }
        }
        
        /**
         * validate typedef request
         *
         * :offset<long>
         *  zero-based index
         *
         * :gcType<string>
         *  a valid __const_Type
         *
         * @param   array $__defineTypes [{:offset} => {:gcType}]
         * @throws  ILLI\Core\Std\Exception\ArgumentExpectedException when {:gcType} is not a string
         */
        protected function parseDef(array $__defineTypes)
        {
            try
            {
                $r = [];
                
                foreach($__defineTypes as $k => $v)
                {
                    if(FALSE === is_string($v))
                        throw new ArgumentExpectedException([
                            'target'    => $this->getName().'['.$k.']',
                            'expected'  => 'string',
                            'detected'  => $t = getType($v),
                            'value'     => is_object($v)
                                        ? get_class($v)
                                        : ((is_string($v) && (class_exists($v) || interface_exists($v))) || is_scalar($v)) ? $v : $t
                        ]);
                        
                    $r[$k] = $v;
                }
                
                if([] === $r)
                    throw new ArgumentLengthZeroException;
                
                return $r;
            }
            catch(\Exception $E)
            {
                throw new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_PARSE_DEF, ['method' => __METHOD__]);
            }
        }
        
        #:ILLI\Core\Std\Spl\Fsb:
            #:NotSupported:
            /**
             * @notSupported
             * @throws  ILLI\Core\Std\Exception\NotSupportedException
             */
            public function setSize($__size)
            {
                throw new NotSupportedException([
                    'target' => __METHOD__
                ]);
            }
            
            /**
             * @notSupported
             * @throws  ILLI\Core\Std\Exception\NotSupportedException
             */
            public function offsetSet($__offset, $__value)
            {
                throw new NotSupportedException([
                    'target' => __METHOD__
                ]);
            }
            
            /**
             * @notSupported
             * @throws  ILLI\Core\Std\Exception\NotSupportedException
             */
            public function offsetUnset($__offset)
            {
                throw new NotSupportedException([
                    'target' => __METHOD__
                ]);
            }
            #::
            
            #:gc:
            public function getSize()
            {
                return $this->getGC()->getSize();
            }
            
            public function offsetGet($__offset)
            {
                return $this->getGC()->offsetGet($__offset);
            }
            
            public function offsetExists($__offset)
            {
                return $this->getGC()->offsetExists($__offset);
            }
            
            public function rewind()
            {
                return $this->getGC()->rewind();
            }
            
            public function end()
            {
                return $this->getGC()->end();
            }
            
            public function valid()
            {
                return $this->getGC()->valid();
            }
            
            public function current()
            {
                return $this->getGC()->current();
            }
            
            public function key()
            {
                return $this->getGC()->key();
            }
            
            public function prev()
            {
                return $this->getGC()->prev();
            }
            
            public function next()
            {
                return $this->getGC()->next();
            }
            
            public function count()
            {
                return $this->getGC()->count();
            }
            
            public function keys()
            {
                return $this->getGC()->keys();
            }
            
            public function values()
            {
                return $this->getGC()->values();
            }
            #::
        #::
    }

Comments