com.marklogic.semantics.sesame.client.MarkLogicClientImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.marklogic.semantics.sesame.client.MarkLogicClientImpl.java

Source

/*
 * Copyright 2015-2016 MarkLogic Corporation
 *
 * 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.
 */
/**
 * A library that enables access to a MarkLogic-backed triple-store via the
 * Sesame API.
 */
package com.marklogic.semantics.sesame.client;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.query.Binding;
import org.openrdf.repository.sparql.query.SPARQLQueryBindingSet;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.marklogic.client.DatabaseClient;
import com.marklogic.client.DatabaseClientFactory;
import com.marklogic.client.FailedRequestException;
import com.marklogic.client.Transaction;
import com.marklogic.client.impl.SPARQLBindingsImpl;
import com.marklogic.client.io.FileHandle;
import com.marklogic.client.io.InputStreamHandle;
import com.marklogic.client.query.QueryDefinition;
import com.marklogic.client.semantics.GraphManager;
import com.marklogic.client.semantics.GraphPermissions;
import com.marklogic.client.semantics.RDFTypes;
import com.marklogic.client.semantics.SPARQLBindings;
import com.marklogic.client.semantics.SPARQLQueryDefinition;
import com.marklogic.client.semantics.SPARQLQueryManager;
import com.marklogic.client.semantics.SPARQLRuleset;
import com.marklogic.semantics.sesame.MarkLogicSesameException;

/**
 * internal class for interacting with java api client
 *
 * @author James Fuller
 */
class MarkLogicClientImpl {

    private static final Logger logger = LoggerFactory.getLogger(MarkLogicClientImpl.class);

    private static final String DEFAULT_GRAPH_URI = "http://marklogic.com/semantics#default-graph";

    private SPARQLRuleset[] ruleset;
    private QueryDefinition constrainingQueryDef;
    private GraphPermissions graphPerms;

    private SPARQLQueryManager sparqlManager;
    private GraphManager graphManager;

    private DatabaseClient databaseClient;

    /**
     * constructor
     *
     * @param host
     * @param port
     * @param user
     * @param password
     * @param auth
     */
    public MarkLogicClientImpl(String host, int port, String user, String password, String auth) {
        setDatabaseClient(DatabaseClientFactory.newClient(host, port, user, password,
                DatabaseClientFactory.Authentication.valueOf(auth)));
    }

    /**
     *  set databaseclient
     *
     * @param databaseClient
     */
    public MarkLogicClientImpl(DatabaseClient databaseClient) {
        setDatabaseClient(databaseClient);
    }

    /**
     * set databaseclient and instantate related managers
     *
     * @param databaseClient
     */
    private void setDatabaseClient(DatabaseClient databaseClient) {
        this.databaseClient = databaseClient;
        this.sparqlManager = getDatabaseClient().newSPARQLQueryManager();
        this.graphManager = getDatabaseClient().newGraphManager();
    }

    /**
     * gets database client
     *
     * @return DatabaseClient
     */
    public DatabaseClient getDatabaseClient() {
        return this.databaseClient;
    }

    /**
     * executes SPARQLQuery
     *
     * @param queryString
     * @param bindings
     * @param start
     * @param pageLength
     * @param tx
     * @param includeInferred
     * @param baseURI
     * @return
     * @throws JsonProcessingException
     */
    public InputStream performSPARQLQuery(String queryString, SPARQLQueryBindingSet bindings, long start,
            long pageLength, Transaction tx, boolean includeInferred, String baseURI)
            throws JsonProcessingException {
        return performSPARQLQuery(queryString, bindings, new InputStreamHandle(), start, pageLength, tx,
                includeInferred, baseURI);
    }

