org.opentripplanner.model.calendar.impl.CalendarServiceDataFactoryImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
/* This file is based on code copied from project OneBusAway, see the LICENSE file for further information. */
package org.opentripplanner.model.calendar.impl;
import static java.util.stream.Collectors.groupingBy;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opentripplanner.model.calendar.CalendarServiceData;
import org.opentripplanner.model.calendar.ServiceCalendar;
import org.opentripplanner.model.calendar.ServiceCalendarDate;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* We perform initial date calculations in the timezone of the host jvm, which may be different than
* the timezone of an agency with the specified service id. To my knowledge, the calculation should
* work the same, which is to say I can't immediately think of any cases where the service dates
* would be computed incorrectly.
*
* @author bdferris
*/
public class CalendarServiceDataFactoryImpl {
private static final Logger LOG = LoggerFactory.getLogger(CalendarServiceDataFactoryImpl.class);
private final Map> calendarDatesByServiceId;
private final Map> calendarsByServiceId;
private final Set serviceIds;
private CalendarServiceDataFactoryImpl(
Collection calendarDates,
Collection serviceCalendars
) {
this.calendarDatesByServiceId =
calendarDates.stream().collect(groupingBy(ServiceCalendarDate::getServiceId));
this.calendarsByServiceId =
serviceCalendars.stream().collect(groupingBy(ServiceCalendar::getServiceId));
this.serviceIds = merge(calendarDatesByServiceId.keySet(), calendarsByServiceId.keySet());
}
public static CalendarServiceData createCalendarServiceData(
Collection calendarDates,
Collection serviceCalendars
) {
return new CalendarServiceDataFactoryImpl(calendarDates, serviceCalendars).createData();
}
/** package local to be unit testable */
static Set merge(Collection set1, Collection set2) {
Set newSet = new HashSet<>();
newSet.addAll(set1);
newSet.addAll(set2);
return newSet;
}
private CalendarServiceData createData() {
CalendarServiceData data = new CalendarServiceData();
int index = 0;
for (FeedScopedId serviceId : serviceIds) {
index++;
LOG.debug("serviceId={} ({}/{})", serviceId, index, serviceIds.size());
Set activeDates = getServiceDatesForServiceId(serviceId);
List serviceDates = new ArrayList<>(activeDates);
Collections.sort(serviceDates);
data.putServiceDatesForServiceId(serviceId, serviceDates);
}
return data;
}
private Set getServiceDatesForServiceId(FeedScopedId serviceId) {
Set activeDates = new HashSet<>();
ServiceCalendar c = findCalendarForServiceId(serviceId);
if (c != null) {
addDatesFromCalendar(c, activeDates);
}
List dates = calendarDatesByServiceId.get(serviceId);
if (dates != null) {
for (ServiceCalendarDate cd : dates) {
addAndRemoveDatesFromCalendarDate(cd, activeDates);
}
}
return activeDates;
}
private ServiceCalendar findCalendarForServiceId(FeedScopedId serviceId) {
List calendars = calendarsByServiceId.get(serviceId);
if (calendars == null || calendars.isEmpty()) {
return null;
}
if (calendars.size() == 1) {
return calendars.get(0);
}
throw new MultipleCalendarsForServiceIdException(serviceId);
}
private void addDatesFromCalendar(ServiceCalendar calendar, Set activeDates) {
LocalDate startDate = calendar.getPeriod().getStart();
LocalDate endDate = calendar.getPeriod().getEnd();
for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
if (
switch (date.getDayOfWeek()) {
case MONDAY -> calendar.getMonday() == 1;
case TUESDAY -> calendar.getTuesday() == 1;
case WEDNESDAY -> calendar.getWednesday() == 1;
case THURSDAY -> calendar.getThursday() == 1;
case FRIDAY -> calendar.getFriday() == 1;
case SATURDAY -> calendar.getSaturday() == 1;
case SUNDAY -> calendar.getSunday() == 1;
}
) {
addServiceDate(activeDates, date);
}
}
}
private void addAndRemoveDatesFromCalendarDate(
ServiceCalendarDate calendarDate,
Set activeDates
) {
LocalDate serviceDate = calendarDate.getDate();
switch (calendarDate.getExceptionType()) {
case ServiceCalendarDate.EXCEPTION_TYPE_ADD -> addServiceDate(activeDates, serviceDate);
case ServiceCalendarDate.EXCEPTION_TYPE_REMOVE -> activeDates.remove(serviceDate);
default -> LOG.warn(
"unknown CalendarDate exception type: {}",
calendarDate.getExceptionType()
);
}
}
private void addServiceDate(Set activeDates, LocalDate serviceDate) {
activeDates.add(serviceDate);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy