001: package com.icesoft.openajax.beans;
002:
003: import com.icesoft.faces.async.render.IntervalRenderer;
004: import com.icesoft.faces.async.render.RenderManager;
005: import com.icesoft.faces.async.render.Renderable;
006: import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
007: import com.icesoft.faces.webapp.xmlhttp.RenderingException;
008: import javax.faces.component.UIComponent;
009: import javax.faces.context.FacesContext;
010: import javax.faces.event.ActionEvent;
011: import javax.faces.event.ValueChangeEvent;
012: import java.text.DateFormat;
013: import java.text.SimpleDateFormat;
014: import java.util.ArrayList;
015: import java.util.Calendar;
016: import java.util.Hashtable;
017: import java.util.TimeZone;
018:
019: /**
020: * Bean backing the Time Zone application. This bean uses the RenderManager to
021: * update state at a specified interval. Also controls time zone information
022: * during the session.
023: */
024: public class TimeZoneBean implements Renderable {
025: /**
026: * The default {@link TimeZone} for this host server.
027: */
028: private TimeZone serverTimeZone;
029:
030: /**
031: * {@link DateFormat} used to display the server time.
032: */
033: private DateFormat serverFormat;
034:
035: /**
036: * Active {@link TimeZone} displayed at top of UI. Changes when a time zone
037: * is selected by pressing one of six commandButtons in UI map.
038: */
039: private TimeZone selectedTimeZone;
040:
041: /**
042: * {@link DateFormat} used to display the selected time.
043: */
044: private DateFormat selectedFormat;
045:
046: /**
047: * List of all possible {@link TimeZoneWrapper} objects, which must mirror
048: * the map and checkbox UIs.
049: */
050: private ArrayList allTimeZoneList;
051:
052: /**
053: * List of checked {@link TimeZoneWrapper} objects, which are shown at the
054: * bottom table UI. Changes when a time zone is selected or deselected by
055: * checking one of six check boxes underneath map UI.
056: */
057: private ArrayList checkedTimeZoneList;
058:
059: /**
060: * Time interval, in milliseconds, between renders.
061: */
062: private final int renderInterval = 1000;
063:
064: /**
065: * The state associated with the current user that can be used for
066: * server-initiated render calls.
067: */
068: private PersistentFacesState state;
069:
070: /**
071: * A named render group that can be shared by all TimeZoneBeans for
072: * server-initiated render calls. Setting the interval determines the
073: * frequency of the render call.
074: */
075: private IntervalRenderer clock;
076:
077: /**
078: * a table mapping the checkbox id's to the checkbox states
079: */
080: private Hashtable checkboxStates;
081:
082: /**
083: * display the open ajax conformance dialog or not
084: */
085: private boolean dialogRendered = true;
086:
087: /**
088: * Constructor initializes time zones.
089: */
090: public TimeZoneBean() {
091: init();
092: }
093:
094: /**
095: * Initializes this TimeZoneBean's properties.
096: */
097: private void init() {
098: serverTimeZone = TimeZone.getDefault();
099: serverFormat = buildDateFormatForTimeZone(serverTimeZone);
100: selectedTimeZone = TimeZone.getTimeZone("Etc/GMT+0"); // selected time zone set to UTC as default
101: selectedFormat = buildDateFormatForTimeZone(selectedTimeZone);
102:
103: // Entries in this list are hardcoded to match entries in
104: // the timezone web file, so no parameters can be changed.
105: allTimeZoneList = new ArrayList(6);
106: allTimeZoneList.add(new TimeZoneWrapper("Pacific/Honolulu",
107: "GMTminus10", "Cminus10"));
108: allTimeZoneList.add(new TimeZoneWrapper("America/Anchorage",
109: "GMTminus9", "Cminus9"));
110: allTimeZoneList.add(new TimeZoneWrapper("America/Los_Angeles",
111: "GMTminus8", "Cminus8"));
112: allTimeZoneList.add(new TimeZoneWrapper("America/Phoenix",
113: "GMTminus7", "Cminus7"));
114: allTimeZoneList.add(new TimeZoneWrapper("America/Chicago",
115: "GMTminus6", "Cminus6"));
116: allTimeZoneList.add(new TimeZoneWrapper("America/New_York",
117: "GMTminus5", "Cminus5"));
118:
119: checkedTimeZoneList = new ArrayList();
120:
121: state = PersistentFacesState.getInstance();
122:
123: checkboxStates = new Hashtable(6);
124: checkboxStates.put("Cminus10", "false");
125: checkboxStates.put("Cminus9", "false");
126: checkboxStates.put("Cminus8", "false");
127: checkboxStates.put("Cminus7", "false");
128: checkboxStates.put("Cminus6", "false");
129: checkboxStates.put("Cminus5", "false");
130: }
131:
132: /**
133: * Gets server time.
134: *
135: * @return Server time.
136: */
137: public String getServerTime() {
138: return formatCurrentTime(serverFormat);
139: }
140:
141: /**
142: * Gets server time zone display name.
143: *
144: * @return Server time zone display name.
145: */
146: public String getServerTimeZoneName() {
147: return displayNameTokenizer(serverTimeZone.getDisplayName());
148: }
149:
150: /**
151: * Gets selected time zone time. This is the time zone selected by one of
152: * six commandButtons from the map in the UI.
153: *
154: * @return selectedTimeZone time.
155: */
156: public String getSelectedTime() {
157: return formatCurrentTime(selectedFormat);
158: }
159:
160: /**
161: * Gets selected time zone display name.
162: *
163: * @return selectedTimeZone display name.
164: */
165: public String getSelectedTimeZoneName() {
166: synchronized (TimeZone.class) {
167: return displayNameTokenizer(selectedTimeZone
168: .getDisplayName());
169: }
170: }
171:
172: /**
173: * Gets ArrayList of currently active <code>TimeZoneWrapper</code> objects.
174: * This list is populated by selectBooleanCheckbox components in UI.
175: *
176: * @return ArrayList of TimeZoneWrapper objects.
177: */
178: public ArrayList getCheckedTimeZoneList() {
179: return checkedTimeZoneList;
180: }
181:
182: public boolean isDialogRendered() {
183: return dialogRendered;
184: }
185:
186: public void setDialogRendered(boolean dialogRendered) {
187: this .dialogRendered = dialogRendered;
188: }
189:
190: public String closeDialog() {
191: dialogRendered = false;
192: return "closeDialog";
193: }
194:
195: /**
196: * Extracts the first word from a TimeZone displayName.
197: *
198: * @param displayName A TimeZone displayName.
199: * @return String The first word from the TimeZone displayName.
200: */
201: public static String displayNameTokenizer(String displayName) {
202: if (displayName == null) {
203: displayName = "";
204: } else {
205: int firstSpace = displayName.indexOf(' ');
206: if (firstSpace != -1) {
207: displayName = displayName.substring(0, firstSpace);
208: }
209: }
210: return displayName;
211: }
212:
213: public static DateFormat buildDateFormatForTimeZone(
214: TimeZone timeZone) {
215: SimpleDateFormat currentFormat = new SimpleDateFormat(
216: "EEE, HH:mm:ss");
217: Calendar currentZoneCal = Calendar.getInstance(timeZone);
218: currentFormat.setCalendar(currentZoneCal);
219: currentFormat.setTimeZone(timeZone);
220: return currentFormat;
221: }
222:
223: public static String formatCurrentTime(DateFormat dateFormat) {
224: Calendar cal = dateFormat.getCalendar();
225: cal.setTimeInMillis(System.currentTimeMillis());
226: return dateFormat.format(cal.getTime());
227: }
228:
229: /**
230: * Each TimeZoneWrapper has one or more ids of components in the UI that
231: * correspond to its time zone. By this, if an event comes from a component
232: * in the web page, then this will return the relevant TimeZoneWrapper.
233: *
234: * @param componentId Id of component in UI
235: * @return TimeZoneWrapper
236: */
237: private TimeZoneWrapper getTimeZoneWrapperByComponentId(
238: String componentId) {
239: for (int i = 0; i < allTimeZoneList.size(); i++) {
240: TimeZoneWrapper tzw = (TimeZoneWrapper) allTimeZoneList
241: .get(i);
242: if (tzw.isRelevantComponentId(componentId)) {
243: return tzw;
244: }
245: }
246: return null;
247: }
248:
249: /**
250: * Used to create, setup, and start an IntervalRenderer from the passed
251: * renderManager This is used in conjunction with faces-config.xml to allow
252: * the same single render manager to be set in all TimeZoneBeans
253: *
254: * @param renderManager RenderManager to get the IntervalRenderer from
255: */
256: public void setRenderManager(RenderManager renderManager) {
257: clock = renderManager.getIntervalRenderer("clock");
258: clock.setInterval(renderInterval);
259: clock.add(this );
260: clock.requestRender();
261: }
262:
263: /**
264: * Gets RenderManager
265: *
266: * @return RenderManager null
267: */
268: public RenderManager getRenderManager() {
269: return null;
270: }
271:
272: //
273: // Renderable interface
274: //
275:
276: /**
277: * Gets the current instance of PersistentFacesState
278: *
279: * @return PersistentFacesState state
280: */
281: public PersistentFacesState getState() {
282: return state;
283: }
284:
285: /**
286: * Callback to inform us that there was an Exception while rendering
287: *
288: * @param renderingException
289: */
290: public void renderingException(RenderingException renderingException) {
291: if (clock != null) {
292: clock.remove(this );
293: clock = null;
294: }
295: }
296:
297: //
298: // Implicit interfaces as defined by the callbacks in the web files
299: //
300:
301: /**
302: * Listens to client input from commandButtons in the UI map and sets the
303: * selected time zone.
304: *
305: * @param event ActionEvent.
306: */
307: public void listen(ActionEvent event) {
308: UIComponent comp = event.getComponent();
309: FacesContext context = FacesContext.getCurrentInstance();
310: String componentId = comp.getClientId(context);
311: TimeZoneWrapper tzw = getTimeZoneWrapperByComponentId(componentId);
312: if (tzw != null) {
313: selectedTimeZone = TimeZone.getTimeZone(tzw.getId());
314: selectedFormat = buildDateFormatForTimeZone(selectedTimeZone);
315: }
316: }
317:
318: /**
319: * Adds or removes a <code>TimeZoneWrapper</code> to
320: * <code>checkedTimeZoneList</code> when a selectBooleanCheckbox
321: * ValueChangeEvent is fired from the UI.
322: *
323: * @param event ValueChangeEvent.
324: */
325: public void timeZoneChanged(ValueChangeEvent event) {
326: UIComponent comp = event.getComponent();
327: FacesContext context = FacesContext.getCurrentInstance();
328: String componentId = comp.getClientId(context);
329: TimeZoneWrapper tzw = getTimeZoneWrapperByComponentId(componentId);
330: if (tzw != null) {
331: boolean checked = ((Boolean) event.getNewValue())
332: .booleanValue();
333: // If checkbox is checked, then add tzw to checkedTimeZoneList
334: if (checked) {
335: if (!checkedTimeZoneList.contains(tzw)) {
336: checkedTimeZoneList.add(tzw);
337: }
338: }
339: // Otherwise, if checkbox is unchecked, then remove tzw from checkedTimeZoneList
340: else {
341: checkedTimeZoneList.remove(tzw);
342: }
343: checkboxStates.put(tzw.getCheckboxId(), checked ? "true"
344: : "false");
345: }
346: }
347:
348: /**
349: * Gets the table of checkbox states.
350: *
351: * @return a table mapping the checkbox id's to the checkbox states
352: */
353: public Hashtable getCheckboxStates() {
354: return checkboxStates;
355: }
356:
357: /**
358: * Sets the table of checkbox states.
359: *
360: * @param checkboxStates a table mapping the checkbox id's to the checkbox
361: * states
362: */
363: public void setCheckboxStates(Hashtable checkboxStates) {
364: this.checkboxStates = checkboxStates;
365: }
366: }
|