package com.tinkerpop.rexster.kibbles.sparql; import com.tinkerpop.blueprints.Graph; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.impls.sail.SailGraph; import com.tinkerpop.blueprints.util.io.graphson.GraphSONMode; import com.tinkerpop.blueprints.util.io.graphson.GraphSONUtility; import com.tinkerpop.rexster.RexsterResourceContext; import com.tinkerpop.rexster.Tokens; import com.tinkerpop.rexster.extension.AbstractRexsterExtension; import com.tinkerpop.rexster.extension.ExtensionApi; import com.tinkerpop.rexster.extension.ExtensionDefinition; import com.tinkerpop.rexster.extension.ExtensionDescriptor; import com.tinkerpop.rexster.extension.ExtensionMethod; import com.tinkerpop.rexster.extension.ExtensionNaming; import com.tinkerpop.rexster.extension.ExtensionPoint; import com.tinkerpop.rexster.extension.ExtensionRequestParameter; import com.tinkerpop.rexster.extension.ExtensionResponse; import com.tinkerpop.rexster.extension.RexsterContext; import com.tinkerpop.rexster.util.RequestObjectHelper; import org.apache.log4j.Logger; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONObject; import javax.ws.rs.core.Response; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * The SPARQL Extension allows execution of SPARQL queries to Sail implementations. */ @ExtensionNaming(namespace = SparqlExtension.EXTENSION_NAMESPACE, name = SparqlExtension.EXTENSION_NAME) public class SparqlExtension extends AbstractRexsterExtension { private static Logger logger = Logger.getLogger(SparqlExtension.class); public static final String EXTENSION_NAMESPACE = "tp"; public static final String EXTENSION_NAME = "sparql"; private static final String WILDCARD = "*"; private static final String API_SHOW_TYPES = "displays the properties of the elements with their native data type (default is false)"; private static final String API_QUERY = "the SPARQL query to be evaluated"; private static final String API_RETURN_KEYS = "an array of element property keys to return (default is to return all element properties)"; @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH) @ExtensionDescriptor(description = "execute SPARQL queries against a SAIL graph.", api = { @ExtensionApi(parameterName = Tokens.REXSTER + "." + Tokens.SHOW_TYPES, description = API_SHOW_TYPES), @ExtensionApi(parameterName = Tokens.REXSTER + "." + Tokens.RETURN_KEYS, description = API_RETURN_KEYS) }) public ExtensionResponse evaluateSparql(@RexsterContext final RexsterResourceContext context, @RexsterContext final Graph graph, @ExtensionRequestParameter(name = "query", description = API_QUERY) final String queryString) { if (queryString == null || queryString.isEmpty()) { final ExtensionMethod extMethod = context.getExtensionMethod(); return ExtensionResponse.error( "the query parameter cannot be empty", null, Response.Status.BAD_REQUEST.getStatusCode(), null, generateErrorJson(extMethod.getExtensionApiAsJson())); } final JSONObject requestObject = context.getRequestObject(); final boolean showTypes = RequestObjectHelper.getShowTypes(requestObject); final GraphSONMode mode = showTypes ? GraphSONMode.EXTENDED : GraphSONMode.NORMAL; final Set<String> returnKeys = RequestObjectHelper.getReturnKeys(requestObject, WILDCARD); if (!(graph instanceof SailGraph)) { final ExtensionMethod extMethod = context.getExtensionMethod(); return ExtensionResponse.error( "the graph to which this extension is applied is not a SailGraph implementation", null, Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), null, generateErrorJson(extMethod.getExtensionApiAsJson())); } try { final SailGraph sailGraph = (SailGraph) graph; final List<Map<String, Vertex>> sparqlResults = sailGraph.executeSparql(queryString); final JSONArray jsonArray = new JSONArray(); for (Map<String, Vertex> map : sparqlResults) { Map<String, JSONObject> mapOfJson = new HashMap<String, JSONObject>(); for (String key : map.keySet()) { mapOfJson.put(key, GraphSONUtility.jsonFromElement(map.get(key), returnKeys, mode)); } jsonArray.put(new JSONObject(mapOfJson)); } final HashMap<String, Object> resultMap = new HashMap<String, Object>(); resultMap.put(Tokens.SUCCESS, true); resultMap.put(Tokens.RESULTS, jsonArray); final JSONObject resultObject = new JSONObject(resultMap); return ExtensionResponse.ok(resultObject); } catch (Exception mqe) { logger.error(mqe); return ExtensionResponse.error( "Error executing SPARQL query [" + queryString + "]", generateErrorJson()); } } }