package bigjava; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Map; import java.util.TimeZone; import java.util.TreeMap; import java.util.logging.Logger; import javax.annotation.Resource; import javax.sql.DataSource; /** This bean formats the local time of day for a given date and city. */ public class TimeZoneBean { /** Initializes the formatter. */ public TimeZoneBean() { timeFormatter = DateFormat.getTimeInstance(); cities = new ArrayList(); } /** Setter for cityToAdd property. @param city the city to add to the list of cities */ public void setCityToAdd(String city) { cityToAdd = city; } /** Getter for cityToAdd property. @return the city to add to the list of cities */ public String getCityToAdd() { return cityToAdd; } /** Setter for the cityToRemove property. @param city the city to remove from the list of cities */ public void setCityToRemove(String city) { cityToRemove = city; } /** Getter for the cityToRemove property. @return the city to remove from the list of cities */ public String getCityToRemove() { return cityToRemove; } /** Read-only citiesAndTimes property. @return a map containing the cities and formatted times */ public Map getCitiesAndTimes() { Date time = new Date(); Map result = new TreeMap(); for (int i = 0; i < cities.size(); i++) { String city = cities.get(i); String label = city + ": "; TimeZone zone = getTimeZone(city); if (zone != null) { timeFormatter.setTimeZone(zone); String timeString = timeFormatter.format(time); label = label + timeString; } else label = label + "unavailable"; result.put(label, city); } return result; } /** Action for adding a city. @return "available" if time zone information is available for the city, "unavailable" otherwise */ public String addCity() { TimeZone zone = getTimeZone(cityToAdd); if (zone == null) return "unavailable"; cities.add(cityToAdd); cityToRemove = cityToAdd; cityToAdd = ""; return "available"; } /** Action for removing a city. @return null if there are more cities to remove, "back" otherwise */ public String removeCity() { cities.remove(cityToRemove); if (cities.size() > 0) return null; else return "back"; } /** Looks up the time zone for a city @param city the city for which to find the time zone @return the time zone or null if no match is found */ private TimeZone getTimeZone(String city) { String[] ids = TimeZone.getAvailableIDs(); for (int i = 0; i < ids.length; i++) if (timeZoneIDmatch(ids[i], city)) return TimeZone.getTimeZone(ids[i]); try { String id = getZoneNameFromDB(city); if (id != null) return TimeZone.getTimeZone(id); } catch (Exception exception) { Logger.global.info("Caught in TimeZone.getTimeZone: " + exception); } return null; } private String getZoneNameFromDB(String city) throws SQLException { if (source == null) { Logger.global.info("No database connection"); return null; } Connection conn = source.getConnection(); try { PreparedStatement stat = conn.prepareStatement( "SELECT Zone FROM CityZone WHERE City=?"); stat.setString(1, city); ResultSet result = stat.executeQuery(); if (result.next()) return result.getString(1).trim(); else return null; } finally { conn.close(); } } /** Checks whether a time zone ID matches a city @param id the time zone ID (e.g. "America/Los_Angeles") @param city the city to match (e.g. "Los Angeles") @return true if the ID and city match */ private static boolean timeZoneIDmatch(String id, String city) { String idCity = id.substring(id.indexOf('/') + 1); return idCity.replace('_', ' ').equals(city); } @Resource(name="jdbc/__default") private DataSource source; private DateFormat timeFormatter; private ArrayList cities; private String cityToAdd; private String cityToRemove; }