/**
  * @see \Components\Marshaller::unmarshal() \Components\Marshaller::unmarshal()
  */
 public function unmarshal($data_, $type_)
 {
     if (Primitive::isNative($type_)) {
         $type = Primitive::asBoxed($type_);
         return $type::cast($data_);
     }
     $type = new \ReflectionClass($type_);
     if ($type->isSubclassOf('Components\\Value')) {
         return $type_::valueOf($data_);
     }
     if ($type->isSubclassOf('Components\\Serializable_Json')) {
         $instance = new $type_();
         return $instance->unserializeJson($data_);
     }
     return $this->m_mapper->hydrateForType($type_, json_decode($data_, true));
 }
 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);
 }
 /**
  * @param string $type_
  *
  * @return array|string
  */
 public static function arrayForType($type_)
 {
     if (isset(self::$m_cache[$type_])) {
         return self::$m_cache[$type_];
     }
     if ($map = Cache::get('components/object/properties/' . md5($type_))) {
         return self::$m_cache[$type_] = $map;
     }
     $annotations = Annotations::get($type_);
     $map = [];
     foreach ($annotations->getPropertyAnnotations() as $propertyName => $propertyAnnotations) {
         if (isset($propertyAnnotations[Annotation_Transient::NAME])) {
             continue;
         }
         $property = array('name' => $propertyName, 'type' => null, 'nameMapped' => $propertyName, 'typeMapped' => null);
         foreach ($propertyAnnotations as $annotation) {
             if ($annotation instanceof Annotation_Type) {
                 if (false === strpos($annotation->value, '[')) {
                     $property['type'] = $annotation->value;
                     if (Primitive::isNative($property['type'])) {
                         $property['type'] = Primitive::asBoxed($property['type']);
                     }
                 } else {
                     if (false !== ($pos = strpos($annotation->value, '[]'))) {
                         $property['type'] = HashMap::TYPE;
                         $property['args'] = ltrim(substr($annotation->value, $pos), '\\');
                         if (Primitive::isNative($property['args'])) {
                             $property['args'] = Primitive::asBoxed($property['args']);
                         }
                     } else {
                         $annotationValue = rtrim($annotation->value, ']');
                         $property['type'] = ltrim(substr($annotationValue, 0, strpos($annotationValue, '[')), '\\');
                         $property['args'] = ltrim(substr($annotationValue, strpos($annotationValue, '[') + 1), '\\');
                         if (Primitive::isNative($property['type'])) {
                             $property['type'] = Primitive::asBoxed($property['type']);
                         }
                         if (Primitive::isNative($property['args'])) {
                             $property['args'] = Primitive::asBoxed($property['args']);
                         }
                     }
                 }
             }
             if ($annotation instanceof Annotation_Name) {
                 $property['nameMapped'] = $annotation->value;
             }
         }
         $map[$propertyName] = $property;
     }
     Cache::set('components/object/properties/' . md5($type_), $map);
     return self::$m_cache[$type_] = $map;
 }