public static function of($typeName, RelativeClassNameResolver $resolver = null)
    {
        $parts = explode("|", $typeName);
        if (count($parts) > 1)
        {
            $types = array();
            foreach ($parts as $part)
                $types[] = self::of($part, $resolver);
            return self::ofUnion($types);
        }
        
        $result = PrimitiveType::parse($typeName);

        if ($result == null)
        {
            if (substr($typeName, -2) === "[]")
            {
                $itemType = self::of(substr($typeName, 0, -2), $resolver);
                return self::ofArray($itemType);
            }

            if ($typeName === "array")
            {
                return self::ofArray(self::ofMixed());
            }

            $realTypeName = "";
            if (substr($typeName, 0, 1) === "\\")
            {
                $realTypeName = substr($typeName, 1);
            }
            else if ($resolver === null)
            {
                $realTypeName = $typeName;
            }
            else
            {
                $realTypeName = $resolver->resolveRelativeName($typeName);
            }

            $isInterface = interface_exists($realTypeName);

            if (!($isInterface || class_exists($realTypeName)))
                throw new ReflectionException("Type '" . $realTypeName . "' does not exist.");

            if ($isInterface)
                return InterfaceType::__internal_create($realTypeName);
            else
                return ClassType::__internal_create($realTypeName);
        }

        return $result;
    }