/* * Copyright 2013, L. Murer. * * 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 tags; import de.schildbach.pte.dto.Connection.Footway; import de.schildbach.pte.dto.Connection.Part; import de.schildbach.pte.dto.Connection.Trip; import de.schildbach.pte.dto.Line; import de.schildbach.pte.dto.Location; import models.Directs; import models.KnownProvider; import models.Stations; import javax.annotation.Nullable; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.TimeZone; /** * User: Laurin * Date: Oct 19, 2011 * Time: 10:41:52 AM * To change this template use File | Settings | File Templates. */ //Although the IDE doesn't recognise it, the methods are used from the templates @SuppressWarnings("UnusedDeclaration") public class FastTags { /** * This Tag verifies, that an object is an instance of a specific class. */ public static boolean isit(Object o, Object clazz) { if (!(clazz instanceof String)) { clazz = clazz.getClass().getSimpleName(); } return o.getClass().getSimpleName().equals(clazz); } /** * It prints out the amount of changes of a trip * * @param vias List with multiple Parts (e.g. a List of Vias) * @param text String to describe the amount (will be displayed) * @param text_plural (optional) String to describe the amount in plural */ public static String getAmountOfChanges(List<Part> vias, String text, @Nullable String text_plural) { int amount = -1; //the first part obviously doesn't count as a change //for each Part that isn't a Footway, count one up for (Part via : vias) { if (!(via instanceof Footway)) { amount++; } } //print the output if (amount == 1) { return "1" + text; } else if (amount > 1) { if (text_plural != null) { return amount + text_plural; } else { return amount + text + "s"; } } return ""; } /** * It prints out the body part, but only if there are multiple parts that need to be displayed * * @param vias List with multiple Parts (e.g. a List of Vias) * @param body displayed, if vias can be displayed */ public static String showDetails(List<Part> vias, String body) { if (hasDetails(vias)) { return body; } else { return ""; } } /** * If there are multiple parts that need to be displayed * * @param vias List with multiple Parts (e.g. a List of Vias) */ public static boolean hasDetails(List<Part> vias) { int totalRealParts = 0; for (Part via : vias) { if (!(via instanceof Footway)) { totalRealParts++; if (totalRealParts > 1) { return true; } } } return false; } /** * It prints out as a table containing how to change from one Part to the next Part. * * @param vias List with multiple Parts (e.g. a List of Vias) * @param provider used for getting the timezone */ public static String getVias(List<Part> vias, KnownProvider provider) { //The default argument should be a List Object containing only parts. Otherwise, there will be thrown an Exception. TimeZone timeZone = provider.timeZone; //For all Vias, do the following boolean isFirstElement = true; //is it the first via? boolean isWalking = false; //is this/the previous via a part to walk (Footway) String lastStationName = ""; //the name of the station of the last via StringBuilder ret = new StringBuilder("<table>"); //For each via as a Part for (Part via : vias) { if (via instanceof Footway) { // don't display this, if it's to walk but remember it. isWalking = true; continue; } //We don't want to display the departure part of the first element, as it's already in the overview. if (isFirstElement) { isFirstElement = false; } else { //Write the part where to depart from this Part (second part in output view) ret.append("\t\t<td style='padding:0 10px;'>"); //If the last station was the same as this one, no need to display its name again (as it's the second part of the line in the output view) if (lastStationName.equals(getLocation(via.departure)) && (via instanceof Trip)) { //make simple output (with Track and Time only) Trip trip = (Trip) via; String gleis = trip.departurePosition; if (gleis != null && gleis.length() > 0) { ret.append("umsteigen auf</td>\n\t\t<td>Gleis ").append(gleis).append(" (").append(printTime(trip.departureTime, timeZone)).append(")"); } else { ret.append("Umstieg auf Anschluss</td>\n\t\t<td>").append(printTime(trip.departureTime, timeZone)); } } else { //if it's not simple to display... if (isWalking) { //if we walked to here isWalking = false; ret.append("Fussweg nach</td>\n\t\t<td>"); } else { //or use a general description ret.append("umsteigen auf</td>\n\t\t<td>"); } //and the target departure to change to ret.append(getPartOfPart(via, true, timeZone)).append("</td>"); } ret.append("\t</tr>\n"); } ret.append("\t<tr><td></td><td align=\"left\" colspan=\"2\">").append(getPartIcon(via, false)).append("</td></tr>\n"); //We don't want to display the arriving part of the last element, as it's already in the overview // if (via_iterator.hasNext()) { //Write the part where to arrive at by this Part (first part in output view) ret.append("\t<tr>\n"); //start a new line ret.append("\t\t<td>").append(getPartOfPart(via, false, timeZone)).append("</td>"); //show the full information of this Parts arrival lastStationName = getLocation(via.arrival); //set the name of this arrival station (to not show it in the second part of the output again) // } } ret.append("\t\t<td></td>\n\t\t<td></td>\n\t</tr>\n</table>\n"); return ret.toString(); } /** * Creates HTML code to display an icon for a part of a connection * * @param p the part to give the icon for * @param iconOnly whether only the icon should be displayed (and not also a description behind) * @return HTML code to display an icon for the given connection part */ private static String getPartIcon(Part p, boolean iconOnly) { if (p instanceof Footway) { return "<img src=\"/public/images/icons/foot.png\" width=\"22\" height=\"22\" alt=\"" + (iconOnly ? "Fussweg" : "") + "\">" + (iconOnly ? "" : " Fussweg"); } else if (p instanceof Trip) { Trip t = (Trip) p; Line line = t.line; if (line != null) { String label = line.label; if (label.length() > 2) { return "<img src=\"/public/images/icons/" + label.substring(0, 1).toLowerCase() + ".png\" width=\"22\" height=\"22\" alt=\"" + (iconOnly ? label.substring(1) : "") + "\">" + (iconOnly ? "" : " " + label.substring(1)); } } } if (iconOnly) { return "<img src=\"/public/images/icons/unknown.png\" width=\"22\" height=\"22\" alt=\"Unbekanntes Verkehrsmittel\">"; } else { return "Reise"; } } /** * It prints out the duration of a connection in hours and minutes * * @param departure departure time * @param arrival arrival time */ public static String getDuration(Date departure, Date arrival) { long duration = (arrival.getTime() - departure.getTime()); duration /= 60000; //to minutes StringBuilder ret = new StringBuilder(); if (duration >= 60) { ret.append(duration / 60); ret.append("h "); } ret.append(duration % 60); ret.append("min"); return ret.toString(); } /** * Parses the time to be displayed * * @param date to be displayed * @param provider used for getting the timezone */ public static String parseTime(Date date, KnownProvider provider) { return printTime(date, provider.timeZone); } /** * It prints out the current time * * @param provider The provider to get the timezone from */ public static String getCurrentTime(KnownProvider provider) { DateFormat now = new SimpleDateFormat("d.M.yy HH:mm"); now.setTimeZone(provider.timeZone); return now.format(new Date()); } /** * Returns the location as a string to display * * @param location the location to be returned as a string * @return the name of the location */ private static String getLocation(Location location) { if (location == null) { return ""; } String out = location.name; if (out == null) { out = ""; } return out; } /** * Gets the departure or arrival of a Via/Part as a String * * @param via the part to render (should, but don't have to, be a Trip) * @param getDeparture Show the departure? (or the arrival) * @param timeZone In which timezone the times should be displayed * @return Description of the departure/arrival of the part */ private static String getPartOfPart(Part via, boolean getDeparture, TimeZone timeZone) { //Make sure, via is not null if (via == null) { return ""; } //Define the output StringBuilder location; if (getDeparture) { //what should be printed (departure or arrival) location = new StringBuilder(getLocation(via.departure)); } else { location = new StringBuilder(getLocation(via.arrival)); } //if it's a Trip, add more information to the output if (via instanceof Trip) { Trip trip = (Trip) via; //yeah, it's a trip // Read track and time String gleis; Date zeit; if (getDeparture) { gleis = trip.departurePosition; zeit = trip.departureTime; } else { gleis = trip.arrivalPosition; zeit = trip.arrivalTime; } location.append(" ("); //Add track, if it's defined if (gleis != null && gleis.length() > 0) { location.append("Gleis "); location.append(gleis); location.append(", "); } //add time location.append(printTime(zeit, timeZone)); location.append(")"); } return location.toString(); } /** * Renders the time for display * * @param date Which time to print * @param timeZone In which timezone should the time be * @return The time to display */ private static String printTime(Date date, TimeZone timeZone) { if (timeZone == null) { timeZone = TimeZone.getDefault(); } DateFormat dateFormat = new SimpleDateFormat("HH:mm"); dateFormat.setTimeZone(timeZone); return dateFormat.format(date); } /** * Removes the matching of a regular expression from the body * * @param regex The regular expression needle that's been removed * @param body haystack */ public static String remove(String regex, String body) { if (body == null) { return null; } if (regex == null) { return body; } else { return body.replaceAll(regex, ""); } } /** * Prints the list of the checkboxes marking direct-connections only * * @param isCrossover If the user filed a crossover request * @param from The list of froms to get the amount * @param to The list of tos to get the amount * @param direct The already given direct/none-direct checks to be displayed * @return The HTML-Code for the direct-connection-only checkboxes */ @SuppressWarnings("UnusedDeclaration") public static String printDirectCheckboxes(boolean isCrossover, Stations from, Stations to, Directs direct) { StringBuilder sb = new StringBuilder(); final int repeats = Math.max(Math.max(from.size(), to.size()), 2) - 1; for (int i = 0; i < repeats; i++) { if (!isCrossover || i == 0) { sb.append("<input id='direct' class='direct' type='checkbox' name='direct[]' value='").append(i).append("'"); if (i < direct.size() && direct.get(i)) { sb.append("checked"); } sb.append("/>"); } } return sb.toString(); } public static class IteratorExtender { private int i = 0; public int get() { return i; } public void next() { ++i; } public boolean isEven() { return i % 2 == 0; } public void reset() { i = 0; } } public static Class getInnerClass(String outerClassName, String innerClassName) throws ClassNotFoundException { for (Class innerClass : Class.forName(outerClassName).getClasses()) { if (innerClass.getSimpleName().equals(innerClassName)) { return innerClass; } } return null; } public static boolean hasDeparturePosition(Part part) { return part instanceof Trip && ((Trip) part).departurePosition != null && !((Trip) part).departurePosition.equals(""); } public static String getDeparturePosition(Part part) { assert hasDeparturePosition(part); return ((Trip) part).departurePosition; } public static boolean hasArrivalPosition(Part part) { return part instanceof Trip && ((Trip) part).arrivalPosition != null && !((Trip) part).arrivalPosition.equals(""); } public static String getArrivalPosition(Part part) { assert hasArrivalPosition(part); return ((Trip) part).arrivalPosition; } }