Skip to content

Commit

Permalink
Merge pull request opentripplanner#6393 from leonardehrenfried/fix-tr…
Browse files Browse the repository at this point in the history
…ansmodel

Extract mapper for Transmodel `bookWhen`, new values for `relativeDirection`
  • Loading branch information
leonardehrenfried authored Jan 24, 2025
2 parents 12b5cb6 + 5639c31 commit cc2fe88
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.opentripplanner.apis.transmodel.mapping;

import org.opentripplanner.transit.model.timetable.booking.BookingInfo;
import org.opentripplanner.transit.model.timetable.booking.BookingTime;

/**
* Maps the {@link BookingInfo} to enum value (as a string) returned by the API.
*/
public class BookingInfoMapper {

public static String mapToBookWhen(BookingInfo bookingInfo) {
if (bookingInfo.getMinimumBookingNotice().isPresent()) {
return null;
}
BookingTime latestBookingTime = bookingInfo.getLatestBookingTime();
BookingTime earliestBookingTime = bookingInfo.getEarliestBookingTime();

// Try to deduce the original enum from stored values
if (earliestBookingTime == null) {
if (latestBookingTime == null) {
return "timeOfTravelOnly";
} else if (latestBookingTime.getDaysPrior() == 1) {
return "untilPreviousDay";
} else if (latestBookingTime.getDaysPrior() == 0) {
return "advanceAndDayOfTravel";
} else {
return "other";
}
} else if (
earliestBookingTime.getDaysPrior() == 0 &&
(latestBookingTime == null || latestBookingTime.getDaysPrior() == 0)
) {
return "dayOfTravelOnly";
} else {
return "other";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ public static RelativeDirection map(RelativeDirection relativeDirection) {
CIRCLE_COUNTERCLOCKWISE,
ELEVATOR,
UTURN_LEFT,
UTURN_RIGHT -> relativeDirection;
// for these the Transmodel API doesn't have a mapping. should it?
case ENTER_STATION,
UTURN_RIGHT,
ENTER_STATION,
EXIT_STATION,
ENTER_OR_EXIT_STATION,
FOLLOW_SIGNS -> RelativeDirection.CONTINUE;
FOLLOW_SIGNS -> relativeDirection;
// this type should never be exposed by an API
case ENTER_OR_EXIT_STATION -> RelativeDirection.CONTINUE;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ public class EnumTypes {
.value("elevator", RelativeDirection.ELEVATOR)
.value("uturnLeft", RelativeDirection.UTURN_LEFT)
.value("uturnRight", RelativeDirection.UTURN_RIGHT)
.value("enterStation", RelativeDirection.ENTER_STATION)
.value("exitStation", RelativeDirection.EXIT_STATION)
.value("followSigns", RelativeDirection.FOLLOW_SIGNS)
.build();

public static final GraphQLEnumType REPORT_TYPE = GraphQLEnumType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import graphql.schema.GraphQLList;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLOutputType;
import org.opentripplanner.apis.transmodel.mapping.BookingInfoMapper;
import org.opentripplanner.apis.transmodel.model.EnumTypes;
import org.opentripplanner.apis.transmodel.model.framework.TransmodelScalars;
import org.opentripplanner.transit.model.organization.ContactInfo;
Expand Down Expand Up @@ -107,34 +108,7 @@ public static GraphQLObjectType create() {
.name("bookWhen")
.description("Time constraints for booking")
.type(EnumTypes.PURCHASE_WHEN)
.dataFetcher(environment -> {
BookingInfo bookingInfo = bookingInfo(environment);
if (bookingInfo.getMinimumBookingNotice().isPresent()) {
return null;
}
BookingTime latestBookingTime = bookingInfo.getLatestBookingTime();
BookingTime earliestBookingTime = bookingInfo.getEarliestBookingTime();

// Try to deduce the original enum from stored values
if (earliestBookingTime == null) {
if (latestBookingTime == null) {
return "timeOfTravelOnly";
} else if (latestBookingTime.getDaysPrior() == 1) {
return "untilPreviousDay";
} else if (latestBookingTime.getDaysPrior() == 0) {
return "advanceAndDayOfTravel";
} else {
return "other";
}
} else if (
earliestBookingTime.getDaysPrior() == 0 &&
(latestBookingTime == null || latestBookingTime.getDaysPrior() == 0)
) {
return "dayOfTravelOnly";
} else {
return "other";
}
})
.dataFetcher(environment -> BookingInfoMapper.mapToBookWhen(bookingInfo(environment)))
.build()
)
.field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,9 @@ enum RelativeDirection {
continue
depart
elevator
enterStation
exitStation
followSigns
hardLeft
hardRight
left
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.opentripplanner.apis.transmodel.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.opentripplanner.apis.transmodel.mapping.BookingInfoMapper.mapToBookWhen;

import java.time.Duration;
import java.time.LocalTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.opentripplanner.transit.model.timetable.booking.BookingInfo;
import org.opentripplanner.transit.model.timetable.booking.BookingTime;

class BookingInfoMapperTest {

private static final Duration TEN_MINUTES = Duration.ofMinutes(10);
private static final BookingTime BOOKING_TIME_ZERO_DAYS_PRIOR = new BookingTime(
LocalTime.of(10, 0),
0
);

@Test
void bookingNotice() {
assertNull(mapToBookWhen(BookingInfo.of().withMinimumBookingNotice(TEN_MINUTES).build()));
}

@Test
void timeOfTravelOnly() {
assertEquals("timeOfTravelOnly", mapToBookWhen(BookingInfo.of().build()));
}

@Test
void untilPreviousDay() {
var info = daysPrior(1);
assertEquals("untilPreviousDay", mapToBookWhen(info));
}

@Test
void advanceAndDayOfTravel() {
var info = daysPrior(0);
assertEquals("advanceAndDayOfTravel", mapToBookWhen(info));
}

@ParameterizedTest
@ValueSource(ints = { 2, 3, 4, 14, 28 })
void other(int days) {
var info = daysPrior(days);
assertEquals("other", mapToBookWhen(info));
}

@Test
void dayOfTravelOnly() {
var info = BookingInfo.of().withEarliestBookingTime(BOOKING_TIME_ZERO_DAYS_PRIOR).build();
assertEquals("dayOfTravelOnly", mapToBookWhen(info));
}

@Test
void latestBookingTime() {
var info = BookingInfo
.of()
.withEarliestBookingTime(BOOKING_TIME_ZERO_DAYS_PRIOR)
.withLatestBookingTime(BOOKING_TIME_ZERO_DAYS_PRIOR)
.build();
assertEquals("dayOfTravelOnly", mapToBookWhen(info));
}

@Test
void earliestBookingTimeZero() {
var info = BookingInfo
.of()
.withEarliestBookingTime(new BookingTime(LocalTime.of(10, 0), 10))
.build();
assertEquals("other", mapToBookWhen(info));
}

private static BookingInfo daysPrior(int daysPrior) {
return BookingInfo
.of()
.withLatestBookingTime(new BookingTime(LocalTime.of(10, 0), daysPrior))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.opentripplanner.apis.transmodel.model;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -93,7 +94,7 @@ void serializeRelativeDirection(RelativeDirection direction) {
Locale.ENGLISH
);
assertInstanceOf(String.class, value);
assertNotNull(value);
assertFalse(((String) value).isEmpty());
}

@Test
Expand Down

0 comments on commit cc2fe88

Please sign in to comment.