All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.apicatalog.cborld.context.ObjectExpansion Maven / Gradle / Ivy

/*
 * Copyright 2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.apicatalog.cborld.context;

import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import com.apicatalog.cborld.db.TypeKeyNameMapper;
import com.apicatalog.cursor.MapCursor;
import com.apicatalog.cursor.MapEntryCursor;
import com.apicatalog.cursor.jakarta.JakartaValueCursor;
import com.apicatalog.jsonld.JsonLdError;
import com.apicatalog.jsonld.context.ActiveContext;
import com.apicatalog.jsonld.context.TermDefinition;
import com.apicatalog.jsonld.json.JsonUtils;
import com.apicatalog.jsonld.lang.Keywords;
import com.apicatalog.jsonld.lang.Utils;

import jakarta.json.JsonString;
import jakarta.json.JsonValue;

final class ObjectExpansion {

    // mandatory
    private ActiveContext activeContext;
    private JsonValue propertyContext;
    private MapCursor element;
    private String activeProperty;
    private URI baseUrl;
    
    private Consumer> appliedContexts;
    private TypeKeyNameMapper typeMapper;

    // optional
    private boolean ordered;
    private boolean fromMap;

    private ObjectExpansion(final ActiveContext activeContext, final JsonValue propertyContext, final MapCursor element,
            final String activeProperty, final URI baseUrl, Consumer> appliedContexts,TypeKeyNameMapper typeMapper) {
        this.activeContext = activeContext;
        this.propertyContext = propertyContext;
        this.element = element;
        this.activeProperty = activeProperty;
        this.baseUrl = baseUrl;
        
        this.appliedContexts = appliedContexts;
        this.typeMapper = typeMapper;

        // default values
        this.ordered = false;
        this.fromMap = false;
    }

    public static final ObjectExpansion with(final ActiveContext activeContext, final JsonValue propertyContext,
            final MapCursor element, final String activeProperty, final URI baseUrl, Consumer> appliedContexts,  TypeKeyNameMapper typeMapper) {
        return new ObjectExpansion(activeContext, propertyContext, element, activeProperty, baseUrl, appliedContexts, typeMapper);
    }

    public ObjectExpansion ordered(boolean value) {
        this.ordered = value;
        return this;
    }

    public ObjectExpansion fromMap(boolean value) {
        this.fromMap = value;
        return this;
    }

    public JsonValue expand() throws JsonLdError {

        if (activeProperty != null && typeMapper != null)  {
            typeMapper.beginMap(activeProperty);
        }
        
        initPreviousContext();

        initPropertyContext();

        initLocalContext();

        // 10.
        final ActiveContext typeContext = activeContext;

        processTypeScoped(typeContext);

        final JsonMapBuilder result = JsonMapBuilder.create();

        ObjectExpansion1314
                    .with(activeContext, element, activeProperty, baseUrl, appliedContexts, typeMapper)
                    .result(result)
                    .ordered(ordered)
                    .expand();

        if (activeProperty != null && typeMapper != null)  {
            typeMapper.end();
        }

        return result.build();
    }

    private void initPropertyContext() throws JsonLdError {
        // 8.
        if (propertyContext != null) {
            activeContext = activeContext
                                .newContext()
                                .overrideProtected(true)
                                .create(
                                    propertyContext,
                                    activeContext
                                            .getTerm(activeProperty)
                                            .map(TermDefinition::getBaseUrl)
                                            .orElse(null)
                                        );
        }
    }

    private void initPreviousContext() throws JsonLdError {

        // 7. If active context has a previous context, the active context is not
        // propagated.
        // If from map is undefined or false, and element does not contain an entry
        // expanding to @value,
        // and element does not consist of a single entry expanding to @id (where
        // entries are IRI expanded),
        // set active context to previous context from active context,
        // as the scope of a term-scoped context does not apply when processing new node
        // objects.
        if (activeContext.getPreviousContext() != null && !fromMap) {

            boolean revert = true;

            for (final String key : Utils.index(element.keys(), true)) {

                final String expandedKey = UriExpansion
                                                .with(activeContext, appliedContexts)
                                                .vocab(true)
                                                .expand(key);

                if (Keywords.VALUE.equals(expandedKey) || (Keywords.ID.equals(expandedKey) && (element.size() == 1))) {
                    revert = false;
                    break;
                }
            }

            if (revert) {
                activeContext = activeContext.getPreviousContext();
            }
        }
    }

    private void initLocalContext() throws JsonLdError {

        // 9.
        if (element.contains(Keywords.CONTEXT)) {
            
            final JsonValue jsonContext = JakartaValueCursor.toJson(element.entry(Keywords.CONTEXT));
            element.parent();

            for (final JsonValue context : JsonUtils.toJsonArray(jsonContext)) {

                final ActiveContext ac = new ActiveContext(activeContext.getBaseUri(), activeContext.getBaseUrl(), activeContext.getOptions())
                                        .newContext()
                                        .create(context, baseUrl);
                appliedContexts.accept(ac.getTerms());
            }

            activeContext = activeContext
                    .newContext()
                    .create(jsonContext, baseUrl);
        }
    }

    private String processTypeScoped(final ActiveContext typeContext) throws JsonLdError {

        if (element.isEmpty()) {
            return null;
        }

        String typeKey = null;

        final Collection keys = element.keys();
                
        final MapEntryCursor entry = element.entry();

        for (final String key : Utils.index(keys, true)) {

            final String expandedKey = UriExpansion
                                            .with(activeContext, appliedContexts)
                                            .vocab(true)
                                            .expand(key);

            if (!Keywords.TYPE.equals(expandedKey)) {
                continue;

            } else if (typeKey == null) {
                typeKey = key;
            }

            if (typeMapper != null) {
                typeMapper.typeKeyName(key);
            }
            
            final JsonValue entryValue = JakartaValueCursor.toJson(entry.mapKey(key));
            
            // 11.2
            final List terms = JsonUtils.toStream(entryValue)
                                            .filter(JsonUtils::isString)
                                            .map(JsonString.class::cast)
                                            .map(JsonString::getString)
                                            .sorted()
                                            .collect(Collectors.toList());
//            entry.save();
//            final List terms = ValueCursor
//                                            .toStream(entry.mapKey(key))
//                                            .filter(ValueCursor::isString)
//                                            .map(ValueCursor::stringValue)
//                                            .sorted()
//                                            .collect(Collectors.toList());

//            entry.restore();
           
            for (final String term : terms) {

                Optional localContext = typeContext.getTerm(term).map(TermDefinition::getLocalContext);

                if (localContext.isPresent()) {
                    
                    final JsonValue lc = localContext.get();
                    
                    if (JsonUtils.isObject(lc)) {
                        appliedContexts.accept(lc.asJsonObject().keySet());
                    }

                    Optional valueDefinition = activeContext.getTerm(term);

                    activeContext =
                            activeContext
                                .newContext()
                                .propagate(false)
                                .create(lc,
                                        valueDefinition
                                                .map(TermDefinition::getBaseUrl)
                                                .orElse(null)
                                        );
                }
            }
        }
        
        element.parent();

        return typeKey;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy