/**
  * Resolves a class member, which is either a field, a class constant
  * or the `ClassName::class` syntax, which returns the class' literal.
  *
  * @param  lang.XPClass $class
  * @param  var[] $token A token as returned by `token_get_all()`
  * @param  string $context
  * @return var
  */
 protected function memberOf($class, $token, $context)
 {
     if (T_VARIABLE === $token[0]) {
         $field = $class->getField(substr($token[1], 1));
         $m = $field->getModifiers();
         if ($m & MODIFIER_PUBLIC) {
             return $field->get(null);
         } else {
             if ($m & MODIFIER_PROTECTED && $class->isAssignableFrom($context)) {
                 return $field->setAccessible(true)->get(null);
             } else {
                 if ($m & MODIFIER_PRIVATE && $class->getName() === $context) {
                     return $field->setAccessible(true)->get(null);
                 } else {
                     throw new IllegalAccessException(sprintf('Cannot access %s field %s::$%s', implode(' ', Modifiers::namesOf($m)), $class->getName(), $field->getName()));
                 }
             }
         }
     } else {
         if (T_CLASS === $token[0]) {
             return $class->literal();
         } else {
             return $class->getConstant($token[1]);
         }
     }
 }
 /**
  * Invokes the underlying method represented by this Method object, 
  * on the specified object with the specified parameters.
  *
  * Example:
  * <code>
  *   $method= XPClass::forName('lang.Object')->getMethod('toString');
  *
  *   var_dump($method->invoke(new Object()));
  * </code>
  *
  * Example (passing arguments)
  * <code>
  *   $method= XPClass::forName('lang.types.String')->getMethod('concat');
  *
  *   var_dump($method->invoke(new String('Hello'), array('World')));
  * </code>
  *
  * Example (static invokation):
  * <code>
  *   $method= XPClass::forName('util.log.Logger')->getMethod('getInstance');
  *
  *   var_dump($method->invoke(NULL));
  * </code>
  *
  * @param   lang.Object obj
  * @param   var[] args default array()
  * @return  var
  * @throws  lang.IllegalArgumentException in case the passed object is not an instance of the declaring class
  * @throws  lang.IllegalAccessException in case the method is not public or if it is abstract
  * @throws  lang.reflect.TargetInvocationException for any exception raised from the invoked method
  */
 public function invoke($obj, $args = array())
 {
     if (NULL !== $obj && !$obj instanceof $this->_class) {
         throw new IllegalArgumentException(sprintf('Passed argument is not a %s class (%s)', xp::nameOf($this->_class), xp::typeOf($obj)));
     }
     // Check modifiers. If caller is an instance of this class, allow
     // protected method invocation (which the PHP reflection API does
     // not).
     $m = $this->_reflect->getModifiers();
     if ($m & MODIFIER_ABSTRACT) {
         throw new IllegalAccessException(sprintf('Cannot invoke abstract %s::%s', $this->_class, $this->_reflect->getName()));
     }
     $public = $m & MODIFIER_PUBLIC;
     if (!$public && !$this->accessible) {
         $t = debug_backtrace(0);
         $decl = $this->_reflect->getDeclaringClass()->getName();
         if ($m & MODIFIER_PROTECTED) {
             $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl);
         } else {
             $allow = $t[1]['class'] === $decl && self::$SETACCESSIBLE_AVAILABLE;
         }
         if (!$allow) {
             throw new IllegalAccessException(sprintf('Cannot invoke %s %s::%s from scope %s', Modifiers::stringOf($this->getModifiers()), $this->_class, $this->_reflect->getName(), $t[1]['class']));
         }
     }
     // For non-public methods: Use setAccessible() / invokeArgs() combination
     // if possible, resort to __call() workaround.
     try {
         if ($public) {
             return $this->_reflect->invokeArgs($obj, (array) $args);
         }
         if (self::$SETACCESSIBLE_AVAILABLE) {
             $this->_reflect->setAccessible(TRUE);
             return $this->_reflect->invokeArgs($obj, (array) $args);
         } else {
             if ($m & MODIFIER_STATIC) {
                 return call_user_func(array($this->_class, '__callStatic'), "" . $this->_reflect->getName(), $args);
             } else {
                 return $obj->__call("" . $this->_reflect->getName(), $args);
             }
         }
     } catch (SystemExit $e) {
         throw $e;
     } catch (Throwable $e) {
         throw new TargetInvocationException($this->_class . '::' . $this->_reflect->getName(), $e);
     } catch (Exception $e) {
         throw new TargetInvocationException($this->_class . '::' . $this->_reflect->getName(), new XPException($e->getMessage()));
     }
 }
 /**
  * Returns a list of all classes inside a given package
  *
  * @param   lang.reflect.Package 
  * @param   bool recursive whether to include subpackages
  * @return  lang.XPClass[]
  */
 protected static function testClassesIn(Package $package, $recursive)
 {
     $r = array();
     foreach ($package->getClasses() as $class) {
         if (!$class->isSubclassOf('unittest.TestCase') || Modifiers::isAbstract($class->getModifiers())) {
             continue;
         }
         $r[] = $class;
     }
     if ($recursive) {
         foreach ($package->getPackages() as $package) {
             $r = array_merge($r, self::testClassesIn($package, $recursive));
         }
     }
     return $r;
 }
 /**
  * Uses the constructor represented by this Constructor object to create 
  * and initialize a new instance of the constructor's declaring class, 
  * with the specified initialization parameters.
  *
  * Example:
  * <code>
  *   $constructor= XPClass::forName('util.Binford')->getConstructor();
  *
  *   $instance= $constructor->newInstance();
  *   $instance= $constructor->newInstance(array(6100));
  * </code>
  *
  * @param   var[] args
  * @return  lang.Generic
  * @throws  lang.IllegalAccessException in case the constructor is not public or if it is abstract
  * @throws  lang.reflect.TargetInvocationException in case the constructor throws an exception
  */
 public function newInstance(array $args = array())
 {
     // Check whether class is abstract
     $class = new ReflectionClass($this->_class);
     if ($class->isAbstract()) {
         throw new IllegalAccessException('Cannot instantiate abstract class ' . $this->_class);
     }
     // Check modifiers. If caller is an instance of this class, allow private and
     // protected constructor invocation (which the PHP reflection API does not).
     $m = $this->_reflect->getModifiers();
     $public = $m & MODIFIER_PUBLIC;
     if (!$public && !$this->accessible) {
         $t = debug_backtrace(0);
         $decl = $this->_reflect->getDeclaringClass()->getName();
         if ($m & MODIFIER_PROTECTED) {
             $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl);
         } else {
             $allow = $t[1]['class'] === $decl && self::$SETACCESSIBLE_AVAILABLE;
         }
         if (!$allow) {
             throw new IllegalAccessException(sprintf('Cannot invoke %s constructor of class %s from scope %s', Modifiers::stringOf($this->getModifiers()), $this->_class, $t[1]['class']));
         }
     }
     // For non-public constructors: Use setAccessible() / invokeArgs() combination
     // if possible, resort to __call() workaround.
     try {
         if ($public) {
             return $class->newInstanceArgs($args);
         }
         $instance = unserialize('O:' . strlen($this->_class) . ':"' . $this->_class . '":0:{}');
         if (self::$SETACCESSIBLE_AVAILABLE) {
             $this->_reflect->setAccessible(TRUE);
             $this->_reflect->invokeArgs($instance, $args);
         } else {
             $instance->__call("__construct", $args);
         }
         return $instance;
     } catch (SystemExit $e) {
         throw $e;
     } catch (Throwable $e) {
         throw new TargetInvocationException($this->_class . '::<init>', $e);
     } catch (Exception $e) {
         throw new TargetInvocationException($this->_class . '::<init>', new XPException($e->getMessage()));
     }
 }
 /**
  * Get all test cases
  *
  * @param   var[] arguments
  * @return  unittest.TestCase[]
  */
 public function testCasesWith($arguments)
 {
     if (NULL === ($cl = $this->findLoaderFor($this->folder->getURI()))) {
         throw new IllegalArgumentException($this->folder->toString() . ' is not in class path');
     }
     $l = strlen($cl->path);
     $e = -strlen(xp::CLASS_FILE_EXT);
     $it = new FilteredIOCollectionIterator(new FileCollection($this->folder), new ExtensionEqualsFilter(xp::CLASS_FILE_EXT), TRUE);
     $cases = array();
     foreach ($it as $element) {
         $name = strtr(substr($element->getUri(), $l, $e), DIRECTORY_SEPARATOR, '.');
         $class = XPClass::forName($name);
         if (!$class->isSubclassOf('unittest.TestCase') || Modifiers::isAbstract($class->getModifiers())) {
             continue;
         }
         $cases = array_merge($cases, $this->testCasesInClass($class, $arguments));
     }
     if (empty($cases)) {
         throw new IllegalArgumentException('Cannot find any test cases in ' . $this->folder->toString());
     }
     return $cases;
 }
Exemple #6
0
 /**
  * Invokes the underlying method represented by this Method object, 
  * on the specified object with the specified parameters.
  *
  * Example:
  * ```php
  * $method= XPClass::forName('lang.Object')->getMethod('toString');
  * $str= $method->invoke(new Object());
  * ```
  *
  * Example (passing arguments)
  * ```php
  * $method= XPClass::forName('util.Date')->getMethod('format');
  * $str= $method->invoke(Date::now(), ['%d.%m.%Y']);
  * ```
  *
  * Example (static invokation):
  * ```php
  * $method= XPClass::forName('util.log.Logger')->getMethod('getInstance');
  * $log= $method->invoke(null);
  * ```
  *
  * @param   object $obj
  * @param   var[] $args default []
  * @return  var
  * @throws  lang.IllegalArgumentException in case the passed object is not an instance of the declaring class
  * @throws  lang.IllegalAccessException in case the method is not public or if it is abstract
  * @throws  lang.reflect.TargetInvocationException for any exception raised from the invoked method
  */
 public function invoke($obj, $args = [])
 {
     if (null !== $obj && !$obj instanceof $this->_class) {
         throw new IllegalArgumentException(sprintf('Passed argument is not a %s class (%s)', XPClass::nameOf($this->_class), \xp::typeOf($obj)));
     }
     // Check modifiers. If caller is an instance of this class, allow
     // protected method invocation (which the PHP reflection API does
     // not).
     $m = $this->_reflect->getModifiers();
     if ($m & MODIFIER_ABSTRACT) {
         throw new IllegalAccessException(sprintf('Cannot invoke abstract %s::%s', XPClass::nameOf($this->_class), $this->_reflect->getName()));
     }
     $public = $m & MODIFIER_PUBLIC;
     if (!$public && !$this->accessible) {
         $t = debug_backtrace(0, 2);
         $decl = $this->_reflect->getDeclaringClass()->getName();
         if ($m & MODIFIER_PROTECTED) {
             $allow = $t[1]['class'] === $decl || is_subclass_of($t[1]['class'], $decl);
         } else {
             $allow = $t[1]['class'] === $decl;
         }
         if (!$allow) {
             throw new IllegalAccessException(sprintf('Cannot invoke %s %s::%s from scope %s', Modifiers::stringOf($this->getModifiers()), XPClass::nameOf($this->_class), $this->_reflect->getName(), $t[1]['class']));
         }
     }
     try {
         if (!$public) {
             $this->_reflect->setAccessible(true);
         }
         return $this->_reflect->invokeArgs($obj, (array) $args);
     } catch (\lang\SystemExit $e) {
         throw $e;
     } catch (\Throwable $e) {
         throw new TargetInvocationException(XPClass::nameOf($this->_class) . '::' . $this->_reflect->getName(), $e);
     }
 }
