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

org.aksw.simba.lsq.model.LsqQuery Maven / Gradle / Ivy

package org.aksw.simba.lsq.model;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.aksw.commons.util.string.StringUtils;
import org.aksw.jenax.annotation.reprogen.HashId;
import org.aksw.jenax.annotation.reprogen.Iri;
import org.aksw.jenax.annotation.reprogen.ResourceView;
import org.aksw.jenax.annotation.reprogen.StringId;
import org.aksw.jenax.arq.util.syntax.QueryHash;
import org.aksw.jenax.model.geosparql.HasGeometry;
import org.aksw.jenax.reprogen.hashid.HashIdCxt;
import org.aksw.simba.lsq.vocab.LSQ;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.Resource;

import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;


/**
 * This class is main entry point for accessing information about a query in LSQ.
 *
 * A practical difference between an lsq:Query and a spin:Query is that the ID (a hashed value) of lsq:Query
 * is computed from the query string, whereas for spin:Query is is obtained via skolemization of the tree structure
 * of the SPIN representation.
 *
 * An LsqQuery is a *record* about a sparql query, encompassing the query string,
 * a spin representation, structural features, mentions in query logs
 * (unfortunately poorly called 'remote execution') and benchmarking information related to the query
 * itself (referred to as local execution) and its constituents.
 *
 *
 * TODO This model keeps the SPIN representation of a query separate from the LSQ record about it,
 * yet I am not totally sure whether actually these should be just two views of a resource which
 * represents a SPARQL query.
 *
 *
 * @author Claus Stadler, Jan 7, 2019
 *
 */
@ResourceView
public interface LsqQuery
    extends Resource, HasGeometry
{
    @HashId(excludeRdfProperty = true)
    @Iri(LSQ.Terms.text)
    String getText();
    LsqQuery setText(String text);

    @Iri(LSQ.Terms.parseError)
    String getParseError();
    LsqQuery setParseError(String text);

    // Note: org.topbraid.spin.model.Query has no registered implementation
    @Iri(LSQ.Terms.hasSpin)
    Resource getSpinQuery();
    LsqQuery setSpinQuery(Resource resource);

    @Iri(LSQ.Terms.hash)
    String getHash();
    LsqQuery setHash(String hash);

    // TODO We should investigate whether an extension of the model to shacl makes sense
    // The main question is which (sub-)set of all possible
    // sparql queries can be represented as shacl

    @Iri(LSQ.Terms.hasStructuralFeatures)
    LsqStructuralFeatures getStructuralFeatures();
    LsqQuery setStructuralFeatures(Resource r);

//    @Iri(LSQ.Strs.hasLocalExec)
//     Set getLocalExecutions(Class itemClazz);
    @Iri(LSQ.Terms.hasLocalExec)
    Set getLocalExecutions();

    // Set getLocalExecutions();

    //Set<>getLocalExecutions();

    // FIXME Dynamically typed collections don't properly work with @HashId yet
//    @Iri(LSQ.Strs.hasRemoteExec)
//     Set getRemoteExecutions(Class itemClazz);

    @Iri(LSQ.Terms.hasRemoteExec)
    Set getRemoteExecutions();

    @StringId
    default String getStringId(HashIdCxt cxt) {
        String prefix = StringUtils.toLowerCamelCase(LsqQuery.class.getSimpleName());
        String hash = getHash();
        if (hash == null) {
            hash = cxt.getHashAsString(this);
        }
        // Note: Dot '.' is not part of base64 encoding
        // This allows to use a hash as a path segment in an URL without introducing ambiguity
        return prefix + "-" + hash.replace('/', '.');
    }

    /**
     * Index of remote executions by the experiment config resource
     * @return
     */
    default Map getLocalExecutionMap() {
        Set res = getLocalExecutions(); //LocalExecution.class);
        Map result = res.stream()
                .collect(Collectors.toMap(r -> r.getBenchmarkRun(), r -> r));
        return result;
    }

//  default Map indexLocalExecs() {
//  Set les = getLocalExecutions(LocalExecution.class);
//
//  Map result = les.stream()
//          .collect(Collectors.toMap(le -> le.getBenchmarkRun(), le -> le));
//
//  return result;
//}


    public static String createHashOld(String str) {
//        System.out.println("Hashing " + str.replace('\n', ' '));

        // FIXME The hash computation of the jsa-mapper includes the properties and use the RDF term serialization - so the hashes do not align
        // The solution would have to exclude the property from id generation and use java string representations of the RDF terms
        // such as @HashId(excludeProperty=true, toJavaString=true)

        // Node tmp = NodeFmtLib.str(NodeFactory.createLiteral(str));
        String tmp = str;
        HashCode hashCode = str == null ? null : Hashing.sha256().hashString(tmp, StandardCharsets.UTF_8);
        String result = hashCode == null ? null : BaseEncoding.base64Url().omitPadding().encode(hashCode.asBytes());

        return result;
    }

    public static String createHash(String str) {
        String result;
        try {
            Query query = QueryFactory.create(str, Syntax.syntaxARQ);
            result = QueryHash.createHash(query).toString();
        } catch (Exception e) {
            result = createHashOld(str);
        }
        return result;
      }

    default LsqQuery setQueryAndHash(String str) {
        String hash = createHash(str);

        setText(str);
        setHash(hash);

        return this;
    }

    default LsqQuery updateHash() {
        String str = getText();
        String hash = createHash(str);
        setHash(hash);
        return this;
    }

    default LsqQuery setQueryAndHash(Query query) {
        String str = query.toString();
        setQueryAndHash(str);

        return this;
    }
//    @ToString
//    default String asString() {
//        return toString() + " " + getText();
//    }
    // Set getRemoteExecutions();
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy