edu.cornell.mannlib.vitro.webapp.controller.admin.SparqlQueryController.java Source code

Java tutorial

Introduction

Here is the source code for edu.cornell.mannlib.vitro.webapp.controller.admin.SparqlQueryController.java

Source

/* $This file is distributed under the terms of the license in /doc/license.txt$ */

package edu.cornell.mannlib.vitro.webapp.controller.admin;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryParseException;

import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.beans.Ontology;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery.InvalidQueryTypeException;
import edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery.SparqlQueryApiExecutor;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.utils.http.AcceptHeaderParsingException;
import edu.cornell.mannlib.vitro.webapp.utils.http.NotAcceptableException;

/**
 * Present the SPARQL Query form, and execute the queries.
 */
public class SparqlQueryController extends FreemarkerHttpServlet {
    private static final Log log = LogFactory.getLog(SparqlQueryController.class);

    private static final String TEMPLATE_NAME = "admin-sparqlQueryForm.ftl";

    /**
     * Always show these prefixes, even though they don't appear in the list of
     * ontologies.
     */
    private static final List<Prefix> DEFAULT_PREFIXES = buildDefaults();

    private static List<Prefix> buildDefaults() {
        Prefix[] array = new Prefix[] { new Prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"),
                new Prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"),
                new Prefix("xsd", "http://www.w3.org/2001/XMLSchema#"),
                new Prefix("owl", "http://www.w3.org/2002/07/owl#"),
                new Prefix("swrl", "http://www.w3.org/2003/11/swrl#"),
                new Prefix("swrlb", "http://www.w3.org/2003/11/swrlb#"),
                new Prefix("vitro", "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#") };
        return Collections.unmodifiableList(Arrays.asList(array));
    }

    private static final String[] SAMPLE_QUERY = { //
            "", //
            "#", //
            "# This example query gets 20 geographic locations", //
            "# and (if available) their labels", //
            "#", //
            "SELECT ?geoLocation ?label", //
            "WHERE", //
            "{", //
            "      ?geoLocation rdf:type vivo:GeographicLocation",
            "      OPTIONAL { ?geoLocation rdfs:label ?label } ", //
            "}", //
            "LIMIT 20" //
    };

    /**
     * If a query has been provided, we answer it directly, bypassing the
     * Freemarker mechanisms.
     */
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        if (!isAuthorizedToDisplayPage(req, resp, SimplePermission.USE_SPARQL_QUERY_PAGE.ACTION)) {
            return;
        }
        if (req.getParameterMap().containsKey("query")) {
            respondToQuery(req, resp);
        } else {
            super.doGet(req, resp);
        }
    }

    private void respondToQuery(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        RDFService rdfService = ModelAccess.on(getServletContext()).getRDFService();

        String queryString = req.getParameter("query");
        try {
            String format = interpretRequestedFormats(req, queryString);
            SparqlQueryApiExecutor core = SparqlQueryApiExecutor.instance(rdfService, queryString, format);
            resp.setContentType(core.getMediaType());
            core.executeAndFormat(resp.getOutputStream());
        } catch (InvalidQueryTypeException e) {
            do400BadRequest("Query type is not SELECT, ASK, CONSTRUCT, " + "or DESCRIBE: '" + queryString + "'",
                    resp);
        } catch (QueryParseException e) {
            do400BadRequest("Failed to parse query: '" + queryString + "''", e, resp);
        } catch (NotAcceptableException | AcceptHeaderParsingException e) {
            do500InternalServerError("Problem with the page fields: the " + "selected fields do not include an "
                    + "acceptable content type.", e, resp);
        } catch (RDFServiceException e) {
            do500InternalServerError("Problem executing the query.", e, resp);
        }
    }

    private String interpretRequestedFormats(HttpServletRequest req, String queryString)
            throws NotAcceptableException {
        Query query = SparqlQueryUtils.create(queryString);
        String parameterName = (query.isSelectType() || query.isAskType()) ? "resultFormat" : "rdfResultFormat";
        String parameterValue = req.getParameter(parameterName);
        if (StringUtils.isBlank(parameterValue)) {
            throw new NotAcceptableException("Parameter '" + parameterName + "' was '" + parameterValue + "'.");
        } else {
            return parameterValue;
        }
    }

    private void do400BadRequest(String message, HttpServletResponse resp) throws IOException {
        resp.setStatus(400);
        resp.getWriter().println(message);
    }

    private void do400BadRequest(String message, Exception e, HttpServletResponse resp) throws IOException {
        resp.setStatus(400);
        PrintWriter w = resp.getWriter();
        w.println(message);
        e.printStackTrace(w);
    }

    private void do500InternalServerError(String message, Exception e, HttpServletResponse resp)
            throws IOException {
        resp.setStatus(500);
        PrintWriter w = resp.getWriter();
        w.println(message);
        e.printStackTrace(w);
    }

    @Override
    protected ResponseValues processRequest(VitroRequest vreq) throws Exception {
        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("sampleQuery", buildSampleQuery(buildPrefixList(vreq)));
        bodyMap.put("title", "SPARQL Query");
        bodyMap.put("submitUrl", UrlBuilder.getUrl("admin/sparqlquery"));
        return new TemplateResponseValues(TEMPLATE_NAME, bodyMap);
    }

    private List<Prefix> buildPrefixList(VitroRequest vreq) {
        List<Prefix> prefixList = new ArrayList<>(DEFAULT_PREFIXES);

        OntologyDao dao = vreq.getUnfilteredWebappDaoFactory().getOntologyDao();
        List<Ontology> ontologies = dao.getAllOntologies();
        if (ontologies == null) {
            ontologies = Collections.emptyList();
        }

        int unnamedOntologyIndex = 1;

        for (Ontology ont : ontologies) {
            String prefix = ont.getPrefix();
            if (prefix == null) {
                prefix = "p" + unnamedOntologyIndex++;
            }
            prefixList.add(new Prefix(prefix, ont.getURI()));
        }

        return prefixList;
    }

    private String buildSampleQuery(List<Prefix> prefixList) {
        StringWriter sw = new StringWriter();
        PrintWriter writer = new PrintWriter(sw);

        for (Prefix p : prefixList) {
            writer.println(p);
        }
        for (String line : SAMPLE_QUERY) {
            writer.println(line);
        }

        return sw.toString();
    }

    public static class Prefix {
        private final String prefix;
        private final String uri;

        public Prefix(String prefix, String uri) {
            this.prefix = prefix;
            this.uri = uri;
        }

        @Override
        public String toString() {
            return String.format("PREFIX %-9s <%s>", prefix + ":", uri);
        }
    }

}