Advertisement
fruffl

Strict Array

Feb 23rd, 2013
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.84 KB | None | 0 0
  1. <?PHP
  2.     NAMESPACE ILLI\Core\Std\Def;
  3.     USE ILLI\Core\Std\Exception\ArgumentExpectedException;
  4.     USE ILLI\Core\Std\Def;
  5.     USE ILLI\Core\Std\Def\__const_Type;
  6.     USE ILLI\Core\Std\Def\ADV;
  7.     USE ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentMethodCallException;
  8.     USE ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentInitializationException;
  9.     USE ILLI\Core\Std\Spl\FsbCollection;
  10.     USE ILLI\Core\Util\Spl;
  11.    
  12.     CLASS ADVArrayKeyValue EXTENDS \ILLI\Core\Std\Def\ADV
  13.     {
  14.         /**
  15.          * cache ADT for key and value
  16.          *
  17.          * :index<long>
  18.          *  0   key
  19.          *  1   value
  20.          *
  21.          * :hashAddr<string>
  22.          *  instance of get_called_class(): ILLI\Core\Std\Def\ADV*
  23.          *  instance of __CLASS__:      ILLI\Core\Std\Def\ADVArrayKeyValue<hash>
  24.          *
  25.          * :ADT<ILLI\Core\Std\Def\ADT>
  26.          *  the ADT for {:index}
  27.          *
  28.          * @var     array [{:hashAddr} => ILLI\Core\Std\Spl\FsbCollection[{:index} => ILLI\Core\Std\Spl\FsbCollection[long offset => {:ADT}]]]
  29.          */
  30.         private static $__kvgc = NULL;
  31.        
  32.         #:ILLI\Core\Std\Def\ADV:
  33.         /**
  34.          * Instantiate a new ADVArray with ADT for key and value.
  35.          *
  36.          * The base-type for this ADV is an array. The difference to ADVArray is an ADT definition for offset-key and -value.
  37.          *
  38.          * @param   string  $__defineKeyType    {:gcType}
  39.          * @param   array   $__defineKeyType    [{:offset} => {:gcType}]
  40.          * @param   string  $__defineValType    {:gcType}
  41.          * @param   array   $__defineValType    [{:offset} => {:gcType}]
  42.          * @param   array   $__data         initial-array
  43.          * @catchable   ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentInitializationException
  44.          * @see     ILLI\Core\Std\Def\ADV::__construct()
  45.          * @see     ILLI\Core\Std\Def::types()
  46.          */
  47.         public function __construct($__defineKeyType = NULL, $__defineValType = NULL, $__data = NULL)
  48.         {
  49.             try
  50.             {
  51.                 parent::__construct([__const_Type::SPL_ARRAY]);
  52.                
  53.                 $t = &self::$__kvgc[$this->getName()];
  54.                
  55.                 if(FALSE === isset($t))
  56.                 {
  57.                     $t = FsbCollection::fromArray([
  58.                         FsbCollection::fromArray(NULL === $__defineKeyType ? [] : Def::types((array) $__defineKeyType)),
  59.                         FsbCollection::fromArray(NULL === $__defineValType ? [] : Def::types((array) $__defineValType))]);
  60.                 }
  61.                
  62.                 if(NULL !== $__data)
  63.                     $this->set($__data);
  64.             }
  65.             catch(\Exception $E)
  66.             {
  67.                 $c = get_called_class();
  68.                 $e = $c.'\ComponentInitializationException';
  69.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  70.                     ? new ComponentInitializationException($E, ['class' => get_called_class()])
  71.                     : new $e($E, ['class' => get_called_class()]);
  72.             }
  73.         }
  74.        
  75.         /**
  76.          * Destroy anonymous ATV definitions
  77.          *
  78.          * @catchable   ILLI\Core\Std\Def\ADVArrayKeyValue\ComponentMethodCallException ComponentMethodCallException::ERROR_DTOR
  79.          * @void
  80.          */
  81.         public function __destruct()
  82.         {
  83.             try
  84.             {
  85.                 if(($c = get_called_class()) === __CLASS__)
  86.                     unset(self::$__kvgc[$this->getName()]);
  87.                
  88.                 parent::__destruct();
  89.             }
  90.             catch(\Exception $E)
  91.             {
  92.                 $c = get_called_class();
  93.                 $e = $c.'\ComponentMethodCallException';
  94.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  95.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_DTOR, ['method' => __METHOD__])
  96.                     : new $e($E, $e::ERROR_DTOR, ['method' => __METHOD__]);
  97.             }
  98.         }
  99.        
  100.         /**
  101.          * value-validation, offset-validation
  102.          *
  103.          * use gc-ADT to validate the value; use kvgc-ADT to validate the offset-name and the offset-value
  104.          *
  105.          * @param   mixed $__value
  106.          * @return  boolean
  107.          * @catchable   ILLI\Core\Std\Exception\ADVArrayKeyValue\ComponentMethodCallException
  108.          * @see     ILLI\Core\Std\Def\ADT::validate()
  109.          * @see     ILLI\Core\Std\Def\ADV::validate()
  110.          */
  111.         public function validate($__value)
  112.         {
  113.             try
  114.             {
  115.                 if(FALSE === $this->getGC()->evaluate('validate', [$__value]))
  116.                     return FALSE;
  117.                
  118.                 foreach($__value as $k => $v)
  119.                 {
  120.                     if(FALSE === $this->validateKey($k))
  121.                         return FALSE;
  122.                        
  123.                     if(FALSE === $this->validateVal($v))
  124.                         return FALSE;
  125.                 }
  126.            
  127.                 return TRUE;
  128.             }
  129.             catch(\Exception $E)
  130.             {
  131.                 $c = get_called_class();
  132.                 $e = $c.'\ComponentMethodCallException';
  133.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  134.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE, ['method' => __METHOD__])
  135.                     : new $e($E, $e::ERROR_VALIDATE, ['method' => __METHOD__]);
  136.             }
  137.         }
  138.        
  139.         /**
  140.          * store data when value-type equals with gc-ADT, when offset-type equals with kvgc-ADT and when offset-value equals with kvgc-ADT
  141.          *
  142.          * @param   mixed $__value
  143.          * @return  this
  144.          * @throws  ILLI\Core\Std\Exception\ArgumentExpectedException on validation-fail
  145.          * @catchable   ILLI\Core\Std\Exception\ADV\ComponentMethodCallException
  146.          * @see     ::validate()
  147.          */
  148.         public function set($__value)
  149.         {
  150.             $c = get_called_class();
  151.             $e = $c.'\ComponentMethodCallException';
  152.                
  153.             try
  154.             {
  155.                 if(FALSE === parent::validate($__value))
  156.                 {
  157.                     $E = new ArgumentExpectedException
  158.                     ([
  159.                         'target'    => get_called_class(),
  160.                         'expected'  => implode('|', array_unique($this->getGC()->invoke('toString'))),
  161.                         'detected'  => $t = getType($v = $__value),
  162.                         'value'     => is_object($v) ? get_class($v) : (is_scalar($v) ? $v : NULL)
  163.                     ]);
  164.                    
  165.                     throw ($c === __CLASS__ || FALSE === class_exists($e))
  166.                         ? new ComponentMethodCallException($E, ['method' => __METHOD__], ComponentMethodCallException::ERROR_SET_TYPE_EXPECTED)
  167.                         : new $e($E, ['method' => __METHOD__], $e::ERROR_SET_TYPE_EXPECTED);
  168.                 }
  169.                
  170.                 $i = 0;
  171.                 foreach($__value as $k => $v)
  172.                 {
  173.                     if(FALSE === $this->validateKey($k))
  174.                     {
  175.                         $E = new ArgumentExpectedException([
  176.                             'target'    => $this->getName().'['.$i.']',
  177.                             'expected'  => implode('|', array_unique($this->getKeyGC()->invoke('toString'))),
  178.                             'detected'  => $t = getType($k),
  179.                             'value'     => is_object($k) ? get_class($k) : (is_scalar($k) ? $k : NULL)
  180.                         ]);
  181.                        
  182.                         $a =
  183.                         [
  184.                             'offset'    => $i,
  185.                             'class'     => get_called_class()
  186.                         ];
  187.                        
  188.                         throw ($c === __CLASS__ || FALSE === class_exists($e))
  189.                             ? new ComponentMethodCallException($E, $a, ComponentMethodCallException::SET_OFFSET_KEY_TYPE_EXPECTED)
  190.                             : new $e($E, $a, $e::SET_OFFSET_KEY_TYPE_EXPECTED);
  191.                     }
  192.                        
  193.                     if(FALSE === $this->validateVal($v))
  194.                     {
  195.                         $E = new ArgumentExpectedException([
  196.                             'target'    => $this->getName().'['.$i.']',
  197.                             'expected'  => implode('|', array_unique($this->getValGC()->invoke('toString'))),
  198.                             'detected'  => $t = getType($v),
  199.                             'value'     => is_object($v) ? get_class($v) : (is_scalar($v) ? $v : NULL)
  200.                         ]);
  201.                        
  202.                         $a =
  203.                         [
  204.                             'offset'    => $i,
  205.                             'class'     => get_called_class()
  206.                         ];
  207.                        
  208.                         throw ($c === __CLASS__ || FALSE === class_exists($e))
  209.                             ? new ComponentMethodCallException($E, $a, ComponentMethodCallException::SET_OFFSET_VAL_TYPE_EXPECTED)
  210.                             : new $e($E, $a, $e::SET_OFFSET_VAL_TYPE_EXPECTED);
  211.                     }
  212.                    
  213.                     $i++;
  214.                 }
  215.            
  216.                 $this->__data = $__value;
  217.                 return $this;
  218.                
  219.             }
  220.             catch(ComponentMethodCallException $E)
  221.             {
  222.                 throw $E;
  223.             }
  224.             catch(\Exception $E)
  225.             {
  226.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  227.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_SET, ['method' => __METHOD__])
  228.                     : new $e($E, $e::ERROR_SET, $e::ERROR_SET,  ['method' => __METHOD__]);
  229.             }
  230.         }
  231.        
  232.         protected function createHashAddr(array $__defineTypes = [])
  233.         {
  234.             try
  235.             {
  236.                 #~ performanced ADT: cache request by called-class; otherwise by hash
  237.                 return ($c = get_called_class()) === __CLASS__ ? Spl::nameWithHash($c, $this) : $c;
  238.             }
  239.             catch(\Exception $E)
  240.             {
  241.                 $c = get_called_class();
  242.                 $e = $c.'\ComponentMethodCallException';
  243.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  244.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_CREATE_HASH_ADDR, ['method' => __METHOD__])
  245.                     : new $e($E, $e::ERROR_CREATE_HASH_ADDR, ['method' => __METHOD__]);
  246.             }
  247.         }
  248.         #::
  249.        
  250.         /**
  251.          * offset key validation
  252.          *
  253.          * use kvgc-ADT to validate the offset-name
  254.          *
  255.          * @param   mixed $__value
  256.          * @return  boolean
  257.          * @catchable   ILLI\Core\Std\Exception\ADVArrayKeyValue\ComponentMethodCallException
  258.          * @see     ILLI\Core\Std\Def\ADT::validate()
  259.          */
  260.         public function validateKey($__value)
  261.         {
  262.             try
  263.             {
  264.                 return $this->getKeyGC()->evaluate('validate', [$__value]);
  265.             }
  266.             catch(\Exception $E)
  267.             {
  268.                 $c = get_called_class();
  269.                 $e = $c.'\ComponentMethodCallException';
  270.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  271.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE_OFFSET_KEY, ['method' => __METHOD__])
  272.                     : new $e($E, $e::ERROR_VALIDATE_OFFSET_KEY, ['method' => __METHOD__]);
  273.             }
  274.         }
  275.        
  276.         /**
  277.          * offset value validation
  278.          *
  279.          * use kvgc-ADT to validate the offset-value
  280.          *
  281.          * @param   mixed $__value
  282.          * @return  boolean
  283.          * @catchable   ILLI\Core\Std\Exception\ADVArrayKeyValue\ComponentMethodCallException
  284.          * @see     ILLI\Core\Std\Def\ADT::validate()
  285.          */
  286.         public function validateVal($__value)
  287.         {
  288.             try
  289.             {
  290.                 return $this->getValGC()->evaluate('validate', [$__value]);
  291.             }
  292.             catch(\Exception $E)
  293.             {
  294.                 $c = get_called_class();
  295.                 $e = $c.'\ComponentMethodCallException';
  296.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  297.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_VALIDATE_OFFSET_VAL, ['method' => __METHOD__])
  298.                     : new $e($E, $e::ERROR_VALIDATE_OFFSET_VAL, ['method' => __METHOD__]);
  299.             }
  300.         }
  301.        
  302.         /**
  303.          * get ADT definition for offset-key
  304.          *
  305.          * @return  ILLI\Core\Std\Spl\FsbCollection
  306.          * @catchable   ILLI\Core\Std\Exception\ADV\ComponentMethodCallException
  307.          */
  308.         public function getKeyGC()
  309.         {
  310.             try
  311.             {
  312.                 return self::$__kvgc[$this->getName()]->offsetGet(0);
  313.             }
  314.             catch(\Exception $E)
  315.             {
  316.                 $c = get_called_class();
  317.                 $e = $c.'\ComponentMethodCallException';
  318.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  319.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_GET_GC_KEY, ['method' => __METHOD__])
  320.                     : new $e($E, $e::ERROR_GET_GC_KEY, ['method' => __METHOD__]);
  321.             }
  322.         }
  323.        
  324.         /**
  325.          * get ADT definition for offset-value
  326.          *
  327.          * @return  ILLI\Core\Std\Spl\FsbCollection
  328.          * @catchable   ILLI\Core\Std\Exception\ADV\ComponentMethodCallException
  329.          */
  330.         public function getValGC()
  331.         {
  332.             try
  333.             {
  334.                 return self::$__kvgc[$this->getName()]->offsetGet(1);
  335.             }
  336.             catch(\Exception $E)
  337.             {
  338.                 $c = get_called_class();
  339.                 $e = $c.'\ComponentMethodCallException';
  340.                 throw ($c === __CLASS__ || FALSE === class_exists($e))
  341.                     ? new ComponentMethodCallException($E, ComponentMethodCallException::ERROR_GET_GC_VAL, ['method' => __METHOD__])
  342.                     : new $e($E, $e::ERROR_GET_GC_VAL, ['method' => __METHOD__]);
  343.             }
  344.         }
  345.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement