<?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