Java tutorial
/** * Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org> * * 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.onebusaway.webapp.actions.where; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; import org.onebusaway.collections.tuple.T2; import org.onebusaway.collections.tuple.Tuples; import org.onebusaway.exceptions.NoSuchStopServiceException; import org.onebusaway.transit_data.model.StopCalendarDayBean; import org.onebusaway.transit_data.model.StopCalendarDaysBean; import org.onebusaway.transit_data.model.StopRouteDirectionScheduleBean; import org.onebusaway.transit_data.model.StopRouteScheduleBean; import org.onebusaway.transit_data.model.StopScheduleBean; import org.onebusaway.transit_data.model.StopTimeInstanceBean; import org.onebusaway.transit_data.model.schedule.FrequencyInstanceBean; import org.onebusaway.transit_data.services.TransitDataService; import org.onebusaway.utility.DateLibrary; import org.springframework.beans.factory.annotation.Autowired; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.conversion.annotations.Conversion; import com.opensymphony.xwork2.conversion.annotations.TypeConversion; @Conversion public class ScheduleAction extends ActionSupport { private static final long serialVersionUID = 1L; private static final StopCalendarDayAdapter _stopCalendarDayAdapter = new StopCalendarDayAdapter(); private final StopTimeAdapter _stopTimeAdapter = new StopTimeAdapter(); @Autowired private TransitDataService _service; private String _id; private Date _date; private StopScheduleBean _result; private TimeZone _timeZone; private boolean _showArrivals = false; public void setId(String id) { _id = id; } @TypeConversion(converter = "org.onebusaway.webapp.actions.where.ScheduleByStopDateConverter") public void setDate(Date date) { _date = date; } public void setShowArrivals(boolean showArrivals) { _showArrivals = showArrivals; } public boolean isShowArrivals() { return _showArrivals; } public StopScheduleBean getResult() { return _result; } public TimeZone getTimeZone() { return _timeZone; } @Override @Actions({ @Action(value = "/where/standard/schedule") }) public String execute() throws Exception { if (_date == null) _date = new Date(); if (_id == null) return INPUT; _result = _service.getScheduleForStop(_id, _date); if (_result == null) throw new NoSuchStopServiceException(_id); StopCalendarDaysBean days = _result.getCalendarDays(); String tzName = days.getTimeZone(); _timeZone = TimeZone.getTimeZone(tzName); if (_timeZone == null) _timeZone = TimeZone.getDefault(); filterResults(); return SUCCESS; } public boolean isAmPmClock() { return DateLibrary.hasAmPmClock(getLocale()); } public List<String> getShortWeekDays() { List<String> result = new ArrayList<String>(); DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(getLocale()); String shortWeekdays[] = dateFormatSymbols.getShortWeekdays(); Calendar calendar = Calendar.getInstance(getLocale()); int firstDayOfWeek = calendar.getFirstDayOfWeek(); for (int dayOfWeek = firstDayOfWeek; dayOfWeek < shortWeekdays.length; dayOfWeek++) { result.add(shortWeekdays[dayOfWeek]); } for (int dayOfWeek = Calendar.SUNDAY; dayOfWeek < firstDayOfWeek; dayOfWeek++) { result.add(shortWeekdays[dayOfWeek]); } return result; } public <T> List<List<T>> getRows(List<T> elements, int rowLength) { List<List<T>> rows = new ArrayList<List<T>>(); List<T> row = new ArrayList<T>(); for (T element : elements) { row.add(element); if (row.size() == rowLength) { rows.add(row); row = new ArrayList<T>(); } } if (!row.isEmpty()) rows.add(row); return rows; } /**** * * @param stopTimes * @param format * @return ****/ public List<T2<String, List<StopTimeInstanceBean>>> getStopTimesByFormatKey( List<StopTimeInstanceBean> stopTimes, String format) { return getTimesByFormatKey(stopTimes, format, _stopTimeAdapter); } public List<T2<String, List<StopCalendarDayBean>>> getStopCalendarDaysByFormatKey( List<StopCalendarDayBean> stopCalendarDays, String format) { return getTimesByFormatKey(stopCalendarDays, format, _stopCalendarDayAdapter); } public List<StopCalendarDayBean> getStopCalendarDaysByFormatKeyAndValue( List<StopCalendarDayBean> stopCalendarDays, String format, String value) { return getTimesByFormatKeyAndValue(stopCalendarDays, format, value, _stopCalendarDayAdapter); } public String getFrequencyCellHeight(FrequencyInstanceBean bean) { int hours = (int) Math.round((bean.getEndTime() - bean.getStartTime()) / (60.0 * 60 * 1000)); if (hours == 0) hours = 1; return hours + "em"; } /**** * ****/ private void filterResults() { List<StopRouteScheduleBean> routes = _result.getRoutes(); List<StopRouteScheduleBean> filteredRoutes = new ArrayList<StopRouteScheduleBean>(routes.size()); for (StopRouteScheduleBean route : routes) { List<StopRouteDirectionScheduleBean> directions = route.getDirections(); List<StopRouteDirectionScheduleBean> filteredDirections = new ArrayList<StopRouteDirectionScheduleBean>( directions.size()); for (StopRouteDirectionScheduleBean direction : directions) { List<StopTimeInstanceBean> filteredStopTimes = getFilteredStopTimes(direction); List<FrequencyInstanceBean> filteredFrequencies = getFilteredFrequencies(direction); if (!(filteredStopTimes.isEmpty() && filteredFrequencies.isEmpty())) { direction.setStopTimes(filteredStopTimes); direction.setFrequencies(filteredFrequencies); filteredDirections.add(direction); } } if (!filteredDirections.isEmpty()) { route.setDirections(filteredDirections); filteredRoutes.add(route); } } _result.setRoutes(filteredRoutes); } private List<StopTimeInstanceBean> getFilteredStopTimes(StopRouteDirectionScheduleBean direction) { List<StopTimeInstanceBean> stopTimes = direction.getStopTimes(); List<StopTimeInstanceBean> filteredStopTimes = new ArrayList<StopTimeInstanceBean>(stopTimes.size()); for (StopTimeInstanceBean stopTime : stopTimes) { if ((_showArrivals && stopTime.isArrivalEnabled()) || (!_showArrivals && stopTime.isDepartureEnabled())) filteredStopTimes.add(stopTime); } return filteredStopTimes; } private List<FrequencyInstanceBean> getFilteredFrequencies(StopRouteDirectionScheduleBean direction) { List<FrequencyInstanceBean> frequencies = direction.getFrequencies(); List<FrequencyInstanceBean> filteredFrequencies = new ArrayList<FrequencyInstanceBean>(frequencies.size()); for (FrequencyInstanceBean frequency : frequencies) { if ((_showArrivals && frequency.isArrivalEnabled()) || (!_showArrivals && frequency.isDepartureEnabled())) filteredFrequencies.add(frequency); } return filteredFrequencies; } public Date getShiftedDate(Date date) { return getShiftedDateStatic(date); } public String getFormattedDate(String format, Date date) { SimpleDateFormat df = new SimpleDateFormat(format); df.setTimeZone(_timeZone); return df.format(date); } /**** * Private Methods ****/ private static interface IAdapter<FROM, TO> { public TO adapt(FROM source); } private static Date getShiftedDateStatic(Date date) { Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.HOUR_OF_DAY, 12); return c.getTime(); } private <T> List<T> getTimesByFormatKeyAndValue(List<T> times, String format, String value, IAdapter<T, Date> adapter) { SimpleDateFormat df = new SimpleDateFormat(format, getLocale()); df.setTimeZone(_timeZone); List<T> results = new ArrayList<T>(); for (T time : times) { Date date = adapter.adapt(time); String v = df.format(date); if (v.equals(value)) results.add(time); } return results; } private <T> List<T2<String, List<T>>> getTimesByFormatKey(List<T> stopTimes, String format, IAdapter<T, Date> adapter) { SimpleDateFormat df = new SimpleDateFormat(format); df.setTimeZone(_timeZone); List<T2<String, List<T>>> tuples = new ArrayList<T2<String, List<T>>>(); T2<String, List<T>> tuple = null; for (T bean : stopTimes) { Date date = adapter.adapt(bean); String key = df.format(date); if (tuple == null || !tuple.getFirst().equals(key)) { if (tuple != null && !tuple.getSecond().isEmpty()) tuples.add(tuple); List<T> beans = new ArrayList<T>(); tuple = Tuples.tuple(key, beans); } tuple.getSecond().add(bean); } if (tuple != null && !tuple.getSecond().isEmpty()) tuples.add(tuple); return tuples; } private class StopTimeAdapter implements IAdapter<StopTimeInstanceBean, Date> { public Date adapt(StopTimeInstanceBean source) { return new Date(_showArrivals ? source.getArrivalTime() : source.getDepartureTime()); } } private static class StopCalendarDayAdapter implements IAdapter<StopCalendarDayBean, Date> { public Date adapt(StopCalendarDayBean source) { Date date = source.getDate(); return getShiftedDateStatic(date); } } }