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

org.opentripplanner.standalone.configure.ConstructApplication Maven / Gradle / Ivy

The newest version!
package org.opentripplanner.standalone.configure;

import jakarta.ws.rs.core.Application;
import javax.annotation.Nullable;
import org.opentripplanner.apis.transmodel.TransmodelAPI;
import org.opentripplanner.datastore.api.DataSource;
import org.opentripplanner.ext.emissions.EmissionsDataModel;
import org.opentripplanner.ext.stopconsolidation.StopConsolidationRepository;
import org.opentripplanner.framework.application.LogMDCSupport;
import org.opentripplanner.framework.application.OTPFeature;
import org.opentripplanner.graph_builder.GraphBuilder;
import org.opentripplanner.graph_builder.GraphBuilderDataSources;
import org.opentripplanner.graph_builder.issue.api.DataImportIssueSummary;
import org.opentripplanner.raptor.configure.RaptorConfig;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.RaptorTransitData;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitTuningParameters;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TripSchedule;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.RaptorTransitDataMapper;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.service.osminfo.OsmInfoGraphBuildRepository;
import org.opentripplanner.service.realtimevehicles.RealtimeVehicleRepository;
import org.opentripplanner.service.vehicleparking.VehicleParkingRepository;
import org.opentripplanner.service.vehicleparking.VehicleParkingService;
import org.opentripplanner.service.vehiclerental.VehicleRentalRepository;
import org.opentripplanner.service.worldenvelope.WorldEnvelopeRepository;
import org.opentripplanner.standalone.api.OtpServerRequestContext;
import org.opentripplanner.standalone.config.BuildConfig;
import org.opentripplanner.standalone.config.CommandLineParameters;
import org.opentripplanner.standalone.config.ConfigModel;
import org.opentripplanner.standalone.config.DebugUiConfig;
import org.opentripplanner.standalone.config.OtpConfig;
import org.opentripplanner.standalone.config.RouterConfig;
import org.opentripplanner.standalone.server.GrizzlyServer;
import org.opentripplanner.standalone.server.OTPWebApplication;
import org.opentripplanner.street.model.StreetLimitationParameters;
import org.opentripplanner.street.model.elevation.ElevationUtils;
import org.opentripplanner.transit.service.TimetableRepository;
import org.opentripplanner.updater.configure.UpdaterConfigurator;
import org.opentripplanner.updater.trip.TimetableSnapshotManager;
import org.opentripplanner.utils.logging.ProgressTracker;
import org.opentripplanner.visualizer.GraphVisualizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is responsible for creating the top level services like the {@link OTPWebApplication}
 * and {@link GraphBuilder}. The purpose of this class is to wire the application, creating the
 * necessary Services and modules and putting them together. It is NOT responsible for starting or
 * running the application. The whole idea of this class is to separate application construction
 * from running it.
 * 

* The top level construction class(this class) may delegate to other construction classes * to inject configuration and services into submodules. An instance of this class is created * using the {@link LoadApplication} - An application is constructed AFTER config and input files * are loaded. *

