/* * Copyright (c) 2014 Washington State Department of Transportation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * */ package gov.wa.wsdot.mobile.client.activities.amtrakcascades.schedules.details; import com.google.gwt.event.shared.EventBus; import com.google.gwt.jsonp.client.JsonpRequestBuilder; import com.google.gwt.place.shared.Place; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.googlecode.mgwt.mvp.client.MGWTAbstractActivity; import com.googlecode.mgwt.ui.client.widget.panel.pull.PullArrowStandardHandler; import com.googlecode.mgwt.ui.client.widget.panel.pull.PullArrowStandardHandler.PullActionHandler; import gov.wa.wsdot.mobile.client.ClientFactory; import gov.wa.wsdot.mobile.client.event.ActionEvent; import gov.wa.wsdot.mobile.client.event.ActionNames; import gov.wa.wsdot.mobile.client.plugins.accessibility.Accessibility; import gov.wa.wsdot.mobile.client.util.Consts; import gov.wa.wsdot.mobile.shared.AmtrakCascadesScheduleFeed; import gov.wa.wsdot.mobile.shared.AmtrakCascadesScheduleItem; import gov.wa.wsdot.mobile.shared.AmtrakCascadesServiceItem; import java.util.*; public class AmtrakCascadesSchedulesDetailsActivity extends MGWTAbstractActivity implements AmtrakCascadesSchedulesDetailsView.Presenter { private ClientFactory clientFactory; private AmtrakCascadesSchedulesDetailsView view; private EventBus eventBus; private String statusDate; private Accessibility accessibility; private static Map<String, AmtrakCascadesScheduleItem> stationItems; private static List<Map<String, AmtrakCascadesScheduleItem>> locationItems; private static List<AmtrakCascadesServiceItem> serviceItems = new ArrayList<AmtrakCascadesServiceItem>(); private static Map<Integer, String> trainNumberMap = new HashMap<Integer, String>(); private static Map<String, String> amtrakStations = new HashMap<String, String>(); private static final String AMTRAK_CASCADES_SCHEDULE_URL = Consts.HOST_URL + "/traveler/api/amtrakcascades/schedule"; public AmtrakCascadesSchedulesDetailsActivity(ClientFactory clientFactory) { this.clientFactory = clientFactory; } @Override public void start(AcceptsOneWidget panel, EventBus eventBus) { view = clientFactory.getAmtrakCascadesDeparturesView(); this.eventBus = eventBus; accessibility = clientFactory.getAccessibility(); view.setPresenter(this); final Place place = clientFactory.getPlaceController().getWhere(); getTrainNumbers(); getAmtrakStations(); view.getPullHeader().setHTML("pull down"); PullArrowStandardHandler headerHandler = new PullArrowStandardHandler( view.getPullHeader(), view.getPullPanel()); headerHandler.setErrorText("Error"); headerHandler.setLoadingText("Loading"); headerHandler.setNormalText("pull down"); headerHandler.setPulledText("release to load"); headerHandler.setPullActionHandler(new PullActionHandler() { @Override public void onPullAction(final AsyncCallback<Void> callback) { new Timer() { @Override public void run() { if (place instanceof AmtrakCascadesSchedulesDetailsPlace) { AmtrakCascadesSchedulesDetailsPlace amtrakCascadesSchedulesPlace = (AmtrakCascadesSchedulesDetailsPlace) place; statusDate = amtrakCascadesSchedulesPlace.getStatusDate(); String fromLocation = amtrakCascadesSchedulesPlace.getFromLocation(); String toLocation = amtrakCascadesSchedulesPlace.getToLocation(); createTopicsList(statusDate, fromLocation, toLocation); } view.refresh(); callback.onSuccess(null); } }.schedule(1); } }); if (place instanceof AmtrakCascadesSchedulesDetailsPlace) { AmtrakCascadesSchedulesDetailsPlace amtrakCascadesSchedulesPlace = (AmtrakCascadesSchedulesDetailsPlace) place; statusDate = amtrakCascadesSchedulesPlace.getStatusDate(); String fromLocation = amtrakCascadesSchedulesPlace.getFromLocation(); String toLocation = amtrakCascadesSchedulesPlace.getToLocation(); view.setHeaderPullHandler(headerHandler); createTopicsList(statusDate, fromLocation, toLocation); panel.setWidget(view); accessibility.postScreenChangeNotification(); } } private void getTrainNumbers() { trainNumberMap.put(7, "Empire Builder Train"); trainNumberMap.put(8, "Empire Builder Train"); trainNumberMap.put(11, "Coast Starlight Train"); trainNumberMap.put(14, "Coast Starlight Train"); trainNumberMap.put(27, "Empire Builder Train"); trainNumberMap.put(28, "Empire Builder Train"); trainNumberMap.put(500, "Amtrak Cascades Train"); trainNumberMap.put(501, "Amtrak Cascades Train"); trainNumberMap.put(502, "Amtrak Cascades Train"); trainNumberMap.put(503, "Amtrak Cascades Train"); trainNumberMap.put(504, "Amtrak Cascades Train"); trainNumberMap.put(505, "Amtrak Cascades Train"); trainNumberMap.put(506, "Amtrak Cascades Train"); trainNumberMap.put(507, "Amtrak Cascades Train"); trainNumberMap.put(508, "Amtrak Cascades Train"); trainNumberMap.put(509, "Amtrak Cascades Train"); trainNumberMap.put(510, "Amtrak Cascades Train"); trainNumberMap.put(511, "Amtrak Cascades Train"); trainNumberMap.put(513, "Amtrak Cascades Train"); trainNumberMap.put(516, "Amtrak Cascades Train"); trainNumberMap.put(517, "Amtrak Cascades Train"); } private void getAmtrakStations() { amtrakStations.put("VAC", "Vancouver, BC"); amtrakStations.put("BEL", "Bellingham, WA"); amtrakStations.put("MVW", "Mount Vernon, WA"); amtrakStations.put("STW", "Stanwood, WA"); amtrakStations.put("EVR", "Everett, WA"); amtrakStations.put("EDM", "Edmonds, WA"); amtrakStations.put("SEA", "Seattle, WA"); amtrakStations.put("TUK", "Tukwila, WA"); amtrakStations.put("TAC", "Tacoma, WA"); amtrakStations.put("OLW", "Olympia/Lacey, WA"); amtrakStations.put("CTL", "Centralia, WA"); amtrakStations.put("KEL", "Kelso/Longview, WA"); amtrakStations.put("VAN", "Vancouver, WA"); amtrakStations.put("PDX", "Portland, OR"); amtrakStations.put("ORC", "Oregon City, OR"); amtrakStations.put("SLM", "Salem, OR"); amtrakStations.put("ALY", "Albany, OR"); amtrakStations.put("EUG", "Eugene, OR"); } /** * Check URL parameters and decide which way we are accessing the API. * * @param scheduleDate date of requested schedule * @param fromLocation departing station name * @param toLocation arriving station name */ private void createTopicsList(String scheduleDate, final String fromLocation, final String toLocation) { String url = AMTRAK_CASCADES_SCHEDULE_URL + "/" + scheduleDate + "/-1/" + fromLocation + "/" + toLocation; view.showProgressIndicator(); if (!toLocation.equalsIgnoreCase("NA")) { getDepartingArrivingTrains(url, fromLocation, toLocation); } else { getDepartingTrains(url, fromLocation, toLocation); } } /** * Get train schedules for those with a departing and arriving station. * * @param url URL of the Web services API * @param toLocation arriving station name * @param fromLocation departing station name */ private void getDepartingArrivingTrains(String url, final String fromLocation, final String toLocation) { JsonpRequestBuilder jsonp = new JsonpRequestBuilder(); jsonp.setTimeout(30000); // Set timeout for 30 seconds jsonp.requestObject(url, new AsyncCallback<AmtrakCascadesScheduleFeed>() { @Override public void onFailure(Throwable caught) { view.hideProgressIndicator(); } @Override public void onSuccess(AmtrakCascadesScheduleFeed result) { if (result.getSchedule() != null) { serviceItems.clear(); AmtrakCascadesScheduleItem scheduleItem; int numItems = result.getSchedule().length(); int i = 0; int startingTripNumber = 0; int currentTripNumber = 0; while (i < numItems) { // Loop through all trains Date scheduledDepartureTime = null; locationItems = new ArrayList<Map<String, AmtrakCascadesScheduleItem>>(); stationItems = new HashMap<String, AmtrakCascadesScheduleItem>(); startingTripNumber = result.getSchedule().get(i).getTripNumber(); currentTripNumber = startingTripNumber; List<String> trainNameList = new ArrayList<String>(); int tripCounter = 0; while (currentTripNumber == startingTripNumber && i < numItems) { // Trains are grouped by two or more scheduleItem = new AmtrakCascadesScheduleItem(); if (result.getSchedule().get(i).getArrivalComment() != null) { scheduleItem.setArrivalComment(result .getSchedule().get(i) .getArrivalComment()); } if (result.getSchedule().get(i).getArrivalScheduleType() != null) { scheduleItem.setArrivalScheduleType(result .getSchedule() .get(i) .getArrivalScheduleType()); } if (result.getSchedule().get(i).getArrivalTime() != null) { scheduleItem.setArrivalTime(result .getSchedule().get(i) .getArrivalTime().toString() .substring(6, 19)); } if (result.getSchedule().get(i).getDepartureComment() != null) { scheduleItem.setDepartureComment(result .getSchedule().get(i) .getDepartureComment()); } if (result.getSchedule().get(i).getDepartureScheduleType() != null) { scheduleItem.setDepartureScheduleType(result .getSchedule() .get(i) .getDepartureScheduleType()); } if (result.getSchedule().get(i).getDepartureTime() != null) { scheduleItem.setDepartureTime(result .getSchedule().get(i) .getDepartureTime().toString() .substring(6, 19)); } if (result.getSchedule().get(i).getScheduledArrivalTime() != null) { scheduleItem.setScheduledArrivalTime(result .getSchedule() .get(i) .getScheduledArrivalTime() .toString() .substring(6, 19)); } scheduleItem.setStationName(result.getSchedule().get(i).getStationName()); if (result.getSchedule().get(i).getTrainMessage() != "") { scheduleItem.setTrainMessage(result .getSchedule().get(i) .getTrainMessage()); } if (result.getSchedule().get(i).getScheduledDepartureTime() != null) { scheduleItem.setScheduledDepartureTime(result .getSchedule() .get(i) .getScheduledDepartureTime() .toString() .substring(6, 19)); // We sort by scheduled departure time of the From station. if (fromLocation.equalsIgnoreCase(scheduleItem.getStationName())) { scheduledDepartureTime = new Date( Long.parseLong((scheduleItem .getScheduledDepartureTime()))); } } int trainNumber = result.getSchedule().get(i).getTrainNumber(); scheduleItem.setTrainNumber(trainNumber); String serviceName = trainNumberMap.get(trainNumber); if (serviceName == null) { serviceName = "Bus Service"; } scheduleItem.setSortOrder(result.getSchedule().get(i).getSortOrder()); String trainName = trainNumber + " " + serviceName; // Add the train name for ever other record. When there is one orgin and destination point // the train name will be the same. If the tripNumber is the same over more than two records // then we have multiple origin and destination points and likely different train names. // e.g. 515 Amtrak Cascades Train, 8911 Bus Service if (tripCounter % 2 == 0) { trainNameList.add(trainName); } scheduleItem.setTrainName(trainName); scheduleItem.setTripNumber(result.getSchedule().get(i).getTripNumber()); scheduleItem.setUpdateTime(result .getSchedule().get(i) .getUpdateTime().toString() .substring(6, 19)); stationItems.put(scheduleItem.getStationName(), scheduleItem); i++; if (i < numItems) { currentTripNumber = result.getSchedule().get(i).getTripNumber(); } tripCounter++; } if (trainNameList.size() > 1) { StringBuilder sb = new StringBuilder(); for (String s: trainNameList) { if (sb.length() > 0) sb.append(", "); sb.append(s); } stationItems.get(fromLocation).setTrainName(sb.toString()); } locationItems.add(stationItems); serviceItems.add(new AmtrakCascadesServiceItem(scheduledDepartureTime, locationItems)); } } Collections.sort(serviceItems, AmtrakCascadesServiceItem.scheduledDepartureTimeComparator); view.hideProgressIndicator(); view.setFromToLocation(fromLocation, toLocation); view.setTitle("Departing: " + amtrakStations.get(fromLocation) + " and Arriving: " + amtrakStations.get(toLocation)); view.render(serviceItems); view.refresh(); accessibility.postScreenChangeNotification(); } }); } /** * Get train schedules for those with just a departing station. * * @param url URL of the Web services API * @param toLocation arriving station name * @param fromLocation departing station name */ private void getDepartingTrains(String url, final String fromLocation, final String toLocation) { JsonpRequestBuilder jsonp = new JsonpRequestBuilder(); jsonp.setTimeout(30000); // Set timeout for 30 seconds jsonp.requestObject(url, new AsyncCallback<AmtrakCascadesScheduleFeed>() { @Override public void onFailure(Throwable caught) { view.hideProgressIndicator(); } @Override public void onSuccess(AmtrakCascadesScheduleFeed result) { if (result.getSchedule() != null) { serviceItems.clear(); AmtrakCascadesScheduleItem scheduleItem; int numItems = result.getSchedule().length(); for (int i = 0; i < numItems; i++) { // Loop through all trains Date scheduledTime = null; locationItems = new ArrayList<Map<String, AmtrakCascadesScheduleItem>>(); stationItems = new HashMap<String, AmtrakCascadesScheduleItem>(); scheduleItem = new AmtrakCascadesScheduleItem(); if (result.getSchedule().get(i).getArrivalComment() != null) { scheduleItem.setArrivalComment(result .getSchedule().get(i) .getArrivalComment()); } if (result.getSchedule().get(i).getArrivalScheduleType() != null) { scheduleItem.setArrivalScheduleType(result .getSchedule().get(i) .getArrivalScheduleType()); } if (result.getSchedule().get(i).getArrivalTime() != null) { scheduleItem.setArrivalTime(result .getSchedule().get(i) .getArrivalTime().toString() .substring(6, 19)); } if (result.getSchedule().get(i).getDepartureComment() != null) { scheduleItem.setDepartureComment(result .getSchedule().get(i) .getDepartureComment()); } if (result.getSchedule().get(i).getDepartureScheduleType() != null) { scheduleItem.setDepartureScheduleType(result .getSchedule().get(i) .getDepartureScheduleType()); } if (result.getSchedule().get(i).getDepartureTime() != null) { scheduleItem.setDepartureTime(result .getSchedule().get(i) .getDepartureTime().toString() .substring(6, 19)); } scheduleItem.setStationName(result.getSchedule().get(i).getStationName()); if (result.getSchedule().get(i).getTrainMessage() != "") { scheduleItem.setTrainMessage(result .getSchedule().get(i) .getTrainMessage()); } if (result.getSchedule().get(i).getScheduledArrivalTime() != null) { scheduleItem.setScheduledArrivalTime(result .getSchedule().get(i) .getScheduledArrivalTime() .toString().substring(6, 19)); if (fromLocation.equalsIgnoreCase(scheduleItem.getStationName())) { scheduledTime = new Date( Long.parseLong((scheduleItem .getScheduledArrivalTime()))); } } if (result.getSchedule().get(i).getScheduledDepartureTime() != null) { scheduleItem.setScheduledDepartureTime(result .getSchedule() .get(i) .getScheduledDepartureTime() .toString() .substring(6, 19)); // We sort by scheduled departure time of the From station. if (fromLocation.equalsIgnoreCase(scheduleItem.getStationName())) { scheduledTime = new Date( Long.parseLong((scheduleItem .getScheduledDepartureTime()))); } } int trainNumber = result.getSchedule().get(i).getTrainNumber(); scheduleItem.setTrainNumber(trainNumber); String serviceName = trainNumberMap.get(trainNumber); if (serviceName == null) { serviceName = "Bus Service"; } scheduleItem.setTrainName(trainNumber + " " + serviceName); scheduleItem.setTripNumber(result.getSchedule().get(i).getTripNumber()); scheduleItem.setUpdateTime(result.getSchedule() .get(i).getUpdateTime().toString() .substring(6, 19)); stationItems.put(scheduleItem.getStationName(), scheduleItem); locationItems.add(stationItems); serviceItems.add(new AmtrakCascadesServiceItem(scheduledTime, locationItems)); } } Collections.sort(serviceItems, AmtrakCascadesServiceItem.scheduledDepartureTimeComparator); view.hideProgressIndicator(); String location = fromLocation; view.setFromToLocation(fromLocation, location); view.setTitle(amtrakStations.get(fromLocation)); view.render(serviceItems); view.refresh(); } }); } @Override public void onStop() { view.setPresenter(null); } @Override public void onBackButtonPressed() { ActionEvent.fire(eventBus, ActionNames.BACK); } @Override public void onItemSelected(int index) { /* AmtrakCascadesServiceItem item = serviceItems.get(index); // Only register the click if the cell is selectable. if (item.getLocation().get(0).size() > 2) { clientFactory.getPlaceController().goTo( new AmtrakCascadesSchedulesDetailsPlace("X", item.getLocation())); } */ } }