From 26b4bc97bbe35ea1fd5ea6f2e71b2b74e3032744 Mon Sep 17 00:00:00 2001 From: Sabina Fataliyeva Date: Thu, 19 Dec 2024 13:33:32 +0200 Subject: [PATCH] Fetcher to for getting a single service link --- .../uttu/graphql/LinesGraphQLSchema.java | 51 +++++++++++- .../uttu/graphql/fetchers/RoutingFetcher.java | 78 +++++++++++++++++++ .../entur/uttu/graphql/model/ServiceLink.java | 10 +++ .../entur/uttu/routing/osrm/OsrmService.java | 20 ++++- 4 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/main/java/no/entur/uttu/graphql/fetchers/RoutingFetcher.java create mode 100644 src/main/java/no/entur/uttu/graphql/model/ServiceLink.java diff --git a/src/main/java/no/entur/uttu/graphql/LinesGraphQLSchema.java b/src/main/java/no/entur/uttu/graphql/LinesGraphQLSchema.java index 52f0e055..cee196c5 100644 --- a/src/main/java/no/entur/uttu/graphql/LinesGraphQLSchema.java +++ b/src/main/java/no/entur/uttu/graphql/LinesGraphQLSchema.java @@ -19,6 +19,7 @@ import static graphql.Scalars.GraphQLID; import static graphql.Scalars.GraphQLInt; import static graphql.Scalars.GraphQLString; +import static graphql.scalars.ExtendedScalars.GraphQLBigDecimal; import static graphql.scalars.ExtendedScalars.GraphQLLong; import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; import static graphql.schema.GraphQLInputObjectField.newInputObjectField; @@ -50,6 +51,7 @@ import no.entur.uttu.graphql.fetchers.DayTypeServiceJourneyCountFetcher; import no.entur.uttu.graphql.fetchers.ExportedPublicLinesFetcher; import no.entur.uttu.graphql.model.Organisation; +import no.entur.uttu.graphql.model.ServiceLink; import no.entur.uttu.graphql.model.StopPlace; import no.entur.uttu.graphql.scalars.DateScalar; import no.entur.uttu.graphql.scalars.DateTimeScalar; @@ -87,7 +89,6 @@ import org.locationtech.jts.geom.Geometry; import org.rutebanken.netex.model.AllVehicleModesOfTransportEnumeration; import org.rutebanken.netex.model.OrganisationTypeEnumeration; -import org.rutebanken.netex.model.Organisation_VersionStructure; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @@ -161,6 +162,9 @@ public class LinesGraphQLSchema { @Autowired private DataFetcher> stopPlacesFetcher; + @Autowired + private DataFetcher routingFetcher; + private GraphQLEnumType createEnum( String name, T[] values, @@ -263,6 +267,8 @@ private GraphQLEnumType createEnum( private GraphQLObjectType stopPlaceObjectType; private GraphQLObjectType organisationObjectType; + private GraphQLObjectType routeGeometryObjectType; + private GraphQLObjectType serviceLinkObjectType; private GraphQLArgument idArgument; private GraphQLArgument idsArgument; @@ -913,6 +919,26 @@ private void initCommonTypes() { .field(newFieldDefinition().name(FIELD_NAME).type(multilingualStringObjectType)) .field(newFieldDefinition().name("type").type(organisationTypeEnum)) .build(); + + routeGeometryObjectType = + newObject() + .name("RouteGeometry") + .field( + newFieldDefinition() + .name("coordinates") + .type(new GraphQLList(new GraphQLList(GraphQLBigDecimal))) + ) + .field(newFieldDefinition().name("distance").type(GraphQLBigDecimal)) + .build(); + + serviceLinkObjectType = + newObject() + .name("ServiceLink") + .field(newFieldDefinition().name("routeGeometry").type(routeGeometryObjectType)) + .field(newFieldDefinition().name("quayRefFrom").type(GraphQLString)) + .field(newFieldDefinition().name("quayRefTo").type(GraphQLString)) + .field(newFieldDefinition().name("serviceLinkRef").type(GraphQLString)) + .build(); } private GraphQLObjectType createQueryObject() { @@ -1102,6 +1128,29 @@ private GraphQLObjectType createQueryObject() { .description("List all organisations") .dataFetcher(organisationsFetcher) ) + .field( + newFieldDefinition() + .type(serviceLinkObjectType) + .name("serviceLink") + .argument( + GraphQLArgument + .newArgument() + .name("quayRefFrom") + .type(GraphQLString) + .description("First stop point's id") + .build() + ) + .argument( + GraphQLArgument + .newArgument() + .name("quayRefTo") + .type(GraphQLString) + .description("Second stop point's id") + .build() + ) + .description("Fetch service link containing route geometry") + .dataFetcher(routingFetcher) + ) .build(); } diff --git a/src/main/java/no/entur/uttu/graphql/fetchers/RoutingFetcher.java b/src/main/java/no/entur/uttu/graphql/fetchers/RoutingFetcher.java new file mode 100644 index 00000000..4e7cac21 --- /dev/null +++ b/src/main/java/no/entur/uttu/graphql/fetchers/RoutingFetcher.java @@ -0,0 +1,78 @@ +package no.entur.uttu.graphql.fetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.util.List; +import java.util.Optional; +import no.entur.uttu.graphql.model.ServiceLink; +import no.entur.uttu.routing.RouteGeometry; +import no.entur.uttu.routing.RoutingService; +import no.entur.uttu.stopplace.spi.StopPlaceRegistry; +import org.rutebanken.netex.model.Quay; +import org.rutebanken.netex.model.StopPlace; +import org.springframework.stereotype.Service; + +@Service("routingFetcher") +public class RoutingFetcher implements DataFetcher { + + private final RoutingService routingService; + private final StopPlaceRegistry stopPlaceRegistry; + + public RoutingFetcher( + RoutingService routingService, + StopPlaceRegistry stopPlaceRegistry + ) { + this.routingService = routingService; + this.stopPlaceRegistry = stopPlaceRegistry; + } + + @Override + public ServiceLink get(DataFetchingEnvironment environment) { + String quayRefFrom = environment.getArgument("quayRefFrom"); + String quayRefTo = environment.getArgument("quayRefTo"); + Quay quayFrom = getQuay(quayRefFrom); + Quay quayTo = getQuay(quayRefTo); + + if (quayFrom == null || quayTo == null) { + return new ServiceLink(quayRefFrom + "_" + quayRefTo, null, null, null); + } + + RouteGeometry routeGeometry = routingService.getRouteGeometry( + quayFrom.getCentroid().getLocation().getLongitude(), + quayFrom.getCentroid().getLocation().getLatitude(), + quayTo.getCentroid().getLocation().getLongitude(), + quayTo.getCentroid().getLocation().getLatitude() + ); + + return new ServiceLink( + quayRefFrom + "_" + quayRefTo, + quayRefFrom, + quayRefTo, + routeGeometry + ); + } + + Quay getQuay(String quayRef) { + if (quayRef == null) { + return null; + } + Optional stopPlaceOptional = stopPlaceRegistry.getStopPlaceByQuayRef( + quayRef + ); + if (stopPlaceOptional.isEmpty()) { + return null; + } + StopPlace stopPlaceFrom = stopPlaceOptional.get(); + List stopPlaceFromQuays = stopPlaceFrom + .getQuays() + .getQuayRefOrQuay() + .stream() + .map(jaxbElement -> (org.rutebanken.netex.model.Quay) jaxbElement.getValue()) + .toList(); + return stopPlaceFromQuays + .stream() + .filter(quay -> quay.getId().equals(quayRef)) + .toList() + .get(0); + } +} diff --git a/src/main/java/no/entur/uttu/graphql/model/ServiceLink.java b/src/main/java/no/entur/uttu/graphql/model/ServiceLink.java new file mode 100644 index 00000000..753a7312 --- /dev/null +++ b/src/main/java/no/entur/uttu/graphql/model/ServiceLink.java @@ -0,0 +1,10 @@ +package no.entur.uttu.graphql.model; + +import no.entur.uttu.routing.RouteGeometry; + +public record ServiceLink( + String serviceLinkRef, + String quayRefFrom, + String quayRefTo, + RouteGeometry routeGeometry +) {} diff --git a/src/main/java/no/entur/uttu/routing/osrm/OsrmService.java b/src/main/java/no/entur/uttu/routing/osrm/OsrmService.java index accd121d..e7b7438a 100644 --- a/src/main/java/no/entur/uttu/routing/osrm/OsrmService.java +++ b/src/main/java/no/entur/uttu/routing/osrm/OsrmService.java @@ -57,14 +57,13 @@ public boolean isEnabled() { return osrmApiEndpoint != null && !osrmApiEndpoint.isBlank(); } - public RouteGeometry getRouteGeometry( + private MutableRequest getRoutingRequest( BigDecimal longitudeFrom, BigDecimal latitudeFrom, BigDecimal longitudeTo, BigDecimal latitudeTo ) { - List> routeCoordinates = new ArrayList<>(); - MutableRequest request = MutableRequest + return MutableRequest .GET( osrmApiEndpoint + "/route/v1/driving/" + @@ -78,6 +77,21 @@ public RouteGeometry getRouteGeometry( "?alternatives=false&steps=false&overview=full&geometries=geojson" ) .header("Content-Type", "application/json"); + } + + public RouteGeometry getRouteGeometry( + BigDecimal longitudeFrom, + BigDecimal latitudeFrom, + BigDecimal longitudeTo, + BigDecimal latitudeTo + ) { + List> routeCoordinates = new ArrayList<>(); + MutableRequest request = getRoutingRequest( + longitudeFrom, + latitudeFrom, + longitudeTo, + latitudeTo + ); try { HttpResponse response = httpClient.send( request,