private Context parse(Object localContext, List<String> remoteContexts,
            boolean parsingARemoteContext) throws JsonLdError {
        if (remoteContexts == null) {
            remoteContexts = new ArrayList<String>();
        }
        // 1. Initialize result to the result of cloning active context.
        Context result = this.clone(); // TODO: clone?
        // 2)
        if (!(localContext instanceof List)) {
            final Object temp = localContext;
            localContext = new ArrayList<Object>();
            ((List<Object>) localContext).add(temp);
        }
        // 3)
        for (final Object context : ((List<Object>) localContext)) {
            // 3.1)
            if (context == null) {
                result = new Context(this.options);
                continue;
            } else if (context instanceof Context) {
                result = ((Context) context).clone();
            }
            // 3.2)
            else if (context instanceof String) {
                String uri = (String) result.get(JsonLdConsts.BASE);
                uri = JsonLdUrl.resolve(uri, (String) context);
                // 3.2.2
                if (remoteContexts.contains(uri)) {
                    throw new JsonLdError(Error.RECURSIVE_CONTEXT_INCLUSION, uri);
                }
                remoteContexts.add(uri);

                // 3.2.3: Dereference context
                final RemoteDocument rd = this.options.getDocumentLoader().loadDocument(uri);
                final Object remoteContext = rd.getDocument();
                if (!(remoteContext instanceof Map) || !((Map<String, Object>) remoteContext)
                        .containsKey(JsonLdConsts.CONTEXT)) {
                    // If the dereferenced document has no top-level JSON object
                    // with an @context member
                    throw new JsonLdError(Error.INVALID_REMOTE_CONTEXT, context);
                }
                final Object tempContext = ((Map<String, Object>) remoteContext)
                        .get(JsonLdConsts.CONTEXT);

                // 3.2.4
                result = result.parse(tempContext, remoteContexts, true);
                // 3.2.5
                continue;
            } else if (!(context instanceof Map)) {
                // 3.3
                throw new JsonLdError(Error.INVALID_LOCAL_CONTEXT, context);
            }
            checkEmptyKey((Map<String, Object>) context);
            // 3.4
            if (!parsingARemoteContext
                    && ((Map<String, Object>) context).containsKey(JsonLdConsts.BASE)) {
                // 3.4.1
                final Object value = ((Map<String, Object>) context).get(JsonLdConsts.BASE);
                // 3.4.2
                if (value == null) {
                    result.remove(JsonLdConsts.BASE);
                } else if (value instanceof String) {
                    // 3.4.3
                    if (JsonLdUtils.isAbsoluteIri((String) value)) {
                        result.put(JsonLdConsts.BASE, value);
                    } else {
                        // 3.4.4
                        final String baseUri = (String) result.get(JsonLdConsts.BASE);
                        if (!JsonLdUtils.isAbsoluteIri(baseUri)) {
                            throw new JsonLdError(Error.INVALID_BASE_IRI, baseUri);
                        }
                        result.put(JsonLdConsts.BASE, JsonLdUrl.resolve(baseUri, (String) value));
                    }
                } else {
                    // 3.4.5
                    throw new JsonLdError(JsonLdError.Error.INVALID_BASE_IRI,
                            "@base must be a string");
                }
            }

            // 3.5
            if (((Map<String, Object>) context).containsKey(JsonLdConsts.VOCAB)) {
                final Object value = ((Map<String, Object>) context).get(JsonLdConsts.VOCAB);
                if (value == null) {
                    result.remove(JsonLdConsts.VOCAB);
                } else if (value instanceof String) {
                    if (JsonLdUtils.isAbsoluteIri((String) value)) {
                        result.put(JsonLdConsts.VOCAB, value);
                    } else {
                        throw new JsonLdError(Error.INVALID_VOCAB_MAPPING,
                                "@value must be an absolute IRI");
                    }
                } else {
                    throw new JsonLdError(Error.INVALID_VOCAB_MAPPING,
                            "@vocab must be a string or null");
                }
            }

            // 3.6
            if (((Map<String, Object>) context).containsKey(JsonLdConsts.LANGUAGE)) {
                final Object value = ((Map<String, Object>) context).get(JsonLdConsts.LANGUAGE);
                if (value == null) {
                    result.remove(JsonLdConsts.LANGUAGE);
                } else if (value instanceof String) {
                    result.put(JsonLdConsts.LANGUAGE, ((String) value).toLowerCase());
                } else {
                    throw new JsonLdError(Error.INVALID_DEFAULT_LANGUAGE, value);
                }
            }

            // 3.7
            final Map<String, Boolean> defined = new LinkedHashMap<String, Boolean>();
            for (final String key : ((Map<String, Object>) context).keySet()) {
                if (JsonLdConsts.BASE.equals(key) || JsonLdConsts.VOCAB.equals(key)
                        || JsonLdConsts.LANGUAGE.equals(key)) {
                    continue;
                }
                result.createTermDefinition((Map<String, Object>) context, key, defined);
            }
        }
        return result;
    }