Exemple #7
0
 /** Retrieve string representation */
 public function toString() : string
 {
     $signature = '';
     foreach ($this->getParameters() as $param) {
         if ($param->isOptional()) {
             $signature .= ', [' . $param->getTypeName() . ' $' . $param->getName() . '= ' . str_replace("\n", ' ', \xp::stringOf($param->getDefaultValue())) . ']';
         } else {
             $signature .= ', ' . $param->getTypeName() . ' $' . $param->getName();
         }
     }
     if ($exceptions = $this->getExceptionNames()) {
         $throws = ' throws ' . implode(', ', $exceptions);
     } else {
         $throws = '';
     }
     return sprintf('%s %s %s(%s)%s', Modifiers::stringOf($this->getModifiers()), $this->getReturnTypeName(), $this->getName(), substr($signature, 2), $throws);
 }
 /**
  * Asserts given modifiers do not contain abstract
  *
  * @param   int modifiers
  * @throws  unittest.AssertionFailedError
  */
 protected function assertNotAbstract($modifiers)
 {
     $this->assertFalse(Modifiers::isAbstract($modifiers), implode(' | ', Modifiers::namesOf($modifiers)));
 }
 public function staticModifier()
 {
     $this->assertTrue(Modifiers::isStatic(MODIFIER_STATIC));
     $this->assertEquals('public static', Modifiers::stringOf(MODIFIER_STATIC));
 }
 /**
  * Prints package
  *
  * @param   lang.reflect.Package package
  */
 protected static function printPackage($package)
 {
     Console::writeLine('package ', $package->getName(), ' {');
     // Child packages
     foreach ($package->getPackages() as $child) {
         Console::writeLine('  package ', $child->getName());
     }
     // Classes
     $order = array('interface' => array(), 'enum' => array(), 'class' => array());
     foreach ($package->getClasses() as $class) {
         $mod = $class->getModifiers();
         if ($class->isInterface()) {
             $type = 'interface';
             $mod = $mod ^ MODIFIER_ABSTRACT;
         } else {
             if ($class->isEnum()) {
                 $type = 'enum';
             } else {
                 $type = 'class';
             }
         }
         $name = self::displayNameOf($class);
         $order[$type][] = implode(' ', Modifiers::namesOf($mod)) . ' ' . $type . ' ' . self::displayNameOf($class);
     }
     foreach ($order as $type => $classes) {
         if (empty($classes)) {
             continue;
         }
         Console::writeLine();
         sort($classes);
         foreach ($classes as $name) {
             Console::writeLine('  ', $name);
         }
     }
     Console::writeLine('}');
 }
 /**
  * Parses annotation string
  *
  * @param   string input
  * @param   string context the class name
  * @return  [:string] imports
  * @param   int line 
  * @return  [:var]
  * @throws  lang.ClassFormatException
  */
 public static function parseAnnotations($input, $context, $imports = array(), $line = -1)
 {
     static $states = array('annotation', 'annotation name', 'annotation value', 'annotation map key', 'annotation map value', 'multi-value');
     $tokens = token_get_all('<?php ' . trim($input, "[# \t\n\r"));
     $annotations = array(0 => array(), 1 => array());
     $place = $context . (-1 === $line ? '' : ', line ' . $line);
     // Resolve classes
     $resolve = function ($type, $context, $imports) {
         if ('self' === $type) {
             return XPClass::forName($context);
         } else {
             if ('parent' === $type) {
                 return XPClass::forName($context)->getParentclass();
             } else {
                 if (FALSE !== strpos($type, '.')) {
                     return XPClass::forName($type);
                 } else {
                     if (isset($imports[$type])) {
                         return XPClass::forName($imports[$type]);
                     } else {
                         if (isset(xp::$cn[$type])) {
                             return XPClass::forName(xp::$cn[$type]);
                         } else {
                             if (FALSE !== ($p = strrpos($context, '.'))) {
                                 return XPClass::forName(substr($context, 0, $p + 1) . $type);
                             } else {
                                 return XPClass::forName($type);
                             }
                         }
                     }
                 }
             }
         }
     };
     // Class::CONSTANT vs. Class::$MEMBER
     $memberOf = function ($tokens, &$i, $class) use($context) {
         if (T_VARIABLE === $tokens[$i][0]) {
             $field = $class->getField(substr($tokens[$i][1], 1));
             $m = $field->getModifiers();
             if ($m & MODIFIER_PUBLIC) {
                 return $field->get(NULL);
             } else {
                 if ($m & MODIFIER_PROTECTED && $class->isAssignableFrom($context)) {
                     return $field->setAccessible(TRUE)->get(NULL);
                 } else {
                     if ($m & MODIFIER_PRIVATE && $class->getName() === $context) {
                         return $field->setAccessible(TRUE)->get(NULL);
                     } else {
                         throw new IllegalAccessException(sprintf('Cannot access %s field %s::$%s', implode(' ', Modifiers::namesOf($m)), $class->getName(), $field->getName()));
                     }
                 }
             }
         } else {
             return $class->getConstant($tokens[$i][1]);
         }
     };
     // Parse a single value (recursively, if necessary)
     $valueOf = function ($tokens, &$i) use(&$valueOf, &$memberOf, &$resolve, $context, $imports) {
         if ('-' === $tokens[$i][0]) {
             $i++;
             return -1 * $valueOf($tokens, $i);
         } else {
             if ('+' === $tokens[$i][0]) {
                 $i++;
                 return +1 * $valueOf($tokens, $i);
             } else {
                 if (T_CONSTANT_ENCAPSED_STRING === $tokens[$i][0]) {
                     return eval('return ' . $tokens[$i][1] . ';');
                 } else {
                     if (T_LNUMBER === $tokens[$i][0]) {
                         return (int) $tokens[$i][1];
                     } else {
                         if (T_DNUMBER === $tokens[$i][0]) {
                             return (double) $tokens[$i][1];
                         } else {
                             if ('[' === $tokens[$i] || T_ARRAY === $tokens[$i][0]) {
                                 $value = array();
                                 $element = NULL;
                                 $key = 0;
                                 $end = '[' === $tokens[$i] ? ']' : ')';
                                 for ($i++, $s = sizeof($tokens);; $i++) {
                                     if ($i >= $s) {
                                         throw new IllegalStateException('Parse error: Unterminated array');
                                     } else {
                                         if ($end === $tokens[$i]) {
                                             $element && ($value[$key] = $element[0]);
                                             break;
                                         } else {
                                             if ('(' === $tokens[$i]) {
                                                 // Skip
                                             } else {
                                                 if (',' === $tokens[$i]) {
                                                     $element || raise('lang.IllegalStateException', 'Parse error: Malformed array - no value before comma');
                                                     $value[$key] = $element[0];
                                                     $element = NULL;
                                                     $key = sizeof($value);
                                                 } else {
                                                     if (T_DOUBLE_ARROW === $tokens[$i][0]) {
                                                         $key = $element[0];
                                                         $element = NULL;
                                                     } else {
                                                         if (T_WHITESPACE === $tokens[$i][0]) {
                                                             continue;
                                                         } else {
                                                             $element && raise('lang.IllegalStateException', 'Parse error: Malformed array - missing comma');
                                                             $element = array($valueOf($tokens, $i));
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                                 return $value;
                             } else {
                                 if ('"' === $tokens[$i] || T_ENCAPSED_AND_WHITESPACE === $tokens[$i][0]) {
                                     throw new IllegalStateException('Parse error: Unterminated string');
                                 } else {
                                     if (T_NS_SEPARATOR === $tokens[$i][0]) {
                                         $type = '';
                                         while (T_NS_SEPARATOR === $tokens[$i++][0]) {
                                             $type .= '.' . $tokens[$i++][1];
                                         }
                                         return $memberOf($tokens, $i, XPClass::forName(substr($type, 1)));
                                     } else {
                                         if (T_STRING === $tokens[$i][0]) {
                                             // constant vs. class::constant
                                             if (T_DOUBLE_COLON === $tokens[$i + 1][0]) {
                                                 $i += 2;
                                                 return $memberOf($tokens, $i, $resolve($tokens[$i - 2][1], $context, $imports));
                                             } else {
                                                 if (defined($tokens[$i][1])) {
                                                     return constant($tokens[$i][1]);
                                                 } else {
                                                     raise('lang.ElementNotFoundException', 'Undefined constant "' . $tokens[$i][1] . '"');
                                                 }
                                             }
                                         } else {
                                             if (T_NEW === $tokens[$i][0]) {
                                                 $type = '';
                                                 while ('(' !== $tokens[$i++]) {
                                                     if (T_STRING === $tokens[$i][0]) {
                                                         $type .= '.' . $tokens[$i][1];
                                                     }
                                                 }
                                                 $class = $resolve(substr($type, 1), $context, $imports);
                                                 for ($args = array(), $arg = NULL, $s = sizeof($tokens);; $i++) {
                                                     if (')' === $tokens[$i]) {
                                                         $arg && ($args[] = $arg[0]);
                                                         break;
                                                     } else {
                                                         if (',' === $tokens[$i]) {
                                                             $args[] = $arg[0];
                                                             $arg = NULL;
                                                         } else {
                                                             if (T_WHITESPACE !== $tokens[$i][0]) {
                                                                 $arg = array($valueOf($tokens, $i));
                                                             }
                                                         }
                                                     }
                                                 }
                                                 return $class->hasConstructor() ? $class->getConstructor()->newInstance($args) : $class->newInstance();
                                             } else {
                                                 throw new IllegalStateException(sprintf('Parse error: Unexpected %s', is_array($tokens[$i]) ? token_name($tokens[$i][0]) : '"' . $tokens[$i] . '"'));
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     };
     // Parse tokens
     try {
         for ($state = 0, $i = 1, $s = sizeof($tokens); $i < $s; $i++) {
             if (T_WHITESPACE === $tokens[$i][0]) {
                 continue;
             } else {
                 if (0 === $state) {
                     // Initial state, expecting @attr or @$param: attr
                     if ('@' === $tokens[$i]) {
                         $annotation = $tokens[$i + 1][1];
                         $param = NULL;
                         $value = NULL;
                         $i++;
                         $state = 1;
                     } else {
                         throw new IllegalStateException('Parse error: Expecting "@"');
                     }
                 } else {
                     if (1 === $state) {
                         // Inside attribute, check for values
                         if ('(' === $tokens[$i]) {
                             $state = 2;
                         } else {
                             if (',' === $tokens[$i]) {
                                 if ($param) {
                                     $annotations[1][$param][$annotation] = $value;
                                 } else {
                                     $annotations[0][$annotation] = $value;
                                 }
                                 $state = 0;
                             } else {
                                 if (']' === $tokens[$i]) {
                                     if ($param) {
                                         $annotations[1][$param][$annotation] = $value;
                                     } else {
                                         $annotations[0][$annotation] = $value;
                                     }
                                     return $annotations;
                                 } else {
                                     if (':' === $tokens[$i]) {
                                         $param = $annotation;
                                         $annotation = NULL;
                                     } else {
                                         if (T_STRING === $tokens[$i][0]) {
                                             $annotation = $tokens[$i][1];
                                         } else {
                                             throw new IllegalStateException('Parse error: Expecting either "(", "," or "]"');
                                         }
                                     }
                                 }
                             }
                         }
                     } else {
                         if (2 === $state) {
                             // Inside braces of @attr(...)
                             if (')' === $tokens[$i]) {
                                 $state = 1;
                             } else {
                                 if (',' === $tokens[$i]) {
                                     trigger_error('Deprecated usage of multi-value annotations in ' . $place, E_USER_DEPRECATED);
                                     $value = (array) $value;
                                     $state = 5;
                                 } else {
                                     if ($i + 2 < $s && ('=' === $tokens[$i + 1] || '=' === $tokens[$i + 2])) {
                                         $key = $tokens[$i][1];
                                         $value = array();
                                         $state = 3;
                                     } else {
                                         $value = $valueOf($tokens, $i);
                                     }
                                 }
                             }
                         } else {
                             if (3 === $state) {
                                 // Parsing key inside @attr(a= b, c= d)
                                 if (')' === $tokens[$i]) {
                                     $state = 1;
                                 } else {
                                     if (',' === $tokens[$i]) {
                                         $key = null;
                                     } else {
                                         if ('=' === $tokens[$i]) {
                                             $state = 4;
                                         } else {
                                             if (is_array($tokens[$i])) {
                                                 $key = $tokens[$i][1];
                                             }
                                         }
                                     }
                                 }
                             } else {
                                 if (4 === $state) {
                                     // Parsing value inside @attr(a= b, c= d)
                                     $value[$key] = $valueOf($tokens, $i);
                                     $state = 3;
                                 } else {
                                     if (5 === $state) {
                                         if (')' === $tokens[$i]) {
                                             // BC: Deprecated multi-value annotations
                                             $value[] = $element;
                                             $state = 1;
                                         } else {
                                             if (',' === $tokens[$i]) {
                                                 $value[] = $element;
                                             } else {
                                                 $element = $valueOf($tokens, $i);
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     } catch (XPException $e) {
         raise('lang.ClassFormatException', $e->getMessage() . ' in ' . $place, $e);
     }
     raise('lang.ClassFormatException', 'Parse error: Unterminated ' . $states[$state] . ' in ' . $place);
 }
Exemple #12
0
 /** Creates a string representation of this field */
 public function toString() : string
 {
     return sprintf('%s %s %s::$%s', Modifiers::stringOf($this->getModifiers()), $this->getTypeName(), $this->getDeclaringClass()->getName(), $this->getName());
 }
 /**
  * Convert data based on type
  *
  * @param   lang.Type type
  * @param   [:var] data
  * @return  var
  */
 public function unmarshal($type, $data)
 {
     if (NULL === $type || $type->equals(Type::$VAR)) {
         // No conversion
         return $data;
     } else {
         if (NULL === $data) {
             // Valid for any type
             return NULL;
         } else {
             if ($type->equals(XPClass::forName('lang.types.String'))) {
                 return new String($this->valueOf($data));
             } else {
                 if ($type->equals(XPClass::forName('util.Date'))) {
                     return $type->newInstance($data);
                 } else {
                     if ($type instanceof XPClass) {
                         foreach ($this->marshallers->keys() as $t) {
                             if ($t->isAssignableFrom($type)) {
                                 return $this->marshallers[$t]->unmarshal($type, $data, $this);
                             }
                         }
                         // Check if a public static one-arg valueOf() method exists
                         // E.g.: Assuming the target type has a valueOf(string $id) and the
                         // given payload data is either a map or an array with one element, or
                         // a primitive, then pass that as value. Examples: { "id" : "4711" },
                         // [ "4711" ] or "4711" - in all cases pass just "4711".
                         if ($type->hasMethod('valueOf')) {
                             $m = $type->getMethod('valueOf');
                             if (Modifiers::isStatic($m->getModifiers()) && Modifiers::isPublic($m->getModifiers()) && 1 === $m->numParameters()) {
                                 if (NULL !== ($arg = $this->keyOf($data))) {
                                     return $m->invoke(NULL, array($this->unmarshal($m->getParameter(0)->getType(), $arg[0])));
                                 }
                             }
                         }
                         // Generic approach
                         $return = $type->newInstance();
                         if (NULL === $data) {
                             $iter = array();
                         } else {
                             if (is_array($data) || $data instanceof Traversable) {
                                 $iter = $data;
                             } else {
                                 $iter = array($data);
                             }
                         }
                         foreach ($iter as $name => $value) {
                             foreach ($this->variantsOf($name) as $variant) {
                                 if ($type->hasField($variant)) {
                                     $field = $type->getField($variant);
                                     $m = $field->getModifiers();
                                     if ($m & MODIFIER_STATIC) {
                                         continue;
                                     } else {
                                         if ($m & MODIFIER_PUBLIC) {
                                             if (NULL !== ($fType = $field->getType())) {
                                                 $field->set($return, $this->unmarshal($fType, $value));
                                             } else {
                                                 $field->set($return, $value);
                                             }
                                             continue 2;
                                         }
                                     }
                                 }
                                 if ($type->hasMethod('set' . $variant)) {
                                     $method = $type->getMethod('set' . $variant);
                                     if ($method->getModifiers() & MODIFIER_PUBLIC) {
                                         if (NULL !== ($param = $method->getParameter(0))) {
                                             $method->invoke($return, array($this->unmarshal($param->getType(), $value)));
                                         } else {
                                             $method->invoke($return, array($value));
                                         }
                                         continue 2;
                                     }
                                 }
                             }
                         }
                         return $return;
                     } else {
                         if ($type instanceof ArrayType) {
                             $return = array();
                             foreach ($data as $element) {
                                 $return[] = $this->unmarshal($type->componentType(), $element);
                             }
                             return $return;
                         } else {
                             if ($type instanceof MapType) {
                                 $return = array();
                                 foreach ($data as $key => $element) {
                                     $return[$key] = $this->unmarshal($type->componentType(), $element);
                                 }
                                 return $return;
                             } else {
                                 if ($type->equals(Primitive::$STRING)) {
                                     return (string) $this->valueOf($data);
                                 } else {
                                     if ($type->equals(Primitive::$INT)) {
                                         return (int) $this->valueOf($data);
                                     } else {
                                         if ($type->equals(Primitive::$DOUBLE)) {
                                             return (double) $this->valueOf($data);
                                         } else {
                                             if ($type->equals(Primitive::$BOOL)) {
                                                 return (bool) $this->valueOf($data);
                                             } else {
                                                 throw new FormatException('Cannot convert to ' . xp::stringOf($type));
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }