public static function expand($input, $options = null)
    {
        $options = self::mergeOptions($options);

        $processor = new Processor($options);
        $activectx = array('@base' => null);

        if (is_string($input)) {
            $remoteDocument = $options->documentLoader->loadDocument($input);

            $input = $remoteDocument->document;
            $activectx['@base'] = new IRI($remoteDocument->documentUrl);

            if (null !== $remoteDocument->contextUrl) {
                $processor->processContext($remoteDocument->contextUrl, $activectx);
            }
        }

        if ($options->base) {
            $activectx['@base'] = $options->base;
        }

        if (null !== $options->expandContext) {
            $processor->processContext($options->expandContext, $activectx);
        }

        $processor->expand($input, $activectx);

        // optimize away default graph (@graph as the only property at the top-level object)
        if (is_object($input) && property_exists($input, '@graph') && (1 === count(get_object_vars($input)))) {
            $input = $input->{'@graph'};
        }

        if (false === is_array($input)) {
            $input = (null === $input) ? array() : array($input);
        }

        return $input;
    }