* THIS CLASS IS NOT THREAD SAFE - THE APPLICATION SHOULD BE CREATED IN ONE THREAD. This * should be really fast, since the only IO operations are reading config files and logging. Loading * transit or map data should NOT happen during this phase. */ public class ConstructApplication { private static final Logger LOG = LoggerFactory.getLogger(ConstructApplication.class); private final CommandLineParameters cli; private final GraphBuilderDataSources graphBuilderDataSources; /** * The OSM Info is injected into the graph-builder, but not the web-server; Hence not part of * the application context. */ private final OsmInfoGraphBuildRepository osmInfoGraphBuildRepository; private final ConstructApplicationFactory factory; /** * Create a new OTP configuration instance for a given directory. */ ConstructApplication( CommandLineParameters cli, Graph graph, OsmInfoGraphBuildRepository osmInfoGraphBuildRepository, TimetableRepository timetableRepository, WorldEnvelopeRepository worldEnvelopeRepository, ConfigModel config, GraphBuilderDataSources graphBuilderDataSources, DataImportIssueSummary issueSummary, EmissionsDataModel emissionsDataModel, VehicleParkingRepository vehicleParkingRepository, @Nullable StopConsolidationRepository stopConsolidationRepository, StreetLimitationParameters streetLimitationParameters ) { this.cli = cli; this.graphBuilderDataSources = graphBuilderDataSources; this.osmInfoGraphBuildRepository = osmInfoGraphBuildRepository; // We create the optional GraphVisualizer here, because it would be significant more complex to // use Dagger DI to do it - passing in a parameter to enable it or not. var graphVisualizer = cli.visualize ? new GraphVisualizer(graph) : null; this.factory = DaggerConstructApplicationFactory.builder() .configModel(config) .graph(graph) .timetableRepository(timetableRepository) .graphVisualizer(graphVisualizer) .worldEnvelopeRepository(worldEnvelopeRepository) .vehicleParkingRepository(vehicleParkingRepository) .emissionsDataModel(emissionsDataModel) .dataImportIssueSummary(issueSummary) .stopConsolidationRepository(stopConsolidationRepository) .streetLimitationParameters(streetLimitationParameters) .schema(config.routerConfig().routingRequestDefaults()) .build(); } public ConstructApplicationFactory getFactory() { return factory; } /** * Create a new Grizzly server - call this method once, the new instance is created every time * this method is called. */ public GrizzlyServer createGrizzlyServer() { return new GrizzlyServer( cli, createApplication(), routerConfig().server().apiProcessingTimeout() ); } /** * Create the default graph builder. */ public GraphBuilder createGraphBuilder() { LOG.info("Wiring up and configuring graph builder task."); return GraphBuilder.create( buildConfig(), graphBuilderDataSources, graph(), osmInfoGraphBuildRepository, factory.timetableRepository(), factory.worldEnvelopeRepository(), factory.vehicleParkingRepository(), factory.emissionsDataModel(), factory.stopConsolidationRepository(), factory.streetLimitationParameters(), cli.doLoadStreetGraph(), cli.doSaveStreetGraph() ); } /** * The output data source to use for saving the serialized graph. *

* This method will return {@code null} if the graph should NOT be saved. The business logic to * make that decision is in the {@link GraphBuilderDataSources}. */ @Nullable public DataSource graphOutputDataSource() { return graphBuilderDataSources.getOutputGraph(); } private Application createApplication() { LOG.info("Wiring up and configuring server."); setupTransitRoutingServer(); return new OTPWebApplication(routerConfig().server(), this::createServerContext); } private void setupTransitRoutingServer() { enableRequestTraceLogging(); createMetricsLogging(); createRaptorTransitData(timetableRepository(), routerConfig().transitTuningConfig()); /* Create updater modules from JSON config. */ UpdaterConfigurator.configure( graph(), realtimeVehicleRepository(), vehicleRentalRepository(), vehicleParkingRepository(), timetableRepository(), snapshotManager(), routerConfig().updaterConfig() ); initEllipsoidToGeoidDifference(); initializeTransferCache(routerConfig().transitTuningConfig(), timetableRepository()); if (OTPFeature.TransmodelGraphQlApi.isOn()) { TransmodelAPI.setUp( routerConfig().transmodelApi(), timetableRepository(), routerConfig().routingRequestDefaults(), routerConfig().server().apiDocumentationProfile(), routerConfig().transitTuningConfig() ); } if (OTPFeature.SandboxAPIGeocoder.isOn()) { LOG.info("Initializing geocoder"); // eagerly initialize the geocoder this.factory.luceneIndex(); } } private void initEllipsoidToGeoidDifference() { try { var c = factory.worldEnvelopeService().envelope().orElseThrow().center(); double value = ElevationUtils.computeEllipsoidToGeoidDifference(c.latitude(), c.longitude()); graph().initEllipsoidToGeoidDifference(value, c.latitude(), c.longitude()); } catch (Exception e) { LOG.error("Error computing ellipsoid/geoid difference"); } } /** * Create transit layer for Raptor routing. Here we map the scheduled timetables. */ public static void createRaptorTransitData( TimetableRepository timetableRepository, TransitTuningParameters tuningParameters ) { if (!timetableRepository.hasTransit() || !timetableRepository.isIndexed()) { LOG.warn( "Cannot create Raptor data, that requires the graph to have transit data and be indexed." ); } LOG.info("Creating transit layer for Raptor routing."); timetableRepository.setRaptorTransitData( RaptorTransitDataMapper.map(tuningParameters, timetableRepository) ); timetableRepository.setRealtimeRaptorTransitData( new RaptorTransitData(timetableRepository.getRaptorTransitData()) ); } public static void initializeTransferCache( TransitTuningParameters transitTuningConfig, TimetableRepository timetableRepository ) { var transferCacheRequests = transitTuningConfig.transferCacheRequests(); if (!transferCacheRequests.isEmpty()) { var progress = ProgressTracker.track( "Creating initial raptor transfer cache", 1, transferCacheRequests.size() ); LOG.info(progress.startMessage()); transferCacheRequests.forEach(request -> { timetableRepository.getRaptorTransitData().initTransferCacheForRequest(request); //noinspection Convert2MethodRef progress.step(s -> LOG.info(s)); }); LOG.info(progress.completeMessage()); } } public TimetableRepository timetableRepository() { return factory.timetableRepository(); } public DataImportIssueSummary dataImportIssueSummary() { return factory.dataImportIssueSummary(); } public OsmInfoGraphBuildRepository osmInfoGraphBuildRepository() { return osmInfoGraphBuildRepository; } public StopConsolidationRepository stopConsolidationRepository() { return factory.stopConsolidationRepository(); } public RealtimeVehicleRepository realtimeVehicleRepository() { return factory.realtimeVehicleRepository(); } public VehicleRentalRepository vehicleRentalRepository() { return factory.vehicleRentalRepository(); } private TimetableSnapshotManager snapshotManager() { return factory.timetableSnapshotManager(); } public VehicleParkingService vehicleParkingService() { return factory.vehicleParkingService(); } public VehicleParkingRepository vehicleParkingRepository() { return factory.vehicleParkingRepository(); } public Graph graph() { return factory.graph(); } public WorldEnvelopeRepository worldEnvelopeRepository() { return factory.worldEnvelopeRepository(); } public OtpConfig otpConfig() { return factory.config().otpConfig(); } public RouterConfig routerConfig() { return factory.config().routerConfig(); } public BuildConfig buildConfig() { return factory.config().buildConfig(); } public DebugUiConfig debugUiConfig() { return factory.config().debugUiConfig(); } public RaptorConfig raptorConfig() { return factory.raptorConfig(); } public GraphVisualizer graphVisualizer() { return factory.graphVisualizer(); } private OtpServerRequestContext createServerContext() { return factory.createServerContext(); } private void enableRequestTraceLogging() { if (routerConfig().server().requestTraceLoggingEnabled()) { LogMDCSupport.enable(); } } private void createMetricsLogging() { factory.metricsLogging(); } public EmissionsDataModel emissionsDataModel() { return factory.emissionsDataModel(); } public StreetLimitationParameters streetLimitationParameters() { return factory.streetLimitationParameters(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy