Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject defaults into the planConnection query in the GTFS GraphQL schema #6339

Open
wants to merge 40 commits into
base: dev-2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c10fb01
Draft for injecting defaults into GraphQL schema
optionsome Dec 17, 2024
2c42d14
Don't rely on directive for injecting defaults
optionsome Dec 17, 2024
c51b975
Use dependency injection for providing GraphQL schema
optionsome Dec 30, 2024
f639ce5
Only construct schema if feature flag is on
optionsome Dec 30, 2024
38b5a5b
Use a slightly prettier method for getting parent name
optionsome Dec 30, 2024
698349e
Replace preferences with route request
optionsome Dec 31, 2024
7162c7a
Add structure for injecting defaults for arguments and use it for
optionsome Dec 31, 2024
280fd45
Add default for search window and allow resetting it to null
optionsome Dec 31, 2024
45eea03
Add the rest of defaults
optionsome Dec 31, 2024
d298811
Fix schema comment about duration being seconds
optionsome Dec 31, 2024
5fe8da8
Move schema tests to new file
optionsome Dec 31, 2024
4f89618
Add tests for default injection
optionsome Dec 31, 2024
6f4a6fb
Merge remote-tracking branch 'upstream/dev-2.x' into plan-connection-…
optionsome Dec 31, 2024
c105fc2
Fix comment
optionsome Dec 31, 2024
3beb9be
Use schema visitor instead of directive wiring
optionsome Jan 3, 2025
813bbbf
Initialize schema on server start up
optionsome Jan 7, 2025
9157359
Remove unnecessary annotation
optionsome Jan 8, 2025
7cd815e
Split factory method into two versions
optionsome Jan 8, 2025
3b3d7ff
Merge remote-tracking branch 'upstream/dev-2.x' into plan-connection-…
optionsome Jan 8, 2025
9f72862
Add javadoc
optionsome Jan 8, 2025
f7585cc
Remove service wrapper
optionsome Jan 10, 2025
69de270
Fix comment
optionsome Jan 10, 2025
fc7c77f
Add missing annotation
optionsome Jan 14, 2025
76db9b5
Refactor defaults
optionsome Jan 14, 2025
a06ed19
Merge remote-tracking branch 'upstream/dev-2.x' into plan-connection-…
optionsome Jan 21, 2025
e958fba
Don't crash OTP on schema building issue
optionsome Jan 24, 2025
e0a30ae
Split building into blocks
optionsome Jan 24, 2025
49954cc
Merge remote-tracking branch 'upstream/dev-2.x' into plan-connection-…
optionsome Jan 30, 2025
8aa1ce0
Refactor blocks into methods
optionsome Jan 30, 2025
0b49da8
Inject defaults for street modes
optionsome Jan 31, 2025
d1e3eac
Add defaults for bicycle/scooter oprimize
optionsome Jan 31, 2025
ab98348
Add defaults for vehicle parking filters/preferred
optionsome Feb 3, 2025
09e0566
Add defaults for allowed and banned rental networks
optionsome Feb 4, 2025
0f356a5
Convert TagsSelect into a class and return tags as list
optionsome Feb 4, 2025
b578c3c
Add default values for transit modes
optionsome Feb 5, 2025
136149a
Fix default value for modes in docs
optionsome Feb 5, 2025
ef7018a
Replace old transit mode mapper with new
optionsome Feb 6, 2025
e18a417
Simplify transit mode default mapping
optionsome Feb 6, 2025
64e5b45
Merge remote-tracking branch 'upstream/dev-2.x' into plan-connection-…
optionsome Feb 6, 2025
09fef41
Add default for car boardCost
optionsome Feb 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.opentripplanner.apis.gtfs;

import graphql.language.BooleanValue;
import graphql.language.FloatValue;
import graphql.language.IntValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.GraphQLArgument;
import graphql.schema.GraphQLInputObjectField;
import graphql.schema.GraphQLNamedSchemaElement;
import graphql.schema.GraphQLSchemaElement;
import graphql.schema.GraphQLTypeVisitor;
import graphql.schema.GraphQLTypeVisitorStub;
import graphql.util.TraversalControl;
import graphql.util.TraverserContext;
import org.opentripplanner.routing.api.request.RouteRequest;

/**
* GraphQL type visitor that injects default values to input fields and query arguments from code
* and configuration.
*/
public class DefaultValueInjector extends GraphQLTypeVisitorStub implements GraphQLTypeVisitor {

private final RouteRequest defaultRouteRequest;

public DefaultValueInjector(RouteRequest defaultRouteRequest) {
this.defaultRouteRequest = defaultRouteRequest;
}

@Override
public TraversalControl visitGraphQLArgument(
GraphQLArgument argument,
TraverserContext<GraphQLSchemaElement> context
) {
var defaultValue = getDefaultValueForSchemaObject(context, argument.getName());
if (defaultValue != null) {
return changeNode(
context,
argument.transform(builder -> builder.defaultValueLiteral(defaultValue).build())
);
}
return TraversalControl.CONTINUE;
}

@Override
public TraversalControl visitGraphQLInputObjectField(
GraphQLInputObjectField field,
TraverserContext<GraphQLSchemaElement> context
) {
var defaultValue = getDefaultValueForSchemaObject(context, field.getName());
if (defaultValue != null) {
return changeNode(
context,
field.transform(builder -> builder.defaultValueLiteral(defaultValue).build())
);
}
return TraversalControl.CONTINUE;
}

private Value getDefaultValueForSchemaObject(
TraverserContext<GraphQLSchemaElement> context,
String name
) {
// Arguments and input fields always have a parent
var parent = (GraphQLNamedSchemaElement) context.getParentNode();
var parentName = parent.getName();
var key = parentName + "_" + name;
optionsome marked this conversation as resolved.
Show resolved Hide resolved
var preferences = defaultRouteRequest.preferences();
switch (key) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider: A map and a bit of refactoring would make this code smaller and more readable. I switch might be faster but I doubt it. I would make builder for the map, so it would look like this:

 b = <new builder>;
 b
    // Add a requiered int
    .intReq("planConnection_first", defaultRouteRequest.numItineraries())
    // Add an optional string, since the argument is not a string the method dos the null check and calls `toString()`.
    .strOpt("planConnection_searchWindow", defaultRouteRequest.searchWindow())
    // Explicit more generic alternative
    .strOpt("planConnection_searchWindow", defaultRouteRequest.searchWindow(), Object::toString)

The comments are just to explain my code, I would strip those away and add JavaDoc on the metods instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did something like that in 76db9b5 . I left out the Object::toString and just called toString on the object, but I can change that if you want. I'm not sure if this is more readable for me since how the method calls get split on multiple lines sometimes, but it's not much less readable either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left out the Object::toString and just called toString on the object
That is perfectly fine, I only did it to make it possible to provide a custom toString().

I would probably try to get ridd of the method chain(preferences.bike().walking().speed()). A simple way to do it is to group the calls and define varables and make a small change to the builder. There is two way to create an "inner" builder, you chose the one you like best. One restrict the scope on(type, lambda) - is safer, the other on(type) : Builder is make the code more compact and more readable.

Like this

    var defaultRequest = ...;
var builder = new DefaultMappingBuilder()
      .intReq("planConnection.first", defaultRequest.numItineraries())
      .stringOpt("planConnection.searchWindow", defaultRequest.searchWindow());

    // Map Bike preferences
    {
      var bike = defaultRequest.preferences().bike();

      // EXAMPLE WITH LAMBDA
      builder
        .on(
          "BicycleParkingPreferencesInput",
          b ->
            b.intReq(
              "unpreferredCost",
              bike.parking().unpreferredVehicleParkingTagCost().toSeconds()
            )
        )
        .on(
          "BicyclePreferencesInput",
          b ->
            b
              .intReq("boardCost", bike.boardCost())
              .floatReq("reluctance", bike.reluctance())
              .floatReq("speed", bike.speed())
        );
      {
        var walking = bike.walking();
        // EXAMPLE RETURNING THE SCOPED BUILDER
        builder.on("BicycleWalkPreferencesCostInput")
          .intReq("mountDismountCost", walking.mountDismountCost().toSeconds())
          .floatReq("reluctance", walking.reluctance());

        builder.on("BicycleWalkPreferencesInput")
          .stringReq("mountDismountTime", walking.mountDismountTime())
          .floatReq("speed", walking.speed());
      }
      {
        var r = bike.rental();
        builder.on("DestinationBicyclePolicyInput")
          .boolReq("allowKeeping", r.allowArrivingInRentedVehicleAtDestination())
          .intReq("keepingCost", r.arrivingInRentalVehicleAtDestinationCost().toSeconds());
      }
    }
  }

  private static class DefaultMappingBuilder {