private Context parse ( Object localContext , List < String > remoteContexts , boolean parsingARemoteContext ) throws JsonLdError { if ( remoteContexts == null ) { remoteContexts = new ArrayList < String > ( ) ; } Context result = this . clone ( ) ; if ( ! ( localContext instanceof List ) ) { final Object temp = localContext ; localContext = new ArrayList < Object > ( ) ; ( ( List < Object > ) localContext ) . add ( temp ) ; } for ( final Object context : ( ( List < Object > ) localContext ) ) { if ( context == null ) { result = new Context ( this . options ) ; continue ; } else if ( context instanceof Context ) { result = ( ( Context ) context ) . clone ( ) ; } else if ( context instanceof String ) { String uri = ( String ) result . get ( JsonLdConsts . BASE ) ; uri = JsonLdUrl . resolve ( uri , ( String ) context ) ; if ( remoteContexts . contains ( uri ) ) { throw new JsonLdError ( Error . RECURSIVE_CONTEXT_INCLUSION , uri ) ; } remoteContexts . add ( uri ) ; final RemoteDocument rd = this . options . getDocumentLoader ( ) . loadDocument ( uri ) ; final Object remoteContext = rd . getDocument ( ) ; if ( ! ( remoteContext instanceof Map ) || ! ( ( Map < String , Object > ) remoteContext ) . containsKey ( JsonLdConsts . CONTEXT ) ) { throw new JsonLdError ( Error . INVALID_REMOTE_CONTEXT , context ) ; } final Object tempContext = ( ( Map < String , Object > ) remoteContext ) . get ( JsonLdConsts . CONTEXT ) ; result = result . parse ( tempContext , remoteContexts , true ) ; continue ; } else if ( ! ( context instanceof Map ) ) { throw new JsonLdError ( Error . INVALID_LOCAL_CONTEXT , context ) ; } checkEmptyKey ( ( Map < String , Object > ) context ) ; if ( ! parsingARemoteContext && ( ( Map < String , Object > ) context ) . containsKey ( JsonLdConsts . BASE ) ) { final Object value = ( ( Map < String , Object > ) context ) . get ( JsonLdConsts . BASE ) ; if ( value == null ) { result . remove ( JsonLdConsts . BASE ) ; } else if ( value instanceof String ) { if ( JsonLdUtils . isAbsoluteIri ( ( String ) value ) ) { result . put ( JsonLdConsts . BASE , value ) ; } else { final String baseUri = ( String ) result . get ( JsonLdConsts . BASE ) ; if ( ! JsonLdUtils . isAbsoluteIri ( baseUri ) ) { throw new JsonLdError ( Error . INVALID_BASE_IRI , baseUri ) ; } result . put ( JsonLdConsts . BASE , JsonLdUrl . resolve ( baseUri , ( String ) value ) ) ; } } else { throw new JsonLdError ( JsonLdError . Error . INVALID_BASE_IRI , "@base must be a string" ) ; } } if ( ( ( Map < String , Object > ) context ) . containsKey ( JsonLdConsts . VOCAB ) ) { final Object value = ( ( Map < String , Object > ) context ) . get ( JsonLdConsts . VOCAB ) ; if ( value == null ) { result . remove ( JsonLdConsts . VOCAB ) ; } else if ( value instanceof String ) { if ( JsonLdUtils . isAbsoluteIri ( ( String ) value ) ) { result . put ( JsonLdConsts . VOCAB , value ) ; } else { throw new JsonLdError ( Error . INVALID_VOCAB_MAPPING , "@value must be an absolute IRI" ) ; } } else { throw new JsonLdError ( Error . INVALID_VOCAB_MAPPING , "@vocab must be a string or null" ) ; } } if ( ( ( Map < String , Object > ) context ) . containsKey ( JsonLdConsts . LANGUAGE ) ) { final Object value = ( ( Map < String , Object > ) context ) . get ( JsonLdConsts . LANGUAGE ) ; if ( value == null ) { result . remove ( JsonLdConsts . LANGUAGE ) ; } else if ( value instanceof String ) { result . put ( JsonLdConsts . LANGUAGE , ( ( String ) value ) . toLowerCase ( ) ) ; } else { throw new JsonLdError ( Error . INVALID_DEFAULT_LANGUAGE , value ) ; } } final Map < String , Boolean > defined = new LinkedHashMap < String , Boolean > ( ) ; for ( final String key : ( ( Map < String , Object > ) context ) . keySet ( ) ) { if ( JsonLdConsts . BASE . equals ( key ) || JsonLdConsts . VOCAB . equals ( key ) || JsonLdConsts . LANGUAGE . equals ( key ) ) { continue ; } result . createTermDefinition ( ( Map < String , Object > ) context , key , defined ) ; } } return result ; }
Helper method used to work around logic errors related to the recursive
nature of the JSONLD-API Context Processing Algorithm.

@param localContext
The Local Context object.
@param remoteContexts
The list of Strings denoting the remote Context URLs.
@param parsingARemoteContext
True if localContext represents a remote context that has been
parsed and sent into this method and false otherwise. This
must be set to know whether to propagate the @code{@base} key
from the context to the result.
@return The parsed and merged Context.
@throws JsonLdError
If there is an error parsing the contexts.