All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.api.resource.PlannerResource Maven / Gradle / Ivy

package org.opentripplanner.api.resource;

import java.time.LocalDateTime;
import java.time.ZoneId;
import javax.ws.rs.GET;
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.MediaType;
import javax.ws.rs.core.UriInfo;
import org.glassfish.grizzly.http.server.Request;
import org.opentripplanner.api.common.Message;
import org.opentripplanner.api.common.RoutingResource;
import org.opentripplanner.api.mapping.PlannerErrorMapper;
import org.opentripplanner.api.mapping.TripPlanMapper;
import org.opentripplanner.api.mapping.TripSearchMetadataMapper;
import org.opentripplanner.api.model.error.PlannerError;
import org.opentripplanner.model.plan.Itinerary;
import org.opentripplanner.routing.RoutingService;
import org.opentripplanner.routing.api.request.RoutingRequest;
import org.opentripplanner.routing.api.response.RoutingResponse;
import org.opentripplanner.standalone.server.Router;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is the primary entry point for the trip planning web service.
 * All parameters are passed in the query string. These parameters are defined as fields in the abstract
 * RoutingResource superclass, which also has methods for building routing requests from query
 * parameters. This allows multiple web services to have the same set of query parameters.
 * In order for inheritance to work, the REST resources are request-scoped (constructed at each request)
 * rather than singleton-scoped (a single instance existing for the lifetime of the OTP server).
 */
@Path("routers/{ignoreRouterId}/plan") // final element needed here rather than on method to distinguish from routers API
public class PlannerResource extends RoutingResource {

    private static final Logger LOG = LoggerFactory.getLogger(PlannerResource.class);

    /**
     * @deprecated The support for multiple routers are removed from OTP2.
     * See https://github.com/opentripplanner/OpenTripPlanner/issues/2760
     */
    @Deprecated @PathParam("ignoreRouterId")
    private String ignoreRouterId;

    // We inject info about the incoming request so we can include the incoming query
    // parameters in the outgoing response. This is a TriMet requirement.
    // Jersey uses @Context to inject internal types and @InjectParam or @Resource for DI objects.
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public TripPlannerResponse plan(@Context UriInfo uriInfo, @Context Request grizzlyRequest) {

        /*
         * TODO: add Lang / Locale parameter, and thus get localized content (Messages & more...)
         * TODO: from/to inputs should be converted / geocoded / etc... here, and maybe send coords 
         *       or vertex ids to planner (or error back to user)
         * TODO: org.opentripplanner.routing.module.PathServiceImpl has COOORD parsing. Abstract that
         *       out so it's used here too...
         */

        // Create response object, containing a copy of all request parameters. Maybe they should be in the debug section of the response.
        TripPlannerResponse response = new TripPlannerResponse(uriInfo);
        RoutingRequest request = null;
        Router router = null;
        RoutingResponse res = null;
        try {

            /* Fill in request fields from query parameters via shared superclass method, catching any errors. */
            request = super.buildRequest(uriInfo.getQueryParameters());
            router = otpServer.getRouter();

            // Route
            RoutingService routingService = new RoutingService(router.graph);
            res = routingService.route(request, router);

            // Map to API
            TripPlanMapper tripPlanMapper = new TripPlanMapper(request.locale, request.showIntermediateStops);
            response.setPlan(tripPlanMapper.mapTripPlan(res.getTripPlan()));
            if (res.getPreviousPageCursor() != null) {
                response.setPreviousPageCursor(res.getPreviousPageCursor().encode());
            }
            if (res.getNextPageCursor() != null) {
                response.setNextPageCursor(res.getNextPageCursor().encode());
            }
            response.setMetadata(TripSearchMetadataMapper.mapTripSearchMetadata(res.getMetadata()));
            if (!res.getRoutingErrors().isEmpty()) {
                // The api can only return one error message, so the first one is mapped
                response.setError(PlannerErrorMapper.mapMessage(res.getRoutingErrors().get(0)));
            }

            /* Populate up the elevation metadata */
            response.elevationMetadata = new ElevationMetadata();
            response.elevationMetadata.ellipsoidToGeoidDifference = router.graph.ellipsoidToGeoidDifference;
            response.elevationMetadata.geoidElevation = request.geoidElevation;

            response.debugOutput = res.getDebugTimingAggregator().finishedRendering();
        }
        catch (Exception e) {
            LOG.error("System error", e);
            PlannerError error = new PlannerError(Message.SYSTEM_ERROR);
            response.setError(error);
        }

        /* Log this request if such logging is enabled. */
        logRequest(grizzlyRequest, request, router, res);

        return response;
    }

    private void logRequest(
        Request grizzlyRequest,
        RoutingRequest request,
        Router router,
        RoutingResponse res
    ) {
        if (request != null && router != null && router.requestLogger != null) {
            StringBuilder sb = new StringBuilder();
            String clientIpAddress = grizzlyRequest.getRemoteAddr();
            //sb.append(LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
            sb.append(clientIpAddress);
            sb.append(' ');
            sb.append(request.arriveBy ? "ARRIVE" : "DEPART");
            sb.append(' ');
            sb.append(LocalDateTime.ofInstant(request.getDateTime(), ZoneId.systemDefault()));
            sb.append(' ');
            sb.append(request.streetSubRequestModes.getAsStr());
            sb.append(' ');
            sb.append(request.from.lat);
            sb.append(' ');
            sb.append(request.from.lng);
            sb.append(' ');
            sb.append(request.to.lat);
            sb.append(' ');
            sb.append(request.to.lng);
            sb.append(' ');
            if (res != null) {
                for (Itinerary it : res.getTripPlan().itineraries) {
                    sb.append(it.durationSeconds);
                    sb.append(' ');
                }
            }
            router.requestLogger.info(sb.toString());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy