/**
  * @param string $name_
  * @param array $args_
  *
  * @return \Components\Enumeration
  *
  * @throws \Components\Runtime_Exception
  */
 public static function __callStatic($name_, array $args_ = [])
 {
     $type = get_called_class();
     if (__CLASS__ === $type) {
         throw new Exception_Abstract_Type('components/enumeration', 'Enumeration can not be invoked directly.');
     }
     if (isset(self::$m_enumInstances[$type][$name_])) {
         return self::$m_enumInstances[$type][$name_];
     }
     if (false === isset(self::$m_enums[$type])) {
         self::initializeType($type);
     }
     if (false === array_key_exists($name_, self::$m_enums[$type])) {
         $trace = debug_backtrace(false);
         $caller = $trace[1];
         throw new Exception_NotImplemented('components/enumeration', sprintf('Call to undefined method %1$s::%2$s() in %3$s on line %4$d.', $type, $name_, $caller['file'], $caller['line']));
     }
     if (!($concrete = Runtime_Classloader::lookup(String::typeToNamespace($type) . '/' . String::typeToPath($name_)))) {
         $concrete = $type;
     }
     if (0 < count($args_)) {
         array_unshift($args_, constant("{$type}::{$name_}"));
         array_unshift($args_, self::$m_enums[$type][$name_]);
         $class = new \ReflectionClass($concrete);
         return $class->newInstanceArgs($args_);
     }
     // Cache simple enum instances.
     // XXX Instances MUST be state-less.
     return self::$m_enumInstances[$type][$name_] = new $concrete(self::$m_enums[$type][$name_], constant("{$type}::{$name_}"));
 }
 private static function initializeMethods()
 {
     if (false === (self::$m_methods = Cache::get('components/rest/methods'))) {
         self::$m_methods = [];
     }
     foreach (self::$m_resources as $resource) {
         if (isset(self::$m_methods[$resource])) {
             continue;
         }
         $annotations = Annotations::get($resource);
         foreach ($annotations->getMethodAnnotations() as $methodName => $methodAnnotations) {
             $httpMethods = [];
             foreach ($methodAnnotations as $methodAnnotationName => $methodAnnotation) {
                 if ($methodAnnotation instanceof Annotation_Method) {
                     $httpMethods[$methodAnnotationName] = $methodAnnotationName;
                 }
             }
             if (count($httpMethods)) {
                 $type = new \ReflectionClass($resource);
                 $method = $type->getMethod($methodName);
                 $parameters = $method->getParameters();
                 $path = [];
                 $query = [];
                 foreach ($parameters as $parameter) {
                     $parameterAnnotations = $annotations->getParameterAnnotations($methodName, $parameter->name);
                     if (isset($parameterAnnotations[Annotation_Param_Query::NAME])) {
                         if (isset($parameterAnnotations[Annotation_Param_Query::NAME]->name)) {
                             $name = $parameterAnnotations[Annotation_Param_Query::NAME]->name;
                         } else {
                             $name = $parameter->name;
                         }
                         if (isset($parameterAnnotations[Annotation_Param_Query::NAME]->type)) {
                             $type = $parameterAnnotations[Annotation_Param_Query::NAME]->type;
                             if (Primitive::isNative($type)) {
                                 $type = Primitive::asBoxed($type);
                             } else {
                                 if ($lookupType = Runtime_Classloader::lookup($type)) {
                                     $type = $lookupType;
                                 }
                             }
                         } else {
                             if ($type = $parameter->getClass()) {
                                 $type = $type->name;
                             } else {
                                 $type = String::TYPE;
                             }
                         }
                         if (isset($parameterAnnotations[Annotation_Param_Query::NAME]->default)) {
                             $value = $parameterAnnotations[Annotation_Param_Query::NAME]->default;
                         } else {
                             $value = null;
                         }
                         $query[$parameter->name] = ['name' => $name, 'type' => $type, 'value' => $value];
                     } else {
                         if ($parameter->isOptional()) {
                             if ($type = $parameter->getClass()) {
                                 $query[$parameter->name] = $type->name;
                             } else {
                                 $query[$parameter->name] = String::TYPE;
                             }
                         } else {
                             if (isset($parameterAnnotations[Annotation_Param_Path::NAME]->type)) {
                                 $type = $parameterAnnotations[Annotation_Param_Path::NAME]->type;
                                 if (Primitive::isNative($type)) {
                                     $type = Primitive::asBoxed($type);
                                 } else {
                                     if ($lookupType = Runtime_Classloader::lookup($type)) {
                                         $type = $lookupType;
                                     }
                                 }
                                 $path[$parameter->name] = $type;
                             } else {
                                 if ($type = $parameter->getClass()) {
                                     $path[$parameter->name] = $type->name;
                                 } else {
                                     $path[$parameter->name] = String::TYPE;
                                 }
                             }
                         }
                     }
                 }
                 $matches = [];
                 preg_match('/\\@return\\s+([\\a-z]+)\\n/i', $method->getDocComment(), $matches);
                 $return = null;
                 if (isset($matches[1])) {
                     $return = $matches[1];
                 }
                 self::$m_methods[$resource][$methodName] = ['name' => $methodName, 'methods' => $httpMethods, 'path' => $path, 'query' => $query, 'return' => $return];
             }
         }
     }
     Cache::set('components/rest/methods', self::$m_methods);
 }
 protected function initialize()
 {
     $a = Annotations::get($this->entityType);
     $this->entityName = Runtime_Classloader::lookupName($this->entityType);
     if ($annotation = $a->getTypeAnnotation(Annotation_Name::NAME)) {
         $this->collectionName = $a->getTypeAnnotation(Annotation_Name::NAME)->value;
     } else {
         $this->collectionName = strtolower(substr($this->entityType, strrpos($this->entityType, '_') + 1));
     }
     if ($annotation = $a->getTypeAnnotation(Annotation_Collection::NAME)) {
         $this->collectionType = Runtime_Classloader::lookup($annotation->value);
     } else {
         $this->collectionType = Entity_Collection::TYPE;
     }
     $this->autoIncrement = true;
     foreach ($a->getPropertyAnnotations() as $property => $annotations) {
         if (isset($annotations[Annotation_Id::NAME])) {
             $this->collectionPrimaryKey = $property;
             $this->collectionPrimaryKeyAutoIncrement = Boolean::valueIsTrue($annotations[Annotation_Id::NAME]->auto);
         }
     }
 }