Skip to content

Commit

Permalink
Merge pull request #261 from ibi-group/feature/otp-1392-download-plan…
Browse files Browse the repository at this point in the history
…-query

Download plan query from resource URI
  • Loading branch information
br648 authored Oct 16, 2024
2 parents 4e1b6b5 + e203492 commit da14ab3
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 284 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ The special E2E client settings should be defined in `env.yml`:
| OTP_TIMEZONE | string | Required | America/Los_Angeles | The timezone identifier that OTP is using to parse dates and times. OTP will use the timezone identifier that it finds in the first available agency to parse dates and times. |
| OTP_UI_NAME | string | Optional | Trip Planner | Config setting for linking to the OTP UI (trip planner). |
| OTP_UI_URL | string | Optional | https://plan.example.com | Config setting for linking to the OTP UI (trip planner). |
| PLAN_QUERY_RESOURCE_URI | string | Optional | https://plan.resource.com | Resource location of bespoke plan query. |
| PUSH_API_KEY | string | Optional | your-api-key | Key for Mobile Team push notifications internal API. |
| PUSH_API_URL | string | Optional | https://example.com/api/otp_push/sound_transit | URL for Mobile Team push notifications internal API. |
| SERVICE_DAY_START_HOUR | integer | Optional | 3 | Optional parameter for the hour (local time, 24-hr format) at which a service day starts. To make the service day change at 2am, enter 2. The default is 3am. |
Expand Down
5 changes: 4 additions & 1 deletion configurations/default/env.yml.tmp
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,7 @@ TRIP_INSTRUCTION_UPCOMING_RADIUS: 10

US_RIDE_GWINNETT_BUS_OPERATOR_NOTIFIER_API_URL: https://bus.notifier.example.com
US_RIDE_GWINNETT_BUS_OPERATOR_NOTIFIER_API_KEY: your-key
US_RIDE_GWINNETT_BUS_OPERATOR_NOTIFIER_QUALIFYING_ROUTES: agency_id:route_id
US_RIDE_GWINNETT_BUS_OPERATOR_NOTIFIER_QUALIFYING_ROUTES: agency_id:route_id

# The location for an OTP plan query request.
PLAN_QUERY_RESOURCE_URI: https://plan.resource.com
5 changes: 4 additions & 1 deletion configurations/test/env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ TRIP_TRACKING_RAIL_BOUNDARY: 200
TRIP_INSTRUCTION_IMMEDIATE_PREFIX_DISTANCE: 2
TRIP_INSTRUCTION_UPCOMING_PREFIX_DISTANCE: 10

VALIDATE_ENVIRONMENT_CONFIG: false
VALIDATE_ENVIRONMENT_CONFIG: false

# The location for an OTP plan query request.
PLAN_QUERY_RESOURCE_URI: https://raw.githubusercontent.com/ibi-group/open-source-configurations/main/atlanta/arc/planQuery.graphql
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.opentripplanner.middleware.models;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.io.Serializable;
Expand Down Expand Up @@ -53,7 +52,6 @@ public enum VisionLimitation {
* the Georgia Tech Mobility Profile Configuration / Logical Flow document,
* so that the mode is constructed based on specific strings in a specific
* order. The device strings are expected to change on occasion.
* @param mobilityProfile consulted to construct and update mobility mode
*/
public void updateMobilityMode() {
// Variable names and the strings we parse are from Georgia Tech document, to facilitate syncing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public OtpGraphQLVariables clone() {
clone.carReluctance = carReluctance;
clone.date = date;
clone.fromPlace = fromPlace;
clone.mobilityProfile = mobilityProfile;
if (modes != null) {
clone.modes = List.copyOf(modes);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,75 @@
package org.opentripplanner.middleware.utils;

import org.eclipse.jetty.http.HttpMethod;
import org.opentripplanner.middleware.bugsnag.BugsnagReporter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;

import static org.opentripplanner.middleware.utils.ConfigUtils.getConfigPropertyAsText;

public class GraphQLUtils {

private GraphQLUtils() {
throw new IllegalStateException("Utility class.");
}

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

// Lazily-initialized in getPlanQueryTemplate()
private static String planQueryTemplate = null;

/**
* Location of the GraphQL plan query template file, as Java resource.
* Location of the GraphQL default plan query template file, as URI resource.
*/
public static final String PLAN_QUERY_RESOURCE = "queries/planQuery.graphql";
private static final String DEFAULT_PLAN_QUERY_RESOURCE_URI =
"https://raw.githubusercontent.com/opentripplanner/otp-ui/refs/heads/master/packages/core-utils/src/planQuery.graphql";

/**
* Return the full GraphQL plan file planQueryTemplate in Java string format, with {@code "} as {@code \"}
* Location of the GraphQL plan query template file, as URI resource.
*/
private static final String PLAN_QUERY_RESOURCE_URI =
getConfigPropertyAsText(
"PLAN_QUERY_RESOURCE_URI",
DEFAULT_PLAN_QUERY_RESOURCE_URI
);


/**
* Return the full GraphQL plan file planQueryTemplate.
*/
public static String getPlanQueryTemplate() {
if (GraphQLUtils.planQueryTemplate == null) {
GraphQLUtils.planQueryTemplate = planQueryTemplateAsString(PLAN_QUERY_RESOURCE);
}
GraphQLUtils.planQueryTemplate = planQueryTemplateAsString();
}
return GraphQLUtils.planQueryTemplate;
}

/**
* Return a GraphQL planQueryTemplate in Java string format, with {@code "} as {@code \"}
* @param resource the plan file or any GraphQL file
* Return a GraphQL planQueryTemplate in Java string format, with {@code "} as {@code \"}.
*/
static String planQueryTemplateAsString(String resource) {
StringBuilder builder = new StringBuilder();
try (var reader = new BufferedReader(new InputStreamReader(
GraphQLUtils.class.getClassLoader().getResourceAsStream(resource)
))) {
int value;
// All this low-level stuff is just to put a \ in front of " in the string.
while ((value = reader.read()) != -1) {
char c = (char)value;
if (c == '\n') builder.append("\\n");
else if (c == '"') builder.append("\\\"");
else builder.append(c);
}
} catch (Exception e) {
LOG.error("Can't find \"{}\" resource.", resource, e);
static String planQueryTemplateAsString() {
String rawPlanQuery = getPlanQueryFromResource();
if (rawPlanQuery == null) {
String message = String.format("Unable to retrieve plan query from resource: %s.", GraphQLUtils.PLAN_QUERY_RESOURCE_URI);
LOG.error(message);
throw new IllegalStateException(message);
}
return builder.toString();
return rawPlanQuery.replace("\"", "\\\"");
}

/**
* Download the plan query from resource URI.
*/
static String getPlanQueryFromResource() {
HttpResponseValues httpResponseValues = HttpUtils.httpRequestRawResponse(
URI.create(GraphQLUtils.PLAN_QUERY_RESOURCE_URI),
10,
HttpMethod.GET,
null,
null
);
return httpResponseValues != null ? httpResponseValues.responseBody : null;
}
}
}
5 changes: 5 additions & 0 deletions src/main/resources/env.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@
"examples": ["https://plan.example.com"],
"description": "Config setting for linking to the OTP UI (trip planner)."
},
"PLAN_QUERY_RESOURCE_URI": {
"type": "string",
"examples": ["https://plan.resource.com"],
"description": "Resource location of bespoke plan query."
},
"PUSH_API_KEY": {
"type": "string",
"examples": ["your-api-key"],
Expand Down
Loading

0 comments on commit da14ab3

Please sign in to comment.