aboutsummaryrefslogtreecommitdiff
path: root/gtfs-realtime-book/ch-06-consuming-service-alerts.md
diff options
context:
space:
mode:
Diffstat (limited to 'gtfs-realtime-book/ch-06-consuming-service-alerts.md')
-rw-r--r--gtfs-realtime-book/ch-06-consuming-service-alerts.md305
1 files changed, 305 insertions, 0 deletions
diff --git a/gtfs-realtime-book/ch-06-consuming-service-alerts.md b/gtfs-realtime-book/ch-06-consuming-service-alerts.md
new file mode 100644
index 0000000..9869173
--- /dev/null
+++ b/gtfs-realtime-book/ch-06-consuming-service-alerts.md
@@ -0,0 +1,305 @@
+## 6. Consuming Service Alerts
+
+The previous chapter introduced you to Protocol Buffers and showed you
+how load a remote GTFS-realtime feed into your Java project. This
+chapter will show you how to read the data from each of the three entity
+types (service alerts, vehicle positions and trip updates).
+
+The previous chapter also showed you how to loop over all entities in a
+feed using `getEntityList()`. Each entity contains either a service
+alert, a vehicle position or a trip update.
+
+Once you have verified that a `FeedEntity` element contains an alert,
+you can retrieve the corresponding `Alert` object using
+`getAlert()`.
+
+```java
+for (FeedEntity entity : fm.getEntityList()) {
+ if (entity.hasAlert()) {
+ Alert alert = entity.getAlert();
+
+ processAlert(alert);
+ }
+}
+```
+
+You can then access the specific properties of a service alert using the
+returned object.
+
+### Cause & Effect
+
+For example, to retrieve the cause value for the alert, you would first
+check for its presence with `hasCause()` then retrieve the value using
+`getCause()`.
+
+```java
+public void processAlert(Alert alert) {
+ if (alert.hasCause()) {
+ Cause cause = alert.getCause();
+
+ // ...
+ }
+
+ // ...
+}
+```
+
+The `Cause` object is an enumerator, meaning it has a finite number of
+possible values. To determine which value the object corresponds to,
+call `getNumber()` to compare it to the possible values.
+
+```java
+switch (cause.getNumber()) {
+ case Cause.ACCIDENT_VALUE:
+ // ...
+
+ case Cause.MEDICAL_EMERGENCY_VALUE:
+ // ...
+}
+```
+
+Note: There are other possible cause values to include in the switch
+statement; these have been omitted here as they are all covered in the
+specification earlier in this book.
+
+The `Effect` field works in the same way. The difference is that the
+possible list of values to compare against is different.
+
+```java
+if (alert.hasEffect()) {
+ Effect effect = alert.getEffect();
+
+ switch (effect.getNumber()) {
+ case Effect.DETOUR_VALUE:
+ // ...
+
+ case Effect.SIGNIFICANT_DELAYS_VALUE:
+ // ...
+ }
+}
+```
+
+### Title, Description and URL
+
+Each of these fields are of type `TranslatedString`. A
+`TranslatedString` may contain multiple `Translation` objects, so
+when processing these fields you must loop over the available
+translations.
+
+For example, to loop over the available translations for the header text
+you iterate over **getTranslationList()**.
+
+```java
+if (alert.hasHeaderText()) {
+ TranslatedString header = alert.getHeaderText();
+
+ for (Translation translation : header.getTranslationList()) {
+ // Process the translation here
+
+ }
+}
+```
+
+***Note:** To access the description you would use `hasDescription()` and
+`getDescription()`, while to access the URL you would use `hasUrl()` and
+`getUrl()`.*
+
+Alternatively, you can use `getTranslationCount()` and
+`getTranslation()` to retrieve each of the available translations.
+
+```java
+for (int i = 0; i < header.getTranslationCount(); i++) {
+ Translation translation = header.getTranslation(i);
+
+ // Process the translation here
+}
+```
+
+A `Translation` object is made up of text and optionally, its
+associated language. When dealing with the URL field, the text retrieved
+from `getText()` contains a full URL.
+
+```java
+if (translation.hasLanguage()) {
+ String language = translation.getLanguage();
+
+ if (language.equals("fr")) {
+ // Do something for French language
+ }
+ else {
+ // All other languages
+ }
+}
+
+if (translation.hasText()) {
+ String text = translation.getText();
+
+ // Do something with the text
+}
+```
+
+***Note:** Most GTFS-realtime feeds only specify text in a single
+language, and therefore do not include the language value.*
+
+### Active Period
+
+A service alert may contain zero or more time ranges, each of which
+specify the dates and times the alert is active for. If none are
+specified then the alert is active as long as it exists within the feed.
+
+You can access each of the `TimeRange` objects using either of the
+following methods:
+
+```java
+for (TimeRange timeRange : alert.getActivePeriodList()) {
+ // ...
+}
+
+for (int i = 0; i < alert.getActivePeriodCount(); i++) {
+ TimeRange timeRange = alert.getActivePeriod(i);
+
+ // ...
+}
+```
+
+A `TimeRange` can have either a start or finish date, or it may
+contain both. In Java, you can turn each of these dates into a
+`java.util.Date` object as shown below.
+
+```java
+if (timeRange.hasStart()) {
+ Date start = new Date(timeRange.getStart() * 1000);
+
+ // ...
+}
+
+if (timeRange.hasEnd()) {
+ Date end = new Date(timeRange.getEnd() * 1000);
+
+ // ...
+}
+```
+
+***Note:** The date value is multiplied by 1,000 because the date in the
+GTFS-realtime is represented by the number of seconds since January 1,
+1970, while `java.util.Date` is instantiated using the number of
+milliseconds since the same date.*
+
+### Affected Entities
+
+A service alert may contain zero or more affected entities, each of
+which describes a route, stop, agency, trip or route type. You can
+access these entities using either of the following methods:
+
+```
+for (EntitySelector entity : alert.getInformedEntityList()) {
+
+}
+
+for (int i = 0; i < alert.getInformedEntityCount(); i++) {
+ EntitySelector entity = alert.getInformedEntity(i);
+
+}
+```
+
+There are a number of properties available in the `EntitySelector`
+object, each of which can be used to match the entity to the
+corresponding GTFS feed.
+
+For example, if the `EntitySelector` object has a route ID value, then
+you should be able to locate the route in the corresponding GTFS feed's
+`routes.txt` file.
+
+The properties can be accessed as follows:
+
+```java
+if (entity.hasAgencyId()) {
+ String agencyId = entity.getAgencyId();
+
+}
+
+if (entity.hasRouteId()) {
+ String routeId = entity.getRouteId();
+
+}
+
+if (entity.hasRouteType()) {
+ int routeType = entity.getRouteType();
+
+}
+
+if (entity.hasStopId()) {
+ String stopId = entity.getStopId();
+
+}
+```
+
+The route type value is an Integer and if present must correspond either
+to the standard GTFS route type values, or to the extended route type
+values.
+
+The other entity information that can be contained in `EntitySelector`
+is trip information. You can access the trip properties as follows:
+
+```java
+if (entity.hasTrip()) {
+ TripDescriptor trip = entity.getTrip();
+
+ if (trip.hasTripId()) {
+ String tripId = trip.getTripId();
+
+ }
+
+ if (trip.hasRouteId()) {
+ String routeId = trip.getRouteId();
+
+ }
+
+ if (trip.hasStartDate()) {
+ String startDate = trip.getStartDate();
+
+ }
+
+ if (trip.hasStartTime()) {
+ String startTime = trip.getStartTime();
+
+ }
+
+ if (trip.hasScheduleRelationship()) {
+ ScheduleRelationship sr = trip.getScheduleRelationship();
+
+ }
+}
+```
+
+You can test the `ScheduleRelationship` value by comparing the
+`getNumber()` value to one of the available constants, as follows.
+
+```java
+if (entity.hasTrip()) {
+ // ...
+
+ if (trip.hasScheduleRelationship()) {
+
+ ScheduleRelationship sr = trip.getScheduleRelationship();
+
+ switch (sr.getNumber()) {
+ case ScheduleRelationship.ADDED_VALUE:
+ // ...
+ break;
+
+ case ScheduleRelationship.CANCELED_VALUE:
+ // ...
+ break;
+
+ case ScheduleRelationship.SCHEDULED_VALUE:
+ // ...
+ break;
+
+ case ScheduleRelationship.UNSCHEDULED_VALUE:
+ // ...
+ break;
+ }
+ }
+}
+```