All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.calendar.impl.CalendarServiceDataFactoryImpl Maven / Gradle / Ivy

There is a newer version: 2.6.0
Show newest version
/**
 * Copyright (C) 2011 Brian Ferris 
 * Copyright (C) 2012 Google, Inc.
 * Copyright (C) 2013 Codemass, Inc. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.opentripplanner.calendar.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import org.onebusaway.gtfs.impl.calendar.CalendarServiceImpl;
import org.onebusaway.gtfs.impl.calendar.UnknownAgencyTimezoneException;
import org.onebusaway.gtfs.model.Agency;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.ServiceCalendar;
import org.onebusaway.gtfs.model.ServiceCalendarDate;
import org.onebusaway.gtfs.model.calendar.CalendarServiceData;
import org.onebusaway.gtfs.model.calendar.LocalizedServiceId;
import org.onebusaway.gtfs.model.calendar.ServiceDate;
import org.onebusaway.gtfs.services.GtfsRelationalDao;
import org.onebusaway.gtfs.services.calendar.CalendarService;
import org.onebusaway.gtfs.services.calendar.CalendarServiceDataFactory;
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 implements
    CalendarServiceDataFactory {

  private final Logger _log = LoggerFactory.getLogger(CalendarServiceDataFactoryImpl.class);

  private GtfsRelationalDao _dao;

  private int _excludeFutureServiceDatesInDays;

  public static CalendarService createService(GtfsRelationalDao dao) {
    CalendarServiceDataFactoryImpl factory = new CalendarServiceDataFactoryImpl(
        dao);
    return new CalendarServiceImpl(factory.createData());
  }

  public CalendarServiceDataFactoryImpl() {

  }

  public CalendarServiceDataFactoryImpl(GtfsRelationalDao dao) {
    _dao = dao;
  }

  public void setGtfsDao(GtfsRelationalDao dao) {
    _dao = dao;
  }

  public void setExcludeFutureServiceDatesInDays(
      int excludeFutureServiceDatesInDays) {
    _excludeFutureServiceDatesInDays = excludeFutureServiceDatesInDays;
  }

  @Override
  public CalendarServiceData createData() {

    CalendarServiceData data = new CalendarServiceData();

    setTimeZonesForAgencies(data);

    List serviceIds = _dao.getAllServiceIds();

    int index = 0;

    for (AgencyAndId serviceId : serviceIds) {

      index++;

      _log.debug("serviceId=" + serviceId + " (" + index + "/"
          + serviceIds.size() + ")");

      TimeZone serviceIdTimeZone = data.getTimeZoneForAgencyId(serviceId.getAgencyId());
      if (serviceIdTimeZone == null) {
        serviceIdTimeZone = TimeZone.getDefault();
      }

      Set activeDates = getServiceDatesForServiceId(serviceId,
          serviceIdTimeZone);

      List serviceDates = new ArrayList(activeDates);
      Collections.sort(serviceDates);

      data.putServiceDatesForServiceId(serviceId, serviceDates);

//      List tripAgencyIds = _dao.getTripAgencyIdsReferencingServiceId(serviceId);

//      Set timeZones = new HashSet();
//      for (String tripAgencyId : tripAgencyIds) {
//        TimeZone timeZone = data.getTimeZoneForAgencyId(tripAgencyId);
//        timeZones.add(timeZone);
//      }

//      for (TimeZone timeZone : timeZones) {
//
//        List dates = new ArrayList(serviceDates.size());
//        for (ServiceDate serviceDate : serviceDates)
//          dates.add(serviceDate.getAsDate(timeZone));
//
//        LocalizedServiceId id = new LocalizedServiceId(serviceId, timeZone);
//        data.putDatesForLocalizedServiceId(id, dates);
//      }
    }

    return data;
  }

  public Set getServiceDatesForServiceId(AgencyAndId serviceId,
      TimeZone serviceIdTimeZone) {
    Set activeDates = new HashSet();
    ServiceCalendar c = _dao.getCalendarForServiceId(serviceId);

    if (c != null) {
      addDatesFromCalendar(c, serviceIdTimeZone, activeDates);
    }
    for (ServiceCalendarDate cd : _dao.getCalendarDatesForServiceId(serviceId)) {
      addAndRemoveDatesFromCalendarDate(cd, serviceIdTimeZone, activeDates);
    }
    return activeDates;
  }

  private void setTimeZonesForAgencies(CalendarServiceData data) {
    for (Agency agency : _dao.getAllAgencies()) {
      TimeZone timeZone = TimeZone.getTimeZone(agency.getTimezone());
      if (timeZone.getID().equals("GMT")
          && !agency.getTimezone().toUpperCase().equals("GMT")) {
        throw new UnknownAgencyTimezoneException(agency.getName(),
            agency.getTimezone());
      }
      data.putTimeZoneForAgencyId(agency.getId(), timeZone);
    }
  }

  private void addDatesFromCalendar(ServiceCalendar calendar,
      TimeZone timeZone, Set activeDates) {

    /**
     * We calculate service dates relative to noon so as to avoid any weirdness
     * relative to DST.
     */
    Date startDate = getServiceDateAsNoon(calendar.getStartDate(), timeZone);
    Date endDate = getServiceDateAsNoon(calendar.getEndDate(), timeZone);

    java.util.Calendar c = java.util.Calendar.getInstance(timeZone);
    c.setTime(startDate);

    while (true) {
      Date date = c.getTime();
      if (date.after(endDate))
        break;

      int day = c.get(java.util.Calendar.DAY_OF_WEEK);
      boolean active = false;

      switch (day) {
        case java.util.Calendar.MONDAY:
          active = calendar.getMonday() == 1;
          break;
        case java.util.Calendar.TUESDAY:
          active = calendar.getTuesday() == 1;
          break;
        case java.util.Calendar.WEDNESDAY:
          active = calendar.getWednesday() == 1;
          break;
        case java.util.Calendar.THURSDAY:
          active = calendar.getThursday() == 1;
          break;
        case java.util.Calendar.FRIDAY:
          active = calendar.getFriday() == 1;
          break;
        case java.util.Calendar.SATURDAY:
          active = calendar.getSaturday() == 1;
          break;
        case java.util.Calendar.SUNDAY:
          active = calendar.getSunday() == 1;
          break;
      }

      if (active) {
        addServiceDate(activeDates, new ServiceDate(c), timeZone);
      }

      c.add(java.util.Calendar.DAY_OF_YEAR, 1);
    }
  }

  private void addAndRemoveDatesFromCalendarDate(
      ServiceCalendarDate calendarDate, TimeZone serviceIdTimeZone,
      Set activeDates) {

    ServiceDate serviceDate = calendarDate.getDate();
    Date targetDate = calendarDate.getDate().getAsDate();
    Calendar c = Calendar.getInstance();
    c.setTime(targetDate);

    switch (calendarDate.getExceptionType()) {
      case ServiceCalendarDate.EXCEPTION_TYPE_ADD:
        addServiceDate(activeDates, serviceDate, serviceIdTimeZone);
        break;
      case ServiceCalendarDate.EXCEPTION_TYPE_REMOVE:
        activeDates.remove(serviceDate);
        break;
      default:
        _log.warn("unknown CalendarDate exception type: "
            + calendarDate.getExceptionType());
        break;
    }
  }

  private void addServiceDate(Set activeDates,
      ServiceDate serviceDate, TimeZone timeZone) {
    if (_excludeFutureServiceDatesInDays > 0) {
      int days = (int) ((serviceDate.getAsDate().getTime() - System.currentTimeMillis()) / (24 * 60 * 60 * 1000));
      if (days > _excludeFutureServiceDatesInDays)
        return;
    }

    activeDates.add(new ServiceDate(serviceDate));
  }

  private static Date getServiceDateAsNoon(ServiceDate serviceDate,
      TimeZone timeZone) {
    Calendar c = serviceDate.getAsCalendar(timeZone);
    c.add(Calendar.HOUR_OF_DAY, 12);
    return c.getTime();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy