org.opentripplanner.ext.legacygraphqlapi.LegacyGraphQLAPI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.ext.legacygraphqlapi;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.ExecutionResult;
import org.opentripplanner.api.json.GraphQLResponseSerializer;
import org.opentripplanner.standalone.server.OTPServer;
import org.opentripplanner.standalone.server.Router;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
// TODO move to org.opentripplanner.api.resource, this is a Jersey resource class
@Path("/routers/{ignoreRouterId}/index/graphql")
@Produces(MediaType.APPLICATION_JSON) // One @Produces annotation for all endpoints.
public class LegacyGraphQLAPI {
@SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(LegacyGraphQLAPI.class);
private final Router router;
private final ObjectMapper deserializer = new ObjectMapper();
/**
* @deprecated The support for multiple routers are removed from OTP2.
* See https://github.com/opentripplanner/OpenTripPlanner/issues/2760
*/
@Deprecated @PathParam("ignoreRouterId")
private String ignoreRouterId;
public LegacyGraphQLAPI(@Context OTPServer otpServer) {
this.router = otpServer.getRouter();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response getGraphQL(
HashMap queryParameters,
@HeaderParam("OTPTimeout") @DefaultValue("30000") int timeout,
@HeaderParam("OTPMaxResolves") @DefaultValue("1000000") int maxResolves,
@Context HttpHeaders headers
) {
if (queryParameters == null || !queryParameters.containsKey("query")) {
LOG.debug("No query found in body");
return Response
.status(Response.Status.BAD_REQUEST)
.type(MediaType.TEXT_PLAIN_TYPE)
.entity("No query found in body")
.build();
}
Locale locale = headers.getAcceptableLanguages().size() > 0
? headers.getAcceptableLanguages().get(0)
: router.defaultRoutingRequest.locale;
String query = (String) queryParameters.get("query");
Object queryVariables = queryParameters.getOrDefault("variables", null);
String operationName = (String) queryParameters.getOrDefault("operationName", null);
Map variables;
if (queryVariables instanceof Map) {
variables = (Map) queryVariables;
}
else if (queryVariables instanceof String && !((String) queryVariables).isEmpty()) {
try {
variables = deserializer.readValue((String) queryVariables, Map.class);
}
catch (IOException e) {
return Response
.status(Response.Status.BAD_REQUEST)
.type(MediaType.TEXT_PLAIN_TYPE)
.entity("Variables must be a valid json object")
.build();
}
}
else {
variables = new HashMap<>();
}
return LegacyGraphQLIndex.getGraphQLResponse(
query,
router,
variables,
operationName,
maxResolves,
timeout,
locale
);
}
@POST
@Consumes("application/graphql")
public Response getGraphQL(
String query,
@HeaderParam("OTPTimeout") @DefaultValue("30000") int timeout,
@HeaderParam("OTPMaxResolves") @DefaultValue("1000000") int maxResolves,
@Context HttpHeaders headers
) {
Locale locale = headers.getAcceptableLanguages().size() > 0
? headers.getAcceptableLanguages().get(0)
: router.defaultRoutingRequest.locale;
return LegacyGraphQLIndex.getGraphQLResponse(
query,
router,
null,
null,
maxResolves,
timeout,
locale);
}
@POST
@Path("/batch")
@Consumes(MediaType.APPLICATION_JSON)
public Response getGraphQLBatch(
List> queries,
@HeaderParam("OTPTimeout") @DefaultValue("30000") int timeout,
@HeaderParam("OTPMaxResolves") @DefaultValue("1000000") int maxResolves,
@Context HttpHeaders headers
) {
List> futures = new ArrayList<>();
Locale locale = headers.getAcceptableLanguages().size() > 0
? headers.getAcceptableLanguages().get(0)
: router.defaultRoutingRequest.locale;
for (HashMap query : queries) {
Map variables;
if (query.get("variables") instanceof Map) {
variables = (Map) query.get("variables");
}
else if (query.get("variables") instanceof String
&& ((String) query.get("variables")).length() > 0) {
try {
variables = deserializer.readValue((String) query.get("variables"), Map.class);
}
catch (IOException e) {
return Response
.status(Response.Status.BAD_REQUEST)
.type(MediaType.TEXT_PLAIN_TYPE)
.entity("Variables must be a valid json object")
.build();
}
}
else {
variables = null;
}
String operationName = (String) query.getOrDefault("operationName", null);
futures.add(() -> LegacyGraphQLIndex.getGraphQLExecutionResult((String) query.get("query"),
router,
variables,
operationName,
maxResolves,
timeout,
locale
));
}
try {
List> results = LegacyGraphQLIndex.threadPool.invokeAll(futures);
return Response.status(Response.Status.OK).entity(GraphQLResponseSerializer.serializeBatch(queries, results)).build();
} catch (InterruptedException e) {
LOG.error("Batch query interrupted", e);
throw new RuntimeException(e);
}
}
}