/**
  * Fetch a qname for a class.
  *
  * @param   lang.XPClass class
  * @return  var xml.QName or NULL if no mapping exists
  */
 public function qnameFor(XPClass $class)
 {
     if (!isset($this->_c2q[$class->getName()])) {
         return NULL;
     }
     return $this->_qnames[$this->_c2q[$class->getName()]];
 }
Ejemplo n.º 2
0
 /**
  * Creates a new array type instance
  *
  * @param  lang.XPClass $base
  * @param  lang.Type[] $components
  */
 public function __construct(XPClass $base, array $components)
 {
     $this->base = $base;
     $this->components = $components;
     parent::__construct(sprintf('%s<%s>', $base->getName(), implode(',', array_map(function ($e) {
         return $e->getName();
     }, $components))), null);
 }
 /**
  * Tries to get class uri via reflection
  *
  * @param lang.XPClass class The class to return the URI for
  * @return string
  */
 private function uriFor(XPClass $class)
 {
     try {
         $Urimethod = $class->getClassLoader()->getClass()->getMethod('classURI');
         $Urimethod->setAccessible(TRUE);
         return $Urimethod->invoke($class->getClassLoader(), $class->getName());
     } catch (Exception $ignored) {
         return $class->getClassName();
     }
 }
Ejemplo n.º 4
0
 /**
  * Returns the enumeration member uniquely identified by its name
  *
  * @param   lang.XPClass class class object
  * @param   string name enumeration member
  * @return  lang.Enum
  * @throws  lang.IllegalArgumentException in case the enum member does not exist or when the given class is not an enum
  */
 public static function valueOf(XPClass $class, $name)
 {
     if (!$class->isEnum()) {
         throw new IllegalArgumentException('Argument class must be lang.XPClass<? extends lang.Enum>');
     }
     try {
         $prop = $class->reflect()->getStaticPropertyValue($name);
         if ($class->isInstance($prop)) {
             return $prop;
         }
     } catch (\ReflectionException $e) {
         throw new IllegalArgumentException($e->getMessage());
     }
     throw new IllegalArgumentException('No such member "' . $name . '" in ' . $class->getName());
 }
Ejemplo n.º 5
0
 /**
  * Show usage
  *
  * @param   lang.XPClass class
  */
 public static function showUsage(XPClass $class)
 {
     // Description
     if (NULL !== ($comment = $class->getComment())) {
         self::$err->writeLine(self::textOf($comment));
         self::$err->writeLine(str_repeat('=', 72));
     }
     $extra = $details = $positional = array();
     foreach ($class->getMethods() as $method) {
         if (!$method->hasAnnotation('arg')) {
             continue;
         }
         $arg = $method->getAnnotation('arg');
         $name = strtolower(preg_replace('/^set/', '', $method->getName()));
         $comment = self::textOf($method->getComment());
         if (0 == $method->numParameters()) {
             $optional = TRUE;
         } else {
             list($first, ) = $method->getParameters();
             $optional = $first->isOptional();
         }
         if (isset($arg['position'])) {
             $details['#' . ($arg['position'] + 1)] = $comment;
             $positional[$arg['position']] = $name;
         } else {
             if (isset($arg['name'])) {
                 $details['--' . $arg['name'] . ' | -' . (isset($arg['short']) ? $arg['short'] : $arg['name'][0])] = $comment;
                 $extra[$arg['name']] = $optional;
             } else {
                 $details['--' . $name . ' | -' . (isset($arg['short']) ? $arg['short'] : $name[0])] = $comment;
                 $extra[$name] = $optional;
             }
         }
     }
     // Usage
     asort($positional);
     self::$err->write('Usage: $ xpcli ', $class->getName(), ' ');
     foreach ($positional as $name) {
         self::$err->write('<', $name, '> ');
     }
     foreach ($extra as $name => $optional) {
         self::$err->write($optional ? '[' : '', '--', $name, $optional ? '] ' : ' ');
     }
     self::$err->writeLine();
     // Argument details
     self::$err->writeLine('Arguments:');
     foreach ($details as $which => $comment) {
         self::$err->writeLine('* ', $which, "\n  ", str_replace("\n", "\n  ", $comment), "\n");
     }
 }
Ejemplo n.º 6
0
 /**
  * Gets class name (and generic components if this class is a 
  * generic definition)
  *
  * @param   lang.XPClass class
  * @return  string
  */
 protected static function displayNameOf(XPClass $class)
 {
     return $class->getName() . ($class->isGenericDefinition() ? '<' . implode(', ', $class->genericComponents()) . '>' : '');
 }
Ejemplo n.º 7
0
 /**
  * Returns the enumeration members for a given class
  *
  * @param  lang.XPClass class class object
  * @return self[]
  * @throws lang.IllegalArgumentException in case the given class is not an enum
  */
 public static function valuesOf(XPClass $class)
 {
     if (!$class->isEnum()) {
         throw new IllegalArgumentException('Argument class must be lang.XPClass<? extends lang.Enum>');
     }
     $r = [];
     if ($class->isSubclassOf(self::class)) {
         foreach ($class->reflect()->getStaticProperties() as $prop) {
             $class->isInstance($prop) && ($r[] = $prop);
         }
     } else {
         $t = ClassLoader::defineClass($class->getName() . 'Enum', self::class, []);
         foreach ($class->reflect()->getMethod('getValues')->invoke(null) as $name => $ordinal) {
             $r[] = $t->newInstance($ordinal, $name);
         }
     }
     return $r;
 }
Ejemplo n.º 8
0
 /**
  * Creates a generic type
  *
  * @param   lang.XPClass self
  * @param   lang.Type[] arguments
  * @return  string created type's literal name
  */
 public static function createGenericType(XPClass $self, array $arguments)
 {
     // Verify
     $annotations = $self->getAnnotations();
     if (!isset($annotations['generic']['self'])) {
         throw new IllegalStateException('Class ' . $self->name . ' is not a generic definition');
     }
     $components = array();
     foreach (explode(',', $annotations['generic']['self']) as $cs => $name) {
         $components[] = ltrim($name);
     }
     $cs++;
     if ($cs !== sizeof($arguments)) {
         throw new IllegalArgumentException(sprintf('Class %s expects %d component(s) <%s>, %d argument(s) given', $self->name, $cs, implode(', ', $components), sizeof($arguments)));
     }
     // Compose names
     $cn = $qc = '';
     foreach ($arguments as $typearg) {
         $cn .= '¸' . strtr($typearg->literal(), '\\', '¦');
         $qc .= ',' . $typearg->getName();
     }
     $name = $self->literal() . '··' . substr($cn, 1);
     $qname = $self->name . '<' . substr($qc, 1) . '>';
     // Create class if it doesn't exist yet
     if (!class_exists($name, FALSE) && !interface_exists($name, FALSE)) {
         $meta = xp::$meta[$self->name];
         // Parse placeholders into a lookup map
         $placeholders = array();
         foreach ($components as $i => $component) {
             $placeholders[$component] = $arguments[$i]->getName();
         }
         // Work on sourcecode
         $cl = self::_classLoaderFor($self->name);
         if (!$cl || !($bytes = $cl->loadClassBytes($self->name))) {
             throw new IllegalStateException($self->name);
         }
         // Namespaced class
         if (FALSE !== ($ns = strrpos($name, '\\'))) {
             $decl = substr($name, $ns + 1);
             $namespace = substr($name, 0, $ns);
             $src = 'namespace ' . $namespace . ';';
         } else {
             $decl = $name;
             $namespace = NULL;
             $src = '';
         }
         // Replace source
         $annotation = NULL;
         $matches = array();
         $state = array(0);
         $counter = 0;
         $tokens = token_get_all($bytes);
         for ($i = 0, $s = sizeof($tokens); $i < $s; $i++) {
             if (T_COMMENT === $tokens[$i][0]) {
                 continue;
             } else {
                 if (0 === $state[0]) {
                     if (T_ABSTRACT === $tokens[$i][0] || T_FINAL === $tokens[$i][0]) {
                         $src .= $tokens[$i][1] . ' ';
                     } else {
                         if (T_CLASS === $tokens[$i][0] || T_INTERFACE === $tokens[$i][0]) {
                             $meta['class'][DETAIL_GENERIC] = array($self->name, $arguments);
                             $src .= $tokens[$i][1] . ' ' . $decl;
                             array_unshift($state, $tokens[$i][0]);
                         }
                     }
                     continue;
                 } else {
                     if (T_CLASS === $state[0]) {
                         if (T_EXTENDS === $tokens[$i][0]) {
                             $i += 2;
                             $parent = '';
                             while ((T_STRING === $tokens[$i][0] || T_NS_SEPARATOR === $tokens[$i][0]) && $i < $s) {
                                 $parent .= $tokens[$i][1];
                                 $i++;
                             }
                             $i--;
                             '\\' === $parent[0] || ($parent = $namespace . '\\' . $parent);
                             if (isset($annotations['generic']['parent'])) {
                                 $xargs = array();
                                 foreach (explode(',', $annotations['generic']['parent']) as $j => $placeholder) {
                                     $xargs[] = Type::forName(strtr(ltrim($placeholder), $placeholders));
                                 }
                                 $src .= ' extends \\' . self::createGenericType($self->getParentClass(), $xargs);
                             } else {
                                 $src .= ' extends ' . $parent;
                             }
                         } else {
                             if (T_IMPLEMENTS === $tokens[$i][0]) {
                                 $src .= ' implements';
                                 $counter = 0;
                                 $annotation = @$annotations['generic']['implements'];
                                 array_unshift($state, 5);
                             } else {
                                 if ('{' === $tokens[$i][0]) {
                                     array_shift($state);
                                     array_unshift($state, 1);
                                     $src .= ' {';
                                 }
                             }
                         }
                         continue;
                     } else {
                         if (T_INTERFACE === $state[0]) {
                             if (T_EXTENDS === $tokens[$i][0]) {
                                 $src .= ' extends';
                                 $counter = 0;
                                 $annotation = @$annotations['generic']['extends'];
                                 array_unshift($state, 5);
                             } else {
                                 if ('{' === $tokens[$i][0]) {
                                     array_shift($state);
                                     array_unshift($state, 1);
                                     $src .= ' {';
                                 }
                             }
                             continue;
                         } else {
                             if (1 === $state[0]) {
                                 // Class body
                                 if (T_FUNCTION === $tokens[$i][0]) {
                                     $braces = 0;
                                     $parameters = $default = array();
                                     array_unshift($state, 3);
                                     array_unshift($state, 2);
                                     $m = $tokens[$i + 2][1];
                                     $p = 0;
                                     $annotations = array($meta[1][$m][DETAIL_ANNOTATIONS], $meta[1][$m][DETAIL_TARGET_ANNO]);
                                 } else {
                                     if ('}' === $tokens[$i][0]) {
                                         $src .= '}';
                                         break;
                                     } else {
                                         if (T_CLOSE_TAG === $tokens[$i][0]) {
                                             break;
                                         }
                                     }
                                 }
                             } else {
                                 if (2 === $state[0]) {
                                     // Method declaration
                                     if ('(' === $tokens[$i][0]) {
                                         $braces++;
                                     } else {
                                         if (')' === $tokens[$i][0]) {
                                             $braces--;
                                             if (0 === $braces) {
                                                 array_shift($state);
                                                 $src .= ')';
                                                 continue;
                                             }
                                         }
                                     }
                                     if (T_VARIABLE === $tokens[$i][0]) {
                                         $parameters[] = $tokens[$i][1];
                                     } else {
                                         if ('=' === $tokens[$i][0]) {
                                             $p = sizeof($parameters) - 1;
                                             $default[$p] = '';
                                         } else {
                                             if (T_WHITESPACE !== $tokens[$i][0] && isset($default[$p])) {
                                                 $default[$p] .= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i];
                                             }
                                         }
                                     }
                                 } else {
                                     if (3 === $state[0]) {
                                         // Method body
                                         if (';' === $tokens[$i][0]) {
                                             // Abstract method
                                             if (isset($annotations[0]['generic']['return'])) {
                                                 $meta[1][$m][DETAIL_RETURNS] = strtr($annotations[0]['generic']['return'], $placeholders);
                                             }
                                             if (isset($annotations[0]['generic']['params'])) {
                                                 foreach (explode(',', $annotations[0]['generic']['params']) as $j => $placeholder) {
                                                     if ('' !== ($replaced = strtr(ltrim($placeholder), $placeholders))) {
                                                         $meta[1][$m][DETAIL_ARGUMENTS][$j] = $replaced;
                                                     }
                                                 }
                                             }
                                             $annotations = array();
                                             unset($meta[1][$m][DETAIL_ANNOTATIONS]['generic']);
                                             array_shift($state);
                                         } else {
                                             if ('{' === $tokens[$i][0]) {
                                                 $braces = 1;
                                                 array_shift($state);
                                                 array_unshift($state, 4);
                                                 $src .= '{';
                                                 if (isset($annotations[0]['generic']['return'])) {
                                                     $meta[1][$m][DETAIL_RETURNS] = strtr($annotations[0]['generic']['return'], $placeholders);
                                                 }
                                                 if (isset($annotations[0]['generic']['params'])) {
                                                     $generic = array();
                                                     foreach (explode(',', $annotations[0]['generic']['params']) as $j => $placeholder) {
                                                         if ('' === ($replaced = strtr(ltrim($placeholder), $placeholders))) {
                                                             $generic[$j] = NULL;
                                                         } else {
                                                             $meta[1][$m][DETAIL_ARGUMENTS][$j] = $replaced;
                                                             $generic[$j] = $replaced;
                                                         }
                                                     }
                                                     foreach ($generic as $j => $type) {
                                                         if (NULL === $type) {
                                                             continue;
                                                         } else {
                                                             if ('...' === substr($type, -3)) {
                                                                 $src .= $j ? '$·args= array_slice(func_get_args(), ' . $j . ');' : '$·args= func_get_args();';
                                                                 $src .= ' if (!is(\'' . substr($generic[$j], 0, -3) . '[]\', $·args)) throw new \\lang\\IllegalArgumentException(' . '"Vararg ' . ($j + 1) . ' passed to ".__METHOD__."' . ' must be of ' . $type . ', ".\\xp::stringOf($·args)." given"' . ');';
                                                             } else {
                                                                 $src .= ' if (' . (isset($default[$j]) ? '(' . $default[$j] . ' !== ' . $parameters[$j] . ') && ' : '') . '!is(\'' . $generic[$j] . '\', ' . $parameters[$j] . ')) throw new \\lang\\IllegalArgumentException(' . '"Argument ' . ($j + 1) . ' passed to ".__METHOD__."' . ' must be of ' . $type . ', ".\\xp::typeOf(' . $parameters[$j] . ')." given"' . ');';
                                                             }
                                                         }
                                                     }
                                                 }
                                                 $annotations = array();
                                                 unset($meta[1][$m][DETAIL_ANNOTATIONS]['generic']);
                                                 continue;
                                             }
                                         }
                                     } else {
                                         if (4 === $state[0]) {
                                             // Method body
                                             if ('{' === $tokens[$i][0]) {
                                                 $braces++;
                                             } else {
                                                 if ('}' === $tokens[$i][0]) {
                                                     $braces--;
                                                     if (0 === $braces) {
                                                         array_shift($state);
                                                     }
                                                 }
                                             }
                                         } else {
                                             if (5 === $state[0]) {
                                                 // Implements (class), Extends (interface)
                                                 if (T_STRING === $tokens[$i][0]) {
                                                     $rel = '';
                                                     while ((T_STRING === $tokens[$i][0] || T_NS_SEPARATOR === $tokens[$i][0]) && $i < $s) {
                                                         $rel .= $tokens[$i][1];
                                                         $i++;
                                                     }
                                                     $i--;
                                                     '\\' === $rel[0] || ($rel = $namespace . '\\' . $rel);
                                                     if (isset($annotation[$counter])) {
                                                         $iargs = array();
                                                         foreach (explode(',', $annotation[$counter]) as $j => $placeholder) {
                                                             $iargs[] = Type::forName(strtr(ltrim($placeholder), $placeholders));
                                                         }
                                                         $src .= '\\' . self::createGenericType(new XPClass(new ReflectionClass($rel)), $iargs);
                                                     } else {
                                                         $src .= $rel;
                                                     }
                                                     $counter++;
                                                     continue;
                                                 } else {
                                                     if ('{' === $tokens[$i][0]) {
                                                         array_shift($state);
                                                         array_unshift($state, 1);
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             $src .= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i];
         }
         // Create class
         // DEBUG fputs(STDERR, "@* ".substr($src, 0, strpos($src, '{'))." -> $qname\n");
         eval($src);
         method_exists($name, '__static') && call_user_func(array($name, '__static'));
         unset($meta['class'][DETAIL_ANNOTATIONS]['generic']);
         xp::$meta[$qname] = $meta;
         xp::$cn[$name] = $qname;
         // Create alias if no PHP namespace is present and a qualified name exists
         if (!$ns && strstr($qname, '.')) {
             class_alias($name, strtr($self->getName(), '.', '\\') . '··' . substr($cn, 1));
         }
     }
     return $name;
 }
 /**
  * Registers a class map
  *
  * @param   xml.QName object
  * @param   lang.XPClass class
  */
 public function registerMapping(QName $qname, XPClass $class)
 {
     $this->map[$qname->localpart] = xp::reflect($class->getName());
 }