static function buildUrl($parts)
    {
        $parts = new ArrayObject($parts);

        ###################
        ### PARSE PARTS ###
        ###################

        // scheme
        $scheme = $parts->key('scheme', '', true);

        // host
        $host = $parts->key('host', '', true);

        // port
        $port = $parts->key('port', '', true);

        // path
        $path = $parts->key('path', '', true);

        // parse query string
        $query = '';
        if($parts->keyExists('query')) {
            if(self::isString($parts->key('query'))) {
                parse_str($parts->key('query'), $queryData);
            } else {
                $queryData = $parts->key('query');
            }

            if(self::isArray($queryData)) {
                $query = $queryData;
            }
        }


        ###################
        ### BUILD URL   ###
        ###################
        $url = '';

        // scheme
        if($scheme && $scheme != '') {
            $url .= $scheme . '://';
        }

        // host
        if($host && $host != '') {
            $url .= $host;
        }

        // port
        if($port != '') {
            $url .= ':' . $port;
        }

        // path
        if($path != '') {
            $url .= $path;
        }

        // query
        if(self::isArray($query)) {
            $query = http_build_query($query);
            if($query != "") {
                $url .= '?' . $query;
            }
        }

        try {
            return new UrlObject($url);
        } catch (\Exception $e) {
            throw new UrlObjectException($e->getMessage());
        }
    }