    private final Map<String, Value> defaultValueForKey;
    private final String typePrefix;

    private DefaultMappingBuilder(Map<String, Value> defaultValueForKey, String typePrefix) {
      this.defaultValueForKey = defaultValueForKey;
      this.typePrefix = typePrefix;
    }

    public DefaultMappingBuilder() {
      this(new HashMap<String, Value>(), "");
    }


    public DefaultMappingBuilder intReq(String key, int value) {
      return put(key, IntValue.of(value));
    }

    public DefaultMappingBuilder floatReq(String key, double value) {
      return put(key, FloatValue.of(value));
    }

    public DefaultMappingBuilder stringReq(String key, Object value) {
      return put(key, StringValue.of(value.toString()));
    }

    public DefaultMappingBuilder stringOpt(String key, @Nullable Object value) {
      return value == null ? null : put(key, StringValue.of(value.toString()));
    }

    public DefaultMappingBuilder boolReq(String key, boolean value) {
      return put(key, BooleanValue.of(value));
    }
    // Create a new builder and call lambda with it
    public DefaultMappingBuilder on(String type, Consumer<DefaultMappingBuilder> body) {
      body.accept(on(type));
      return this;
    }
    // Create new Builder and return it
    public DefaultMappingBuilder on(String type) {
      return new DefaultMappingBuilder(this.defaultValueForKey, type + ".");
    }

    private DefaultMappingBuilder put(String key, Value value) {
      defaultValueForKey.put(typePrefix + key, value);
      return this;
    }

    public Map<String, Value> build() {
      return defaultValueForKey;
    }
  }

case "planConnection_first":
return IntValue.of(defaultRouteRequest.numItineraries());
case "planConnection_searchWindow":
return defaultRouteRequest.searchWindow() != null
? StringValue.of(defaultRouteRequest.searchWindow().toString())
: null;
case "AlightPreferencesInput_slack":
return StringValue.of(preferences.transit().alightSlack().defaultValue().toString());
case "BicycleParkingPreferencesInput_unpreferredCost":
return IntValue.of(
preferences.bike().parking().unpreferredVehicleParkingTagCost().toSeconds()
);
case "BicyclePreferencesInput_boardCost":
return IntValue.of(preferences.bike().boardCost());
case "BicyclePreferencesInput_reluctance":
return FloatValue.of(preferences.bike().reluctance());
case "BicyclePreferencesInput_speed":
return FloatValue.of(preferences.bike().speed());
case "BicycleWalkPreferencesCostInput_mountDismountCost":
return IntValue.of(preferences.bike().walking().mountDismountCost().toSeconds());
case "BicycleWalkPreferencesCostInput_reluctance":
return FloatValue.of(preferences.bike().walking().reluctance());
case "BicycleWalkPreferencesInput_mountDismountTime":
return StringValue.of(preferences.bike().walking().mountDismountTime().toString());
case "BicycleWalkPreferencesInput_speed":
return FloatValue.of(preferences.bike().walking().speed());
case "BoardPreferencesInput_slack":
return StringValue.of(preferences.transit().boardSlack().defaultValue().toString());
case "BoardPreferencesInput_waitReluctance":
return FloatValue.of(preferences.transfer().waitReluctance());
case "CarParkingPreferencesInput_unpreferredCost":
return IntValue.of(
preferences.car().parking().unpreferredVehicleParkingTagCost().toSeconds()
);
case "CarPreferencesInput_reluctance":
return FloatValue.of(preferences.car().reluctance());
case "DestinationBicyclePolicyInput_allowKeeping":
return BooleanValue.of(
preferences.bike().rental().allowArrivingInRentedVehicleAtDestination()
);
case "DestinationBicyclePolicyInput_keepingCost":
return IntValue.of(
preferences.bike().rental().arrivingInRentalVehicleAtDestinationCost().toSeconds()
);
case "DestinationScooterPolicyInput_allowKeeping":
return BooleanValue.of(
preferences.scooter().rental().allowArrivingInRentedVehicleAtDestination()
);
case "DestinationScooterPolicyInput_keepingCost":
return IntValue.of(
preferences.scooter().rental().arrivingInRentalVehicleAtDestinationCost().toSeconds()
);
case "ScooterPreferencesInput_reluctance":
return FloatValue.of(preferences.scooter().reluctance());
case "ScooterPreferencesInput_speed":
return FloatValue.of(preferences.scooter().speed());
case "TimetablePreferencesInput_excludeRealTimeUpdates":
return BooleanValue.of(preferences.transit().ignoreRealtimeUpdates());
case "TimetablePreferencesInput_includePlannedCancellations":
return BooleanValue.of(preferences.transit().includePlannedCancellations());
case "TimetablePreferencesInput_includeRealTimeCancellations":
return BooleanValue.of(preferences.transit().includeRealtimeCancellations());
case "TransferPreferencesInput_cost":
return IntValue.of(preferences.transfer().cost());
case "TransferPreferencesInput_maximumAdditionalTransfers":
return IntValue.of(preferences.transfer().maxAdditionalTransfers());
case "TransferPreferencesInput_maximumTransfers":
// Max transfers are wrong in the internal model but fixed in the API mapping
return IntValue.of(preferences.transfer().maxTransfers() - 1);
case "TransferPreferencesInput_slack":
return StringValue.of(preferences.transfer().slack().toString());
case "WalkPreferencesInput_boardCost":
return IntValue.of(preferences.walk().boardCost());
case "WalkPreferencesInput_reluctance":
return FloatValue.of(preferences.walk().reluctance());
case "WalkPreferencesInput_safetyFactor":
return FloatValue.of(preferences.walk().safetyFactor());
case "WalkPreferencesInput_speed":
return FloatValue.of(preferences.walk().speed());
case "WheelchairPreferencesInput_enabled":
return BooleanValue.of(defaultRouteRequest.wheelchair());
default:
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentripplanner.apis.gtfs;

import graphql.schema.GraphQLSchema;
import org.opentripplanner.routing.api.RoutingService;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.routing.fares.FareService;
Expand All @@ -17,6 +18,7 @@ public record GraphQLRequestContext(
VehicleRentalService vehicleRentalService,
VehicleParkingService vehicleParkingService,
RealtimeVehicleService realTimeVehicleService,
GraphQLSchema schema,
GraphFinder graphFinder,
RouteRequest defaultRouteRequest
) {
Expand All @@ -28,6 +30,7 @@ public static GraphQLRequestContext ofServerContext(OtpServerRequestContext cont
context.vehicleRentalService(),
context.vehicleParkingService(),
context.realtimeVehicleService(),
context.schema(),
context.graphFinder(),
context.defaultRouteRequest()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,203 +7,22 @@
import graphql.execution.AbortExecutionException;
import graphql.execution.instrumentation.ChainedInstrumentation;
import graphql.execution.instrumentation.Instrumentation;
import graphql.scalars.ExtendedScalars;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import io.micrometer.core.instrument.Metrics;
import jakarta.ws.rs.core.Response;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.opentripplanner.apis.gtfs.datafetchers.AgencyImpl;
import org.opentripplanner.apis.gtfs.datafetchers.AlertEntityTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.AlertImpl;
import org.opentripplanner.apis.gtfs.datafetchers.BikeParkImpl;
import org.opentripplanner.apis.gtfs.datafetchers.BikeRentalStationImpl;
import org.opentripplanner.apis.gtfs.datafetchers.BookingInfoImpl;
import org.opentripplanner.apis.gtfs.datafetchers.BookingTimeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.CallScheduledTimeTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.CallStopLocationTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.CarParkImpl;
import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl;
import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl;
import org.opentripplanner.apis.gtfs.datafetchers.CurrencyImpl;
import org.opentripplanner.apis.gtfs.datafetchers.DefaultFareProductImpl;
import org.opentripplanner.apis.gtfs.datafetchers.DepartureRowImpl;
import org.opentripplanner.apis.gtfs.datafetchers.EstimatedTimeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.FareProductUseImpl;
import org.opentripplanner.apis.gtfs.datafetchers.FeedImpl;
import org.opentripplanner.apis.gtfs.datafetchers.GeometryImpl;
import org.opentripplanner.apis.gtfs.datafetchers.ItineraryImpl;
import org.opentripplanner.apis.gtfs.datafetchers.LegImpl;
import org.opentripplanner.apis.gtfs.datafetchers.LegTimeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.MoneyImpl;
import org.opentripplanner.apis.gtfs.datafetchers.NodeTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.OpeningHoursImpl;
import org.opentripplanner.apis.gtfs.datafetchers.PatternImpl;
import org.opentripplanner.apis.gtfs.datafetchers.PlaceImpl;
import org.opentripplanner.apis.gtfs.datafetchers.PlaceInterfaceTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.PlanConnectionImpl;
import org.opentripplanner.apis.gtfs.datafetchers.PlanImpl;
import org.opentripplanner.apis.gtfs.datafetchers.QueryTypeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RealTimeEstimateImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RentalPlaceTypeResolver;
import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleTypeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RideHailingEstimateImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RouteImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RouteTypeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.RoutingErrorImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StopCallImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StopGeometriesImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StopImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StopOnRouteImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StopOnTripImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StopRelationshipImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StoptimeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.StoptimesInPatternImpl;
import org.opentripplanner.apis.gtfs.datafetchers.SystemNoticeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.TicketTypeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.TranslatedStringImpl;
import org.opentripplanner.apis.gtfs.datafetchers.TripImpl;
import org.opentripplanner.apis.gtfs.datafetchers.TripOccupancyImpl;
import org.opentripplanner.apis.gtfs.datafetchers.TripOnServiceDateImpl;
import org.opentripplanner.apis.gtfs.datafetchers.UnknownImpl;
import org.opentripplanner.apis.gtfs.datafetchers.VehicleParkingImpl;
import org.opentripplanner.apis.gtfs.datafetchers.VehiclePositionImpl;
import org.opentripplanner.apis.gtfs.datafetchers.VehicleRentalNetworkImpl;
import org.opentripplanner.apis.gtfs.datafetchers.VehicleRentalStationImpl;
import org.opentripplanner.apis.gtfs.datafetchers.debugOutputImpl;
import org.opentripplanner.apis.gtfs.datafetchers.elevationProfileComponentImpl;
import org.opentripplanner.apis.gtfs.datafetchers.placeAtDistanceImpl;
import org.opentripplanner.apis.gtfs.datafetchers.serviceTimeRangeImpl;
import org.opentripplanner.apis.gtfs.datafetchers.stepImpl;
import org.opentripplanner.apis.gtfs.datafetchers.stopAtDistanceImpl;
import org.opentripplanner.apis.gtfs.model.StopPosition;
import org.opentripplanner.apis.support.graphql.LoggingDataFetcherExceptionHandler;
import org.opentripplanner.ext.actuator.MicrometerGraphQLInstrumentation;
import org.opentripplanner.framework.application.OTPFeature;
import org.opentripplanner.framework.graphql.GraphQLResponseSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class GtfsGraphQLIndex {

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

private static final GraphQLSchema indexSchema = buildSchema();

protected static GraphQLSchema buildSchema() {
try {
URL url = Objects.requireNonNull(GtfsGraphQLIndex.class.getResource("schema.graphqls"));
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(url.openStream());
IntrospectionTypeWiring typeWiring = new IntrospectionTypeWiring(typeRegistry);
RuntimeWiring runtimeWiring = RuntimeWiring
.newRuntimeWiring()
.scalar(GraphQLScalars.DURATION_SCALAR)
.scalar(GraphQLScalars.POLYLINE_SCALAR)
.scalar(GraphQLScalars.GEOJSON_SCALAR)
.scalar(GraphQLScalars.GRAPHQL_ID_SCALAR)
.scalar(GraphQLScalars.GRAMS_SCALAR)
.scalar(GraphQLScalars.OFFSET_DATETIME_SCALAR)
.scalar(GraphQLScalars.RATIO_SCALAR)
.scalar(GraphQLScalars.COORDINATE_VALUE_SCALAR)
.scalar(GraphQLScalars.COST_SCALAR)
.scalar(GraphQLScalars.RELUCTANCE_SCALAR)
.scalar(GraphQLScalars.LOCAL_DATE_SCALAR)
.scalar(ExtendedScalars.GraphQLLong)
.scalar(ExtendedScalars.Locale)
.scalar(
ExtendedScalars
.newAliasedScalar("Speed")
.aliasedScalar(ExtendedScalars.NonNegativeFloat)
.build()
)
.type("Node", type -> type.typeResolver(new NodeTypeResolver()))
.type("PlaceInterface", type -> type.typeResolver(new PlaceInterfaceTypeResolver()))
.type("RentalPlace", type -> type.typeResolver(new RentalPlaceTypeResolver()))
.type("StopPosition", type -> type.typeResolver(new StopPosition() {}))
.type("FareProduct", type -> type.typeResolver(new FareProductTypeResolver()))
.type("AlertEntity", type -> type.typeResolver(new AlertEntityTypeResolver()))
.type("CallStopLocation", type -> type.typeResolver(new CallStopLocationTypeResolver()))
.type("CallScheduledTime", type -> type.typeResolver(new CallScheduledTimeTypeResolver()))
.type(typeWiring.build(AgencyImpl.class))
.type(typeWiring.build(AlertImpl.class))
.type(typeWiring.build(BikeParkImpl.class))
.type(typeWiring.build(VehicleParkingImpl.class))
.type(typeWiring.build(BikeRentalStationImpl.class))
.type(typeWiring.build(CarParkImpl.class))
.type(typeWiring.build(CoordinatesImpl.class))
.type(typeWiring.build(debugOutputImpl.class))
.type(typeWiring.build(DepartureRowImpl.class))
.type(typeWiring.build(elevationProfileComponentImpl.class))
.type(typeWiring.build(FeedImpl.class))
.type(typeWiring.build(GeometryImpl.class))
.type(typeWiring.build(ItineraryImpl.class))
.type(typeWiring.build(LegImpl.class))
.type(typeWiring.build(PatternImpl.class))
.type(typeWiring.build(PlaceImpl.class))
.type(typeWiring.build(placeAtDistanceImpl.class))
.type(typeWiring.build(PlanConnectionImpl.class))
.type(typeWiring.build(PlanImpl.class))
.type(typeWiring.build(QueryTypeImpl.class))
.type(typeWiring.build(RouteImpl.class))
.type(typeWiring.build(serviceTimeRangeImpl.class))
.type(typeWiring.build(stepImpl.class))
.type(typeWiring.build(StopImpl.class))
.type(typeWiring.build(stopAtDistanceImpl.class))
.type(typeWiring.build(StoptimeImpl.class))
.type(typeWiring.build(StoptimesInPatternImpl.class))
.type(typeWiring.build(TicketTypeImpl.class))
.type(typeWiring.build(TranslatedStringImpl.class))
.type(typeWiring.build(TripImpl.class))
.type(typeWiring.build(SystemNoticeImpl.class))
.type(typeWiring.build(ContactInfoImpl.class))
.type(typeWiring.build(BookingTimeImpl.class))
.type(typeWiring.build(BookingInfoImpl.class))
.type(typeWiring.build(VehicleRentalStationImpl.class))
.type(typeWiring.build(VehicleRentalNetworkImpl.class))
.type(typeWiring.build(RentalVehicleImpl.class))
.type(typeWiring.build(RentalVehicleTypeImpl.class))
.type(typeWiring.build(StopOnRouteImpl.class))
.type(typeWiring.build(StopOnTripImpl.class))
.type(typeWiring.build(UnknownImpl.class))
.type(typeWiring.build(RouteTypeImpl.class))
.type(typeWiring.build(RoutingErrorImpl.class))
.type(typeWiring.build(StopGeometriesImpl.class))
.type(typeWiring.build(VehiclePositionImpl.class))
.type(typeWiring.build(StopRelationshipImpl.class))
.type(typeWiring.build(OpeningHoursImpl.class))
.type(typeWiring.build(RideHailingEstimateImpl.class))
.type(typeWiring.build(MoneyImpl.class))
.type(typeWiring.build(CurrencyImpl.class))
.type(typeWiring.build(FareProductUseImpl.class))
.type(typeWiring.build(DefaultFareProductImpl.class))
.type(typeWiring.build(TripOnServiceDateImpl.class))
.type(typeWiring.build(StopCallImpl.class))
.type(typeWiring.build(TripOccupancyImpl.class))
.type(typeWiring.build(LegTimeImpl.class))
.type(typeWiring.build(RealTimeEstimateImpl.class))
.type(typeWiring.build(EstimatedTimeImpl.class))
.build();
SchemaGenerator schemaGenerator = new SchemaGenerator();
return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
} catch (Exception e) {
LOG.error("Unable to build GTFS GraphQL Schema", e);
}
return null;
}

static ExecutionResult getGraphQLExecutionResult(
String query,
Map<String, Object> variables,
Expand All @@ -224,7 +43,7 @@ static ExecutionResult getGraphQLExecutionResult(
}

GraphQL graphQL = GraphQL
.newGraphQL(indexSchema)
.newGraphQL(requestContext.schema())
.instrumentation(instrumentation)
.defaultDataFetcherExceptionHandler(new LoggingDataFetcherExceptionHandler())
.build();
Expand Down
Loading
Loading