Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package com.tinkerpop.rexster;
import com.codahale.metrics.annotation.Timed;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.VertexQuery;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONMode;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONUtility;
import com.tinkerpop.rexster.extension.ExtensionMethod;
import com.tinkerpop.rexster.extension.ExtensionPoint;
import com.tinkerpop.rexster.extension.ExtensionResponse;
import com.tinkerpop.rexster.extension.ExtensionSegmentSet;
import com.tinkerpop.rexster.extension.HttpMethod;
import com.tinkerpop.rexster.extension.RexsterExtension;
import com.tinkerpop.rexster.server.RexsterApplication;
import com.tinkerpop.rexster.util.ElementHelper;
import com.tinkerpop.rexster.util.RequestObjectHelper;
import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Variant;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.Set;
/**
* Vertex resource.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
@Path("/graphs/{graphname}/vertices")
public class VertexResource extends AbstractSubResource {
private static Logger logger = Logger.getLogger(VertexResource.class);
public VertexResource() {
super(null);
}
public VertexResource(final UriInfo ui, final HttpServletRequest req, final RexsterApplication ra) {
super(ra);
this.httpServletRequest = req;
this.uriInfo = ui;
}
@OPTIONS
public Response optionsVertices() {
return buildOptionsResponse(HttpMethod.GET.toString(),
HttpMethod.POST.toString());
}
/**
* GET http://host/graph/vertices
* graph.getVertices();
*/
@GET
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON})
@Timed(name = "http.rest.vertices.collection.get", absolute = true)
public Response getVertices(@PathParam("graphname") final String graphName) {
return getVertices(graphName, false);
}
@GET
@Produces({RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.collection.get", absolute = true)
public Response getVerticesRexsterJson(@PathParam("graphname") final String graphName) {
return getVertices(graphName, true);
}
private Response getVertices(final String graphName, final boolean showTypes) {
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
final Graph graph = rag.getGraph();
final GraphSONMode mode = showTypes ? GraphSONMode.EXTENDED : GraphSONMode.NORMAL;
final JSONObject theRequestObject = this.getRequestObject();
final Long start = RequestObjectHelper.getStartOffset(theRequestObject);
final Long end = RequestObjectHelper.getEndOffset(theRequestObject);
final Set returnKeys = RequestObjectHelper.getReturnKeys(theRequestObject);
String key = null;
Object value = null;
Object temp = theRequestObject.opt(Tokens.KEY);
if (null != temp)
key = temp.toString();
temp = theRequestObject.opt(Tokens.VALUE);
if (null != temp)
value = ElementHelper.getTypedPropertyValue(temp.toString());
final boolean filtered = key != null && value != null;
try {
long counter = 0l;
final JSONArray vertexArray = new JSONArray();
boolean wasInSection = false;
final Iterable vertices = filtered ? graph.getVertices(key, value) : graph.getVertices();
for (Vertex vertex : vertices) {
if (counter >= start && counter < end) {
wasInSection = true;
vertexArray.put(GraphSONUtility.jsonFromElement(vertex, returnKeys, mode));
} else if (wasInSection) {
break;
}
counter++;
}
this.resultObject.put(Tokens.RESULTS, vertexArray);
this.resultObject.put(Tokens.TOTAL_SIZE, vertexArray.length());
this.resultObject.put(Tokens.QUERY_TIME, this.sh.stopWatch());
} catch (JSONException ex) {
logger.error(ex);
JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} catch (Exception re) {
logger.error(re);
JSONObject error = generateErrorObject(re.getMessage(), re);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} finally {
rag.tryCommit();
}
return Response.ok(this.resultObject).build();
}
@OPTIONS
@Path("/{id}")
public Response optionsSingleVertex() {
return buildOptionsResponse();
}
/**
* GET http://host/graph/vertices/id
* graph.getVertex(id);
*/
@GET
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON})
@Timed(name = "http.rest.vertices.object.get", absolute = true)
public Response getSingleVertex(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return getSingleVertex(graphName, id, false, false);
}
@GET
@Path("/{id}")
@Produces({RexsterMediaType.APPLICATION_REXSTER_JSON})
@Timed(name = "http.rest.vertices.object.get", absolute = true)
public Response getSingleVertexRexsterJson(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return getSingleVertex(graphName, id, false, true);
}
@GET
@Path("/{id}")
@Produces({RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.get", absolute = true)
public Response getSingleVertexRexsterTypedJson(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return getSingleVertex(graphName, id, true, true);
}
private Response getSingleVertex(final String graphName, final String id, final boolean showTypes, final boolean showHypermedia) {
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
try {
final Vertex vertex = rag.getGraph().getVertex(id);
if (null != vertex) {
final JSONObject theRequestObject = this.getRequestObject();
final GraphSONMode mode = showTypes ? GraphSONMode.EXTENDED : GraphSONMode.NORMAL;
final Set returnKeys = RequestObjectHelper.getReturnKeys(theRequestObject);
this.resultObject.put(Tokens.RESULTS, GraphSONUtility.jsonFromElement(vertex, returnKeys, mode));
this.resultObject.put(Tokens.QUERY_TIME, this.sh.stopWatch());
if (showHypermedia) {
JSONArray extensionsList = rag.getExtensionHypermedia(ExtensionPoint.VERTEX, this.getUriPath());
if (extensionsList != null) {
this.resultObject.put(Tokens.EXTENSIONS, extensionsList);
}
}
} else {
final String msg = "Vertex with [" + id + "] cannot be found.";
logger.info(msg);
final JSONObject error = generateErrorObject(msg);
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
} catch (JSONException ex) {
logger.error(ex);
final JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} finally {
rag.tryCommit();
}
return Response.ok(this.resultObject).build();
}
@HEAD
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_JSON)
public Response headVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
this.setRequestObject(json);
return this.executeVertexExtension(graphName, id, HttpMethod.HEAD);
}
@HEAD
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
public Response headVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return this.executeVertexExtension(graphName, id, HttpMethod.HEAD);
}
@PUT
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_JSON)
@Timed(name = "http.rest.vertices.extension.put", absolute = true)
public Response putVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
this.setRequestObject(json);
return this.executeVertexExtension(graphName, id, HttpMethod.PUT);
}
@PUT
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Timed(name = "http.rest.vertices.extension.put", absolute = true)
public Response putVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final MultivaluedMap formParams) {
this.setRequestObject(formParams);
return this.executeVertexExtension(graphName, id, HttpMethod.PUT);
}
@PUT
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Timed(name = "http.rest.vertices.extension.put", absolute = true)
public Response putVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return this.executeVertexExtension(graphName, id, HttpMethod.PUT);
}
@OPTIONS
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_JSON)
public Response optionsVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
this.setRequestObject(json);
return this.executeVertexExtension(graphName, id, HttpMethod.OPTIONS);
}
@OPTIONS
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
public Response optionsVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return this.executeVertexExtension(graphName, id, HttpMethod.OPTIONS);
}
@DELETE
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_JSON)
@Timed(name = "http.rest.vertices.extension.delete", absolute = true)
public Response deleteVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
this.setRequestObject(json);
return this.executeVertexExtension(graphName, id, HttpMethod.DELETE);
}
@DELETE
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Timed(name = "http.rest.vertices.extension.delete", absolute = true)
public Response deleteVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return this.executeVertexExtension(graphName, id, HttpMethod.DELETE);
}
@POST
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_JSON)
@Timed(name = "http.rest.vertices.extension.post", absolute = true)
public Response postVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
this.setRequestObject(json);
return this.executeVertexExtension(graphName, id, HttpMethod.POST);
}
@POST
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Timed(name = "http.rest.vertices.extension.post", absolute = true)
public Response postVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id, final MultivaluedMap formParams) {
this.setRequestObject(formParams);
return this.executeVertexExtension(graphName, id, HttpMethod.POST);
}
@POST
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Timed(name = "http.rest.vertices.extension.post", absolute = true)
public Response postVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return this.executeVertexExtension(graphName, id, HttpMethod.POST);
}
@GET
@Path("/{id}/{extension: (?!outE)(?!bothE)(?!inE)(?!out)(?!both)(?!in)(?!query).+}")
@Timed(name = "http.rest.vertices.extension.get", absolute = true)
public Response getVertexExtension(@PathParam("graphname") final String graphName, @PathParam("id") final String id) {
return this.executeVertexExtension(graphName, id, HttpMethod.GET);
}
private Response executeVertexExtension(final String graphName, final String id, final HttpMethod httpMethodRequested) {
final Vertex vertex = this.getRexsterApplicationGraph(graphName).getGraph().getVertex(id);
ExtensionResponse extResponse;
ExtensionMethod methodToCall;
final ExtensionSegmentSet extensionSegmentSet = parseUriForExtensionSegment(graphName, ExtensionPoint.VERTEX);
// determine if the namespace and extension are enabled for this graph
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
if (rag.isExtensionAllowed(extensionSegmentSet)) {
final Object returnValue;
// namespace was allowed so try to run the extension
try {
// look for the extension as loaded through serviceloader
final List rexsterExtensions;
try {
rexsterExtensions = findExtensionClasses(extensionSegmentSet);
} catch (ServiceConfigurationError sce) {
logger.error("ServiceLoader could not find a class referenced in com.tinkerpop.rexster.extension.RexsterExtension.");
final JSONObject error = generateErrorObject(
"Class specified in com.tinkerpop.rexster.extension.RexsterExtension could not be found.",
sce);
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
if (rexsterExtensions == null || rexsterExtensions.size() == 0) {
// extension was not found for some reason
logger.error("The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "]. Check com.tinkerpop.rexster.extension.RexsterExtension file in META-INF.services.");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "]");
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
// look up the method on the extension that needs to be called.
methodToCall = findExtensionMethod(rexsterExtensions, ExtensionPoint.VERTEX, extensionSegmentSet.getExtensionMethod(), httpMethodRequested);
if (methodToCall == null) {
// extension method was not found for some reason
if (httpMethodRequested == HttpMethod.OPTIONS) {
// intercept the options call and return the standard business
// no need to stop the transaction here
return buildOptionsResponse();
}
logger.error("The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "] with a HTTP method of [" + httpMethodRequested.name() + "]. Check com.tinkerpop.rexster.extension.RexsterExtension file in META-INF.services.");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "] with a HTTP method of [" + httpMethodRequested.name() + "]");
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
// found the method...time to do work
returnValue = invokeExtension(rag, methodToCall, vertex);
} catch (WebApplicationException wae) {
// already logged this...just throw it up.
rag.tryRollback();
throw wae;
} catch (Exception ex) {
logger.error("Dynamic invocation of the [" + extensionSegmentSet + "] extension failed.", ex);
if (ex.getCause() != null) {
final Throwable cause = ex.getCause();
logger.error("It would be smart to trap this this exception within the extension and supply a good response to the user:" + cause.getMessage(), cause);
}
rag.tryRollback();
final JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
if (returnValue instanceof ExtensionResponse) {
extResponse = (ExtensionResponse) returnValue;
if (extResponse.isErrorResponse()) {
// an error was raised within the extension. pass it back out as an error.
logger.warn("The [" + extensionSegmentSet + "] extension raised an error response.");
if (methodToCall.getExtensionDefinition().autoCommitTransaction()) {
rag.tryRollback();
}
throw new WebApplicationException(Response.fromResponse(extResponse.getJerseyResponse()).build());
}
if (methodToCall.getExtensionDefinition().autoCommitTransaction()) {
rag.tryCommit();
}
} else {
// extension method is not returning the correct type...needs to be an ExtensionResponse
logger.error("The [" + extensionSegmentSet + "] extension does not return an ExtensionResponse.");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension does not return an ExtensionResponse.");
rag.tryRollback();
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
} else {
// namespace was not allowed
logger.error("The [" + extensionSegmentSet + "] extension was not configured for [" + graphName + "]");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension was not configured for [" + graphName + "]");
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
String mediaType = MediaType.APPLICATION_JSON;
if (methodToCall != null) {
mediaType = methodToCall.getExtensionDefinition().produces();
extResponse = tryAppendRexsterAttributesIfJson(extResponse, methodToCall, mediaType);
}
return Response.fromResponse(extResponse.getJerseyResponse()).type(mediaType).build();
}
@OPTIONS
@Path("/{id}/{direction}")
public Response optionsVertexEdges() {
return buildOptionsResponse();
}
/**
* GET http://host/graph/vertices/id/direction
* graph.getVertex(id).get{Direction}Edges();
*/
@GET
@Path("/{id}/{direction}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON})
@Timed(name = "http.rest.vertices.object.edges.collection.get", absolute = true)
public Response getVertexEdges(@PathParam("graphname") String graphName, @PathParam("id") String vertexId, @PathParam("direction") String direction) {
return this.getVertexEdges(graphName, vertexId, direction, false);
}
@GET
@Path("/{id}/{direction}")
@Produces({RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.edges.collection.get", absolute = true)
public Response getVertexEdgesRexsterTypedJson(@PathParam("graphname") String graphName, @PathParam("id") String vertexId, @PathParam("direction") String direction) {
return this.getVertexEdges(graphName, vertexId, direction, true);
}
private Response getVertexEdges(String graphName, String vertexId, String direction, boolean showTypes) {
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
try {
final Vertex vertex = rag.getGraph().getVertex(vertexId);
if (vertex == null) {
final String msg = "Vertex with [" + vertexId + "] cannot be found.";
logger.info(msg);
final JSONObject error = generateErrorObject(msg);
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
final GraphSONMode mode = showTypes ? GraphSONMode.EXTENDED : GraphSONMode.NORMAL;
final JSONObject theRequestObject = this.getRequestObject();
final Long start = RequestObjectHelper.getStartOffset(theRequestObject);
final Long end = RequestObjectHelper.getEndOffset(theRequestObject);
final Set returnKeys = RequestObjectHelper.getReturnKeys(theRequestObject);
// accept either an array of labels or just one label
final String[] labels = getLabelsFromRequest(theRequestObject);
// break out the segment into the return and the direction
final VertexQueryArguments queryArguments = new VertexQueryArguments(direction);
// if this is a query and the _return is "count" then we don't bother to send back the
// result array
final boolean countOnly = queryArguments.isCountOnly();
// what kind of data the calling client wants back (vertices, edges, count, vertex identifiers)
final ReturnType returnType = queryArguments.getReturnType();
// the query direction (both, out, in)
final Direction queryDirection = queryArguments.getQueryDirection();
long counter = 0l;
final JSONArray elementArray = new JSONArray();
VertexQuery query = vertex.query().direction(queryDirection);
if (labels != null) {
query = query.labels(labels);
}
// add .has() elements to query
RequestObjectHelper.buildQueryProperties(theRequestObject, query);
// need to include limits in addition to standard rexster paging as there is buffering going on via
// rexstergraph that requires both ... meaning, i might do a vertex query with limit that exceeds my
// buffer size for rexstergraph.
final int limitTake = theRequestObject.has(Tokens._TAKE) ? theRequestObject.getInt(Tokens._TAKE) : Integer.MIN_VALUE;
//final long limitSkip = theRequestObject.has(Tokens._SKIP) ? theRequestObject.getLong(Tokens._SKIP) : Long.MIN_VALUE;
if (limitTake >= 0) {
query = query.limit(limitTake);
}
if (returnType == ReturnType.VERTICES || returnType == ReturnType.VERTEX_IDS) {
final Iterable vertexQueryResults = query.vertices();
for (Vertex v : vertexQueryResults) {
if (counter >= start && counter < end) {
if (returnType.equals(ReturnType.VERTICES)) {
elementArray.put(GraphSONUtility.jsonFromElement(v, returnKeys, mode));
} else {
elementArray.put(v.getId());
}
}
counter++;
}
} else if (returnType == ReturnType.EDGES) {
final Iterable edgeQueryResults = query.edges();
for (Edge e : edgeQueryResults) {
if (counter >= start && counter < end) {
elementArray.put(GraphSONUtility.jsonFromElement(e, returnKeys, mode));
}
counter++;
}
} else if (returnType == ReturnType.COUNT) {
counter = query.count();
} else {
final JSONObject error = generateErrorObject(direction + " direction segment was invalid.");
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(error).build());
}
if (!countOnly) {
this.resultObject.put(Tokens.RESULTS, elementArray);
}
this.resultObject.put(Tokens.TOTAL_SIZE, counter);
this.resultObject.put(Tokens.QUERY_TIME, this.sh.stopWatch());
} catch (JSONException ex) {
logger.error(ex);
final JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} catch (WebApplicationException wae) {
throw wae;
} catch (Exception re) {
logger.error(re);
final JSONObject error = generateErrorObject(re.getMessage(), re);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} finally {
rag.tryCommit();
}
return Response.ok(this.resultObject).build();
}
@POST
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Consumes({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON})
@Timed(name = "http.rest.vertices.object.post", absolute = true)
public Response postNullVertexRexsterConsumesJson(@Context final Request request, @PathParam("graphname") final String graphName, final JSONObject json) {
// initializes the request object with the data POSTed to the resource. URI parameters
// will then be ignored when the getRequestObject is called as the request object will
// have already been established.
this.setRequestObject(json);
final Variant v = request.selectVariant(producesVariantList);
return this.postVertex(graphName, null, false, v);
}
@POST
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Consumes({RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.post", absolute = true)
public Response postNullVertexRexsterConsumesTypedJson(@Context final Request request, @PathParam("graphname") final String graphName, final JSONObject json) {
// initializes the request object with the data POSTed to the resource. URI parameters
// will then be ignored when the getRequestObject is called as the request object will
// have already been established.
this.setRequestObject(json);
final Variant v = request.selectVariant(producesVariantList);
return this.postVertex(graphName, null, true, v);
}
/**
* POST http://host/graph/vertices
* graph.addVertex(null);
*/
@POST
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.post", absolute = true)
public Response postNullVertexOnUri(@Context final Request request, @PathParam("graphname") final String graphName) {
final Variant v = request.selectVariant(producesVariantList);
return this.postVertex(graphName, null, true, v);
}
/**
* POST http://host/graph/vertices/id
* Vertex v = graph.addVertex(id);
* v.setProperty(key,value);
*/
@POST
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Consumes({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON})
@Timed(name = "http.rest.vertices.object.post", absolute = true)
public Response postVertexConsumesJson(@Context final Request request, @PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
// initializes the request object with the data POSTed to the resource. URI parameters
// will then be ignored when the getRequestObject is called as the request object will
// have already been established.
this.setRequestObject(json);
final Variant v = request.selectVariant(producesVariantList);
return this.postVertex(graphName, id, false, v);
}
@POST
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Consumes({RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.post", absolute = true)
public Response postVertexRexsterConsumesTypedJson(@Context final Request request, @PathParam("graphname") final String graphName, @PathParam("id") final String id, final JSONObject json) {
// initializes the request object with the data POSTed to the resource. URI parameters
// will then be ignored when the getRequestObject is called as the request object will
// have already been established.
this.setRequestObject(json);
final Variant v = request.selectVariant(producesVariantList);
return this.postVertex(graphName, id, true, v);
}
/**
* POST http://host/graph/vertices/id?key=value
* Vertex v = graph.addVertex(id);
* v.setProperty(key,value);
*/
@POST
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.post", absolute = true)
public Response postVertexOnUri(@Context final Request request, @PathParam("graphname") final String graphName, @PathParam("id") final String id) {
final Variant v = request.selectVariant(producesVariantList);
return postVertex(graphName, id, true, v);
}
private Response postVertex(final String graphName, final String id, final boolean parseTypes, final Variant variant) {
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
final Graph graph = rag.getGraph();
final MediaType produces = variant.getMediaType();
final boolean showTypes = produces.equals(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON_TYPE);
final boolean showHypermedia = produces.equals(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON_TYPE)
|| produces.equals(RexsterMediaType.APPLICATION_REXSTER_JSON_TYPE);
try {
// blueprints throws IllegalArgumentException if the id is null
Vertex vertex = id == null ? null : graph.getVertex(id);
final JSONObject theRequestObject = this.getRequestObject();
if (null == vertex) {
vertex = graph.addVertex(id);
} else {
if (!RequestObjectHelper.hasElementProperties(theRequestObject)) {
// if the edge exists there better be some properties to assign
// this really isn't a BAD_REQUEST, but CONFLICT isn't much better...bah
JSONObject error = generateErrorObjectJsonFail(new Exception("Vertex with id " + id + " already exists"));
throw new WebApplicationException(Response.status(Status.CONFLICT).entity(error).build());
}
}
final Iterator keys = theRequestObject.keys();
while (keys.hasNext()) {
final String key = keys.next().toString();
if (!key.startsWith(Tokens.UNDERSCORE)) {
vertex.setProperty(key, ElementHelper.getTypedPropertyValue(theRequestObject.get(key), parseTypes));
}
}
final GraphSONMode mode = showTypes ? GraphSONMode.EXTENDED : GraphSONMode.NORMAL;
final Set returnKeys = RequestObjectHelper.getReturnKeys(theRequestObject);
final JSONObject elementJson = GraphSONUtility.jsonFromElement(vertex, returnKeys, mode);
rag.tryCommit();
// some graph implementations close scope at the close of the transaction so we generate the
// JSON before the transaction but set the id after for graphs that don't generate the id
// until the transaction is committed
elementJson.put(Tokens._ID, vertex.getId());
this.resultObject.put(Tokens.RESULTS, elementJson);
if (showHypermedia) {
final JSONArray extensionsList = rag.getExtensionHypermedia(ExtensionPoint.VERTEX, this.getUriPath());
if (extensionsList != null) {
this.resultObject.put(Tokens.EXTENSIONS, extensionsList);
}
}
this.resultObject.put(Tokens.QUERY_TIME, sh.stopWatch());
} catch (JSONException ex) {
rag.tryRollback();
logger.error(ex);
JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} catch (Exception re) {
rag.tryRollback();
logger.error(re);
JSONObject error = generateErrorObject(re.getMessage(), re);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
return Response.ok(this.resultObject).build();
}
/**
* PUT http://host/graph/vertices/id
* Vertex v = graph.addVertex(id);
* v.setProperty(key,value);
*/
@PUT
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Consumes({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON})
@Timed(name = "http.rest.vertices.object.put", absolute = true)
public Response putVertexConsumesJson(@Context Request request, @PathParam("graphname") String graphName, @PathParam("id") String id, JSONObject json) {
// initializes the request object with the data PUTed to the resource. URI parameters
// will then be ignored when the getRequestObject is called as the request object will
// have already been established.
this.setRequestObject(json);
Variant v = request.selectVariant(producesVariantList);
return this.putVertex(graphName, id, false, v);
}
@PUT
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Consumes(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON)
@Timed(name = "http.rest.vertices.object.put", absolute = true)
public Response putVertexConsumesTypedJson(@Context Request request, @PathParam("graphname") String graphName, @PathParam("id") String id, JSONObject json) {
// initializes the request object with the data PUTed to the resource. URI parameters
// will then be ignored when the getRequestObject is called as the request object will
// have already been established.
this.setRequestObject(json);
Variant v = request.selectVariant(producesVariantList);
return this.putVertex(graphName, id, true, v);
}
/**
* PUT http://host/graph/vertices/id?key=value
* remove all properties
* v.setProperty(key,value);
*/
@PUT
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.put", absolute = true)
public Response putVertexConsumesUri(@Context Request request, @PathParam("graphname") String graphName, @PathParam("id") String id) {
Variant v = request.selectVariant(producesVariantList);
return putVertex(graphName, id, true, v);
}
private Response putVertex(final String graphName, final String id, final boolean parseTypes, final Variant variant) {
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
final Graph graph = rag.getGraph();
final MediaType produces = variant.getMediaType();
final boolean showTypes = produces.equals(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON_TYPE);
final boolean showHypermedia = produces.equals(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON_TYPE)
|| produces.equals(RexsterMediaType.APPLICATION_REXSTER_JSON_TYPE);
try {
final Vertex vertex = graph.getVertex(id);
if (null == vertex) {
final String msg = "Vertex with [" + id + "] cannot be found.";
logger.info(msg);
final JSONObject error = generateErrorObject(msg);
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
// remove all properties as this is a replace operation
com.tinkerpop.blueprints.util.ElementHelper.removeProperties(new ArrayList() {{
add(vertex);
}});
final JSONObject theRequestObject = this.getRequestObject();
final Iterator keys = theRequestObject.keys();
while (keys.hasNext()) {
final String key = keys.next().toString();
if (!key.startsWith(Tokens.UNDERSCORE)) {
vertex.setProperty(key, ElementHelper.getTypedPropertyValue(theRequestObject.get(key), parseTypes));
}
}
rag.tryCommit();
// some graph implementations close scope at the close of the transaction so this has to be
// reconstituted
final Vertex reconstitutedElement = graph.getVertex(vertex.getId());
final GraphSONMode mode = showTypes ? GraphSONMode.EXTENDED : GraphSONMode.NORMAL;
final Set returnKeys = RequestObjectHelper.getReturnKeys(theRequestObject);
this.resultObject.put(Tokens.RESULTS, GraphSONUtility.jsonFromElement(reconstitutedElement, returnKeys, mode));
if (showHypermedia) {
final JSONArray extensionsList = rag.getExtensionHypermedia(ExtensionPoint.VERTEX, this.getUriPath());
if (extensionsList != null) {
this.resultObject.put(Tokens.EXTENSIONS, extensionsList);
}
}
this.resultObject.put(Tokens.QUERY_TIME, sh.stopWatch());
} catch (JSONException ex) {
rag.tryRollback();
logger.error(ex);
JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} catch (Exception re) {
rag.tryRollback();
logger.error(re);
JSONObject error = generateErrorObject(re.getMessage(), re);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
return Response.ok(this.resultObject).build();
}
/**
* DELETE http://host/graph/vertices/id
* graph.removeVertex(graph.getVertex(id));
*
* DELETE http://host/graph/vertices/id?key1&key2
* Vertex v = graph.getVertex(id);
* v.removeProperty(key1);
* v.removeProperty(key2);
*/
@DELETE
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, RexsterMediaType.APPLICATION_REXSTER_JSON, RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON})
@Timed(name = "http.rest.vertices.object.delete", absolute = true)
public Response deleteVertex(@PathParam("graphname") String graphName, @PathParam("id") String id) {
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
final Graph graph = rag.getGraph();
try {
final List keys = this.getNonRexsterRequestKeys();
final Vertex vertex = graph.getVertex(id);
if (null != vertex) {
if (keys.size() > 0) {
// delete vertex properites
for (final String key : keys) {
vertex.removeProperty(key);
}
} else {
// delete vertex
graph.removeVertex(vertex);
}
} else {
final String msg = "Vertex with [" + id + "] cannot be found.";
logger.info(msg);
JSONObject error = generateErrorObject(msg);
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
rag.tryCommit();
this.resultObject.put(Tokens.QUERY_TIME, sh.stopWatch());
} catch (JSONException ex) {
rag.tryRollback();
logger.error(ex);
final JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
} catch (Exception re) {
rag.tryRollback();
logger.error(re);
final JSONObject error = generateErrorObject(re.getMessage(), re);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
return Response.ok(this.resultObject).build();
}
private static String[] getLabelsFromRequest(JSONObject theRequestObject) {
JSONArray labelSet = theRequestObject.optJSONArray(Tokens._LABEL);
if (labelSet == null) {
final String oneLabel = theRequestObject.optString(Tokens._LABEL);
if (oneLabel != null && !oneLabel.isEmpty()) {
labelSet = new JSONArray();
labelSet.put(oneLabel);
}
}
String[] labels = null;
if (labelSet != null) {
labels = new String[labelSet.length()];
for (int ix = 0; ix < labelSet.length(); ix++) {
labels[ix] = labelSet.optString(ix);
}
}
return labels;
}
private enum ReturnType {VERTICES, EDGES, COUNT, VERTEX_IDS}
private final class VertexQueryArguments {
private final Direction queryDirection;
private final ReturnType returnType;
private final boolean countOnly;
public VertexQueryArguments(String directionSegment) {
if (directionSegment.equals(Tokens.OUT_E)) {
returnType = ReturnType.EDGES;
queryDirection = Direction.OUT;
countOnly = false;
} else if (directionSegment.equals(Tokens.IN_E)) {
returnType = ReturnType.EDGES;
queryDirection = Direction.IN;
countOnly = false;
} else if (directionSegment.equals(Tokens.BOTH_E)) {
returnType = ReturnType.EDGES;
queryDirection = Direction.BOTH;
countOnly = false;
} else if (directionSegment.equals(Tokens.OUT)) {
returnType = ReturnType.VERTICES;
queryDirection = Direction.OUT;
countOnly = false;
} else if (directionSegment.equals(Tokens.IN)) {
returnType = ReturnType.VERTICES;
queryDirection = Direction.IN;
countOnly = false;
} else if (directionSegment.equals(Tokens.BOTH)) {
returnType = ReturnType.VERTICES;
queryDirection = Direction.BOTH;
countOnly = false;
} else if (directionSegment.equals(Tokens.BOTH_COUNT)) {
returnType = ReturnType.COUNT;
queryDirection = Direction.BOTH;
countOnly = true;
} else if (directionSegment.equals(Tokens.IN_COUNT)) {
returnType = ReturnType.COUNT;
queryDirection = Direction.IN;
countOnly = true;
} else if (directionSegment.equals(Tokens.OUT_COUNT)) {
returnType = ReturnType.COUNT;
queryDirection = Direction.OUT;
countOnly = true;
} else if (directionSegment.equals(Tokens.BOTH_IDS)) {
returnType = ReturnType.VERTEX_IDS;
queryDirection = Direction.BOTH;
countOnly = false;
} else if (directionSegment.equals(Tokens.IN_IDS)) {
returnType = ReturnType.VERTEX_IDS;
queryDirection = Direction.IN;
countOnly = false;
} else if (directionSegment.equals(Tokens.OUT_IDS)) {
returnType = ReturnType.VERTEX_IDS;
queryDirection = Direction.OUT;
countOnly = false;
} else {
final JSONObject error = generateErrorObject(directionSegment + " segment was invalid.");
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(error).build());
}
}
public Direction getQueryDirection() {
return queryDirection;
}
public ReturnType getReturnType() {
return returnType;
}
public boolean isCountOnly() {
return countOnly;
}
}
}