Skip to content

Commit

Permalink
Parse all required fields and fields
Browse files Browse the repository at this point in the history
- Refactor entities into model package.
- Add stop times to trip and trips to routes.
  • Loading branch information
munterfi committed Apr 11, 2024
1 parent 3dc54d2 commit 70d8c1b
Show file tree
Hide file tree
Showing 17 changed files with 233 additions and 39 deletions.
8 changes: 0 additions & 8 deletions src/main/java/ch/naviqore/gtfs/schedule/Calendar.java

This file was deleted.

25 changes: 14 additions & 11 deletions src/main/java/ch/naviqore/gtfs/schedule/GtfsScheduleReader.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package ch.naviqore.gtfs.schedule;

import ch.naviqore.gtfs.schedule.model.GtfsSchedule;
import ch.naviqore.gtfs.schedule.model.GtfsScheduleBuilder;
import ch.naviqore.gtfs.schedule.type.ExceptionType;
import ch.naviqore.gtfs.schedule.type.RouteType;
import ch.naviqore.gtfs.schedule.type.ServiceDayTime;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -53,17 +58,10 @@ public class GtfsScheduleReader {
@RequiredArgsConstructor
@Getter
public enum GtfsFile {
AGENCY("agency.txt"),
CALENDAR_DATES("calendar_dates.txt"),
CALENDAR("calendar.txt"),
FARE_ATTRIBUTES("fare_attributes.txt"),
FARE_RULES("fare_rules.txt"),
FREQUENCIES("frequencies.txt"),
ROUTES("routes.txt"),
SHAPES("shapes.txt"),
STOP_TIMES("stop_times.txt"),
STOPS("stops.txt"),
TRIPS("trips.txt");
AGENCY("agency.txt"), CALENDAR_DATES("calendar_dates.txt"), CALENDAR("calendar.txt"), FARE_ATTRIBUTES(
"fare_attributes.txt"), FARE_RULES("fare_rules.txt"), FREQUENCIES("frequencies.txt"), ROUTES(
"routes.txt"), SHAPES("shapes.txt"), STOP_TIMES("stop_times.txt"), STOPS("stops.txt"), TRIPS(
"trips.txt");

private final String fileName;
}
Expand Down Expand Up @@ -117,6 +115,11 @@ private GtfsSchedule buildSchedule(Map<GtfsFile, List<CSVRecord>> records) {
for (CSVRecord record : records.get(GtfsFile.TRIPS)) {
builder.addTrip(record.get("trip_id"), record.get("route_id"), record.get("service_id"));
}
for (CSVRecord record : records.get(GtfsFile.STOP_TIMES)) {
builder.addStopTime(record.get("trip_id"), record.get("stop_id"),
ServiceDayTime.parse(record.get("arrival_time")),
ServiceDayTime.parse(record.get("departure_time")));
}
return builder.build();
}

Expand Down
4 changes: 0 additions & 4 deletions src/main/java/ch/naviqore/gtfs/schedule/Route.java

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/java/ch/naviqore/gtfs/schedule/Trip.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.model;

public record Agency(String agency, String name, String url, String timezone) {
}
45 changes: 45 additions & 0 deletions src/main/java/ch/naviqore/gtfs/schedule/model/Calendar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ch.naviqore.gtfs.schedule.model;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
@Getter
public final class Calendar {
private final String id;
private final EnumSet<DayOfWeek> serviceDays;
private final LocalDate startDate;
private final LocalDate endDate;
private final Map<LocalDate, CalendarDate> calendarDates = new HashMap<>();

void addCalendarDate(CalendarDate calendarDate) {
calendarDates.put(calendarDate.date(), calendarDate);
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Calendar) obj;
return Objects.equals(this.id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "Calendar[" + "id=" + id + ", " + "serviceDays=" + serviceDays + ", " + "startDate=" + startDate + ", " + "endDate=" + endDate + ']';
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.model;

import ch.naviqore.gtfs.schedule.type.ExceptionType;

import java.time.LocalDate;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.model;

import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.model;

import ch.naviqore.gtfs.schedule.type.ExceptionType;
import ch.naviqore.gtfs.schedule.type.RouteType;
import ch.naviqore.gtfs.schedule.type.ServiceDayTime;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
Expand Down Expand Up @@ -55,8 +58,7 @@ public GtfsScheduleBuilder addRoute(String id, String agencyId, String shortName
return this;
}

public GtfsScheduleBuilder addCalendar(String id, EnumSet<DayOfWeek> serviceDays, LocalDate startDate,
LocalDate endDate) {
public GtfsScheduleBuilder addCalendar(String id, EnumSet<DayOfWeek> serviceDays, LocalDate startDate, LocalDate endDate) {
if (calendars.containsKey(id)) {
throw new IllegalArgumentException("Calendar " + id + " already exists");
}
Expand All @@ -71,8 +73,8 @@ public GtfsScheduleBuilder addCalendarDate(String calendarId, LocalDate date, Ex
throw new IllegalArgumentException("Calendar " + calendarId + " does not exist");
}
log.debug("Adding calendar {}-{}", calendarId, date);
// TODO: Handle calendar dates
var calendarDate = new CalendarDate(calendar, date, type);
CalendarDate calendarDate = new CalendarDate(calendar, date, type);
calendar.addCalendarDate(calendarDate);
return this;
}

Expand All @@ -89,7 +91,25 @@ public GtfsScheduleBuilder addTrip(String id, String routeId, String serviceId)
throw new IllegalArgumentException("Calendar " + serviceId + " does not exist");
}
log.debug("Adding trip {}", id);
trips.put(id, new Trip(id, route, calendar));
Trip trip = new Trip(id, route, calendar);
route.addTrip(trip);
trips.put(id, trip);
return this;
}

public GtfsScheduleBuilder addStopTime(String tripId, String stopId, ServiceDayTime arrival, ServiceDayTime departure) {
Trip trip = trips.get(tripId);
if (trip == null) {
throw new IllegalArgumentException("Trip " + tripId + " does not exist");
}
Stop stop = stops.get(stopId);
if (stop == null) {
throw new IllegalArgumentException("Stop " + stopId + " does not exist");
}
log.debug("Adding stop {} to trip {} ({}-{})", stopId, tripId, arrival, departure);
StopTime stopTime = new StopTime(stop, trip, arrival, departure);
trip.addStopTime(stopTime);
// TODO: Add stop time to stop
return this;
}

Expand Down
44 changes: 44 additions & 0 deletions src/main/java/ch/naviqore/gtfs/schedule/model/Route.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ch.naviqore.gtfs.schedule.model;

import ch.naviqore.gtfs.schedule.type.RouteType;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
@Getter
public final class Route {
private final String id;
private final Agency agency;
private final String shortName;
private final String longName;
private final RouteType type;
private final List<Trip> trips = new ArrayList<>();

void addTrip(Trip trip) {
trips.add(trip);
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Route) obj;
return Objects.equals(this.id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "Route[" + "id=" + id + ", " + "agency=" + agency + ", " + "shortName=" + shortName + ", " + "longName=" + longName + ", " + "type=" + type + ']';
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.model;

public record Stop(String id, String name, double lat, double lon) {
}
6 changes: 6 additions & 0 deletions src/main/java/ch/naviqore/gtfs/schedule/model/StopTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ch.naviqore.gtfs.schedule.model;

import ch.naviqore.gtfs.schedule.type.ServiceDayTime;

public record StopTime(Stop stop, Trip trip, ServiceDayTime arrival, ServiceDayTime departure) {
}
45 changes: 45 additions & 0 deletions src/main/java/ch/naviqore/gtfs/schedule/model/Trip.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ch.naviqore.gtfs.schedule.model;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@RequiredArgsConstructor
@Getter
public final class Trip implements Comparable<Trip> {
private final String id;
private final Route route;
private final Calendar calendar;
private final List<StopTime> stopTimes = new ArrayList<>();

void addStopTime(StopTime stopTime) {
stopTimes.add(stopTime);
}

@Override
public int compareTo(Trip o) {
// TODO: Sort stopTimes, then return first stop.
return 0;
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Trip) obj;
return Objects.equals(this.id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "Trip[" + "id=" + id + ", " + "route=" + route + ", " + "calendar=" + calendar + ']';
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.type;

import lombok.AccessLevel;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.naviqore.gtfs.schedule;
package ch.naviqore.gtfs.schedule.type;

import lombok.AccessLevel;
import lombok.Getter;
Expand Down
44 changes: 44 additions & 0 deletions src/main/java/ch/naviqore/gtfs/schedule/type/ServiceDayTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ch.naviqore.gtfs.schedule.type;

import lombok.EqualsAndHashCode;
import lombok.Getter;


/**
* Service day time
* <p>
* A service day may end after 24:00:00 and times like 25:30:00 are possible values. java.time.LocalTime does not
* support this. Therefore, this time class is used to be able to cover service days bigger than 24 hours.
*
* @author munterfi
*/
@EqualsAndHashCode
@Getter
public class ServiceDayTime implements Comparable<ServiceDayTime> {
private final int totalSeconds;

public ServiceDayTime(int hours, int minutes, int seconds) {
this.totalSeconds = seconds + 60 * minutes + 3600 * hours;
}

public static ServiceDayTime parse(String timeString) {
String[] parts = timeString.split(":");
int hours = Integer.parseInt(parts[0]);
int minutes = Integer.parseInt(parts[1]);
int seconds = Integer.parseInt(parts[2]);
return new ServiceDayTime(hours, minutes, seconds);
}

@Override
public int compareTo(ServiceDayTime o) {
return Integer.compare(totalSeconds, o.totalSeconds);
}

@Override
public String toString() {
int hours = totalSeconds / 3600;
int minutes = (totalSeconds % 3600) / 60;
int seconds = totalSeconds % 60;
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.naviqore.gtfs.schedule;

import ch.naviqore.gtfs.schedule.model.GtfsSchedule;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
Expand Down

0 comments on commit 70d8c1b

Please sign in to comment.