    /**
     * executes SPARQLQuery
     *
     * @param queryString
     * @param bindings
     * @param handle
     * @param start
     * @param pageLength
     * @param tx
     * @param includeInferred
     * @param baseURI
     * @return
     * @throws JsonProcessingException
     */
    public InputStream performSPARQLQuery(String queryString, SPARQLQueryBindingSet bindings,
            InputStreamHandle handle, long start, long pageLength, Transaction tx, boolean includeInferred,
            String baseURI) throws JsonProcessingException {
        SPARQLQueryDefinition qdef = sparqlManager.newQueryDefinition(queryString);
        if (notNull(baseURI) && !baseURI.isEmpty()) {
            qdef.setBaseUri(baseURI);
        }
        if (notNull(ruleset)) {
            qdef.setRulesets(ruleset);
        }
        if (notNull(getConstrainingQueryDefinition())) {
            qdef.setConstrainingQueryDefinition(getConstrainingQueryDefinition());
            qdef.setDirectory(getConstrainingQueryDefinition().getDirectory());
            qdef.setCollections(getConstrainingQueryDefinition().getCollections());
            qdef.setResponseTransform(getConstrainingQueryDefinition().getResponseTransform());
            qdef.setOptionsName(getConstrainingQueryDefinition().getOptionsName());
        }
        qdef.setIncludeDefaultRulesets(includeInferred);
        if (notNull(graphPerms)) {
            qdef.setUpdatePermissions(graphPerms);
        }
        if (pageLength > 0) {
            sparqlManager.setPageLength(pageLength);
        } else {
            sparqlManager.clearPageLength();
        }
        sparqlManager.executeSelect(qdef, handle, start, tx);
        return new BufferedInputStream(handle.get());
    }

    /**
     * executes GraphQuery
     * @param queryString
     * @param bindings
     * @param tx
     * @param includeInferred
     * @param baseURI
     * @return
     * @throws JsonProcessingException
     */
    public InputStream performGraphQuery(String queryString, SPARQLQueryBindingSet bindings, Transaction tx,
            boolean includeInferred, String baseURI) throws JsonProcessingException {
        return performGraphQuery(queryString, bindings, new InputStreamHandle(), tx, includeInferred, baseURI);
    }

    /**
     * executes GraphQuery
     *
     * @param queryString
     * @param bindings
     * @param handle
     * @param tx
     * @param includeInferred
     * @param baseURI
     * @return
     * @throws JsonProcessingException
     */
    public InputStream performGraphQuery(String queryString, SPARQLQueryBindingSet bindings,
            InputStreamHandle handle, Transaction tx, boolean includeInferred, String baseURI)
            throws JsonProcessingException {
        SPARQLQueryDefinition qdef = sparqlManager.newQueryDefinition(queryString);
        if (notNull(baseURI) && !baseURI.isEmpty()) {
            qdef.setBaseUri(baseURI);
        }
        if (notNull(ruleset)) {
            qdef.setRulesets(ruleset);
        }
        if (notNull(getConstrainingQueryDefinition())) {
            qdef.setConstrainingQueryDefinition(getConstrainingQueryDefinition());
            qdef.setDirectory(getConstrainingQueryDefinition().getDirectory());
            qdef.setCollections(getConstrainingQueryDefinition().getCollections());
            qdef.setResponseTransform(getConstrainingQueryDefinition().getResponseTransform());
            qdef.setOptionsName(getConstrainingQueryDefinition().getOptionsName());
        }
        if (notNull(graphPerms)) {
            qdef.setUpdatePermissions(graphPerms);
        }
        qdef.setIncludeDefaultRulesets(includeInferred);
        sparqlManager.executeDescribe(qdef, handle, tx);
        return new BufferedInputStream(handle.get());
    }

    /**
     * executes BooleanQuery
     *
     * @param queryString
     * @param bindings
     * @param tx
     * @param includeInferred
     * @param baseURI
     * @return
     */
    public boolean performBooleanQuery(String queryString, SPARQLQueryBindingSet bindings, Transaction tx,
            boolean includeInferred, String baseURI) {
        SPARQLQueryDefinition qdef = sparqlManager.newQueryDefinition(queryString);
        if (notNull(baseURI) && !baseURI.isEmpty()) {
            qdef.setBaseUri(baseURI);
        }
        qdef.setIncludeDefaultRulesets(includeInferred);
        if (notNull(ruleset)) {
            qdef.setRulesets(ruleset);
        }
        if (notNull(getConstrainingQueryDefinition())) {
            qdef.setConstrainingQueryDefinition(getConstrainingQueryDefinition());
            qdef.setDirectory(getConstrainingQueryDefinition().getDirectory());
            qdef.setCollections(getConstrainingQueryDefinition().getCollections());
            qdef.setResponseTransform(getConstrainingQueryDefinition().getResponseTransform());
            qdef.setOptionsName(getConstrainingQueryDefinition().getOptionsName());
        }
        if (notNull(graphPerms)) {
            qdef.setUpdatePermissions(graphPerms);
        }
        return sparqlManager.executeAsk(qdef, tx);
    }

    /**
     * executes UpdateQuery
     *
     * @param queryString
     * @param bindings
     * @param tx
     * @param includeInferred
     * @param baseURI
     */
    public void performUpdateQuery(String queryString, SPARQLQueryBindingSet bindings, Transaction tx,
            boolean includeInferred, String baseURI) {
        SPARQLQueryDefinition qdef = sparqlManager.newQueryDefinition(queryString);
        if (notNull(baseURI) && !baseURI.isEmpty()) {
            qdef.setBaseUri(baseURI);
        }
        if (notNull(ruleset)) {
            qdef.setRulesets(ruleset);
        }
        if (notNull(graphPerms)) {
            qdef.setUpdatePermissions(graphPerms);
        }
        qdef.setIncludeDefaultRulesets(includeInferred);
        sparqlManager.clearPageLength();
        sparqlManager.executeUpdate(qdef, tx);
    }

    /**
     * executes merge of triples from File
     *
     * @param file
     * @param baseURI
     * @param dataFormat
     * @param tx
     * @param contexts
     * @throws RDFParseException
     */
    // performAdd
    // as we use mergeGraphs, baseURI is always file.toURI
    public void performAdd(File file, String baseURI, RDFFormat dataFormat, Transaction tx, Resource... contexts)
            throws RDFParseException {
        try {
            graphManager.setDefaultMimetype(dataFormat.getDefaultMIMEType());
            if (dataFormat.equals(RDFFormat.NQUADS) || dataFormat.equals(RDFFormat.TRIG)) {
                graphManager.mergeGraphs(new FileHandle(file), tx);
            } else {
                if (notNull(contexts) && contexts.length > 0) {
                    for (int i = 0; i < contexts.length; i++) {
                        if (notNull(contexts[i])) {
                            graphManager.mergeAs(contexts[i].toString(), new FileHandle(file), getGraphPerms(), tx);
                        } else {
                            graphManager.mergeAs(DEFAULT_GRAPH_URI, new FileHandle(file), getGraphPerms(), tx);
                        }
                    }
                } else {
                    graphManager.mergeAs(DEFAULT_GRAPH_URI, new FileHandle(file), getGraphPerms(), tx);
                }
            }
        } catch (FailedRequestException e) {
            logger.error(e.getLocalizedMessage());
            throw new RDFParseException("Request to MarkLogic server failed, check file and format.");
        }
    }

    /**
     * executes merge of triples from InputStream
     *
     * @param in
     * @param baseURI
     * @param dataFormat
     * @param tx
     * @param contexts
     * @throws RDFParseException
     */
    public void performAdd(InputStream in, String baseURI, RDFFormat dataFormat, Transaction tx,
            Resource... contexts) throws RDFParseException, MarkLogicSesameException {
        try {
            graphManager.setDefaultMimetype(dataFormat.getDefaultMIMEType());
            if (dataFormat.equals(RDFFormat.NQUADS) || dataFormat.equals(RDFFormat.TRIG)) {
                graphManager.mergeGraphs(new InputStreamHandle(in), tx);
            } else {
                if (notNull(contexts) && contexts.length > 0) {
                    for (int i = 0; i < contexts.length; i++) {
                        if (notNull(contexts[i])) {
                            graphManager.mergeAs(contexts[i].toString(), new InputStreamHandle(in), getGraphPerms(),
                                    tx);
                        } else {
                            graphManager.mergeAs(DEFAULT_GRAPH_URI, new InputStreamHandle(in), getGraphPerms(), tx);
                        }
                    }
                } else {
                    graphManager.mergeAs(DEFAULT_GRAPH_URI, new InputStreamHandle(in), getGraphPerms(), tx);
                }
            }
            in.close();
        } catch (FailedRequestException e) {
            logger.error(e.getLocalizedMessage());
            throw new RDFParseException("Request to MarkLogic server failed, check input is valid.");
        } catch (IOException e) {
            logger.error(e.getLocalizedMessage());
            throw new MarkLogicSesameException("IO error");
        }
    }

    /**
     * executes INSERT of single triple
     *
     * @param baseURI
     * @param subject
     * @param predicate
     * @param object
     * @param tx
     * @param contexts
     * @throws MarkLogicSesameException
     */
    public void performAdd(String baseURI, Resource subject, URI predicate, Value object, Transaction tx,
            Resource... contexts) throws MarkLogicSesameException {
        StringBuilder sb = new StringBuilder();
        if (notNull(contexts) && contexts.length > 0) {
            if (notNull(baseURI))
                sb.append("BASE <" + baseURI + ">\n");
            sb.append("INSERT DATA { ");
            for (int i = 0; i < contexts.length; i++) {
                if (notNull(contexts[i])) {
                    sb.append("GRAPH <" + contexts[i].stringValue() + "> { ?s ?p ?o .} ");
                } else {
                    sb.append("GRAPH <" + DEFAULT_GRAPH_URI + "> { ?s ?p ?o .} ");
                }
            }
            sb.append("}");
        } else {
            sb.append("INSERT DATA { GRAPH <" + DEFAULT_GRAPH_URI + "> {?s ?p ?o .}}");
        }
        SPARQLQueryDefinition qdef = sparqlManager.newQueryDefinition(sb.toString());
        if (notNull(ruleset)) {
            qdef.setRulesets(ruleset);
        }
        if (notNull(graphPerms)) {
            qdef.setUpdatePermissions(graphPerms);
        }
        if (notNull(baseURI) && !baseURI.isEmpty()) {
            qdef.setBaseUri(baseURI);
        }

        if (notNull(subject))
            qdef.withBinding("s", subject.stringValue());
        if (notNull(predicate))
            qdef.withBinding("p", predicate.stringValue());
        if (notNull(object))
            bindObject(qdef, "o", object);
        sparqlManager.executeUpdate(qdef, tx);
    }

    /**
     * executes DELETE of single triple
     *
     * @param baseURI
     * @param subject
     * @param predicate
     * @param object
     * @param tx
     * @param contexts
     * @throws MarkLogicSesameException
     */
    public void performRemove(String baseURI, Resource subject, URI predicate, Value object, Transaction tx,
            Resource... contexts) throws MarkLogicSesameException {
        StringBuilder sb = new StringBuilder();
        if (notNull(contexts) && contexts.length > 0) {
            if (notNull(baseURI))
                sb.append("BASE <" + baseURI + ">\n");
            sb.append("DELETE WHERE { ");
            for (int i = 0; i < contexts.length; i++) {
                if (notNull(contexts[i])) {
                    sb.append("GRAPH <" + contexts[i].stringValue() + "> { ?s ?p ?o .} ");
                } else {
                    sb.append("GRAPH <" + DEFAULT_GRAPH_URI + "> { ?s ?p ?o .} ");
                }
            }
            sb.append("}");
        } else {
            sb.append("DELETE WHERE { GRAPH ?ctx { ?s ?p ?o .}}");
        }

        SPARQLQueryDefinition qdef = sparqlManager.newQueryDefinition(sb.toString());
        if (notNull(baseURI) && !baseURI.isEmpty()) {
            qdef.setBaseUri(baseURI);
        }
        if (notNull(subject))
            qdef.withBinding("s", subject.stringValue());
        if (notNull(predicate))
            qdef.withBinding("p", predicate.stringValue());
        if (notNull(object))
            bindObject(qdef, "o", object);
        sparqlManager.executeUpdate(qdef, tx);
    }

    /**
     * clears triples from named graph
     *
     * @param tx
     * @param contexts
     */
    public void performClear(Transaction tx, Resource... contexts) {
        if (notNull(contexts)) {
            for (int i = 0; i < contexts.length; i++) {
                if (notNull(contexts[i])) {
                    graphManager.delete(contexts[i].stringValue(), tx);
                } else {
                    graphManager.delete(DEFAULT_GRAPH_URI, tx);
                }
            }
        } else {
            graphManager.delete(DEFAULT_GRAPH_URI, tx);
        }
    }

    /**
     * clears all triples
     *
     * @param tx
     */
    public void performClearAll(Transaction tx) {
        graphManager.deleteGraphs(tx);
    }

    /**
     * getter rulesets
     *
     * @return
     */
    public SPARQLRuleset[] getRulesets() {
        return this.ruleset;
    }

    /**
     * setter for rulesets, filters out nulls
     *
     * @param rulesets
     */
    public void setRulesets(SPARQLRuleset... rulesets) {
        if (notNull(rulesets)) {
            List<SPARQLRuleset> list = new ArrayList<>();
            for (Object r : rulesets) {
                if (r != null && rulesets.length > 0) {
                    list.add((SPARQLRuleset) r);
                }
            }
            this.ruleset = list.toArray(new SPARQLRuleset[list.size()]);
        } else {
            this.ruleset = null;
        }
    }

    /**
     * setter for graph permissions
     *
     * @param graphPerms
     */
    public void setGraphPerms(GraphPermissions graphPerms) {
        this.graphPerms = graphPerms;
    }

    /**
     * getter for graph permissions
     *
     * @return
     */
    public GraphPermissions getGraphPerms() {
        return this.graphPerms;
    }

    /**
     * setter for ConstrainingQueryDefinition
     *
     * @param constrainingQueryDefinition
     */
    public void setConstrainingQueryDefinition(QueryDefinition constrainingQueryDefinition) {
        this.constrainingQueryDef = constrainingQueryDefinition;
    }

    /**
     * getter for ConstrainingQueryDefinition
     *
     * @return
     */
    public QueryDefinition getConstrainingQueryDefinition() {
        return this.constrainingQueryDef;
    }

    /**
     * close client
     *
     * @return
     */
    public void close() {
        // close MarkLogicClientImpl
    }

    public void release() {
        if (this.databaseClient != null) {
            try {
                this.databaseClient.release();
            } catch (Exception e) {
                logger.info("Failed releasing DB client", e);
            }
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * converts Sesame BindingSet to java api client SPARQLBindings
     *
     * @param bindings
     * @return
     */
    protected SPARQLBindings getSPARQLBindings(SPARQLQueryBindingSet bindings) {
        SPARQLBindings sps = new SPARQLBindingsImpl();
        for (Binding binding : bindings) {
            sps.bind(binding.getName(), binding.getValue().stringValue());
        }
        return sps;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * bind object
     *
     * @param qdef
     * @param variableName
     * @param object
     * @return
     * @throws MarkLogicSesameException
     */
    private static SPARQLQueryDefinition bindObject(SPARQLQueryDefinition qdef, String variableName, Value object)
            throws MarkLogicSesameException {
        SPARQLBindings bindings = qdef.getBindings();
        if (object != null) {
            if (object instanceof URI) {
                bindings.bind(variableName, object.stringValue());
            } else if (object instanceof Literal) {
                Literal lit = (Literal) object;
                if (lit.getLanguage() != null) {
                    String languageTag = lit.getLanguage();
                    bindings.bind(variableName, lit.getLabel(), Locale.forLanguageTag(languageTag));
                } else if (((Literal) object).getDatatype() != null) {
                    try {
                        String xsdType = lit.getDatatype().toString();
                        String fragment = new java.net.URI(xsdType).getFragment();
                        bindings.bind(variableName, lit.getLabel(), RDFTypes.valueOf(fragment.toUpperCase()));
                    } catch (URISyntaxException e) {
                        logger.error(e.getLocalizedMessage());
                        throw new MarkLogicSesameException("Problem with object datatype.");
                    }
                } else {
                    // assume we have a string value
                    bindings.bind(variableName, lit.getLabel(), RDFTypes.STRING);
                }
            }
            qdef.setBindings(bindings);
        }
        return qdef;
    }

    /**
     * tedious utility for checking if object is null or not
     *
     * @param item
     * @return
     */
    private static Boolean notNull(Object item) {
        return item != null;
    }

}