public function publicModifier()
 {
     $this->assertTrue(Modifiers::isPublic(MODIFIER_PUBLIC));
     $this->assertEquals('public', Modifiers::stringOf(MODIFIER_PUBLIC));
 }
 /**
  * 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));
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }