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

org.aksw.jena_sparql_api.shape.ResourceShapeParserJson Maven / Gradle / Ivy

There is a newer version: 3.17.0-1
Show newest version
package org.aksw.jena_sparql_api.shape;

import java.util.Map.Entry;

import org.aksw.gson.utils.JsonVisitor;
import org.aksw.gson.utils.JsonWalker;
import org.aksw.jena_sparql_api.concepts.Relation;
import org.aksw.jena_sparql_api.utils.Vars;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.shared.impl.PrefixMappingImpl;
import org.apache.jena.sparql.core.Prologue;
import org.apache.jena.sparql.expr.E_Equals;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprVar;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.syntax.ElementFilter;
import org.apache.jena.sparql.util.ExprUtils;


/**
 * shape: true
 *
 * shape: 'rdfs:label'
 *
 *
 * shape: ['rdf:type', 'rdfs:label']
 *
 * shape: {
 *   'rdf:type': true # Fetch rdf:type triples together with all outgoing triples of rdf:type
 * }
 *
 * shape: {
 *   'rdf:type': false # Fetch rdf:type triples, but no further reachable triples
 * }
 *
 * shape: {
 *   '-rdf:type': ... # Prefix with '-' to navigate in inverse direction (should replace '>' which we used so far)
 * }
 *
 * shape: {
 *   '~?p = rdf:type && langMatches(lang(?o), "en")' // Prefix with ~ to use a sparql expression
 * }
 *
 * Special attributes start with '$':
 * $filter: Set a concept for filtering the set of reached resources
 *
 * note:
 * ['rdf:type'] is equivalent to { 'rdf:type': false }
 *
 * shape: {
 *   'rdf:type': {
 *     $filter: '?s | ?s a owl:Class' // Only fetch types that are owl:Classes (i.e. exclude e.g. SKOS concepts),
 *     $predicates: ['rdfs:label']
 *   }
 * }
 *
 * Macro symbols:
 * shape: '{@literal @}spatial'
 *
 * At {@literal @}spatial will extended with its definition.
 *
 *
 * @author raven
 *
 */
public class ResourceShapeParserJson
    implements JsonVisitor
{
    protected ResourceShapeBuilder builder;

    public ResourceShapeBuilder getBuilder() {
        return builder;
    }

    public ResourceShapeParserJson() {
        this(new PrefixMappingImpl());
    }

    public ResourceShapeParserJson(PrefixMapping prefixMapping) {
        this(new ResourceShapeBuilder(prefixMapping));
    }

    public ResourceShapeParserJson(Prologue prologue) {
        this(new ResourceShapeBuilder(prologue));
    }

    public ResourceShapeParserJson(ResourceShapeBuilder builder) {
        this.builder = builder;
        //this.builder = new ResourceShapeBuilder(prefixMapping);
    }


    /**
     * String must be of format
     * [-] [~] str
     *
     * -: If present, assume inverse direction
     * ~: If present, str is assumed to be a SPARQL expression. Otherwise, a property URI is assumed
     *
     *
     * @param str
     * @return
     */
    public static StepRelation parseStep(String str, PrefixMapping prefixMapping) {
        str = str.trim();

        // Check the first character
        char c = str.charAt(0);
        boolean isInverse = c == '-';

        if(isInverse) {
            str = str.substring(1);
        }

        c = str.charAt(0);
        boolean isExpr = c == '~';

        if(isExpr) {
            str = str.substring(1);
        }

        Expr expr;
        if(isExpr) {
            expr = ExprUtils.parse(str, prefixMapping);
        } else {
            String p = prefixMapping.expandPrefix(str);
            Node np = NodeFactory.createURI(p);
            expr = new E_Equals(new ExprVar(Vars.p), NodeValue.makeNode(np));
        }

        Relation relation = new Relation(new ElementFilter(expr), Vars.p, Vars.o);

        StepRelation result = new StepRelation(relation, isInverse);
        return result;
    }

    public static ResourceShape parse(JsonElement json) {
        ResourceShapeParserJson parser = new ResourceShapeParserJson();
        JsonWalker.visit(json, parser);

        ResourceShape result = parser.getBuilder().getResourceShape();
        return result;
    }

    public static ResourceShape parse(JsonElement json, ResourceShapeBuilder builder) {
        ResourceShapeParserJson parser = new ResourceShapeParserJson(builder);

        JsonWalker.visit(json, parser);
        ResourceShape result = builder.getResourceShape();
        return result;
    }


    @Override
    public Void visit(JsonNull json) {
        return null;
    }


    @Override
    public Void visit(JsonObject json) {
        PrefixMapping pm = builder.getPrefixMapping();

        for(Entry entry : json.entrySet()) {
            String str = entry.getKey();
            JsonElement e = entry.getValue();
            StepRelation step = parseStep(str, pm);
            ResourceShapeBuilder subBilder = builder.nav(step);
            JsonWalker.visit(e, this);
            parse(e, subBilder);
        }

        return null;
    }


    @Override
    public Void visit(JsonArray json) {
        for(JsonElement item : json) {
            JsonWalker.walk(item, this);
        }
        return null;
    }


    @Override
    public Void visit(JsonPrimitive json) {
        PrefixMapping pm = builder.getPrefixMapping();

        if(json.isBoolean()) {
            Boolean tf = json.getAsBoolean();
            if(tf == true) {
                builder.nav(NodeValue.TRUE, true);
            }
        }
        else if (json.isString()) { // fetch a single property
            String str = json.getAsString();
            StepRelation step = parseStep(str, pm);

            builder.nav(step);
        }

        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy