001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.event;
042:
043: import com.sun.data.provider.RowKey;
044: import com.sun.rave.web.ui.util.LogUtil;
045:
046: import java.util.HashMap;
047:
048: import javax.faces.FactoryFinder;
049: import javax.faces.lifecycle.Lifecycle;
050: import javax.faces.lifecycle.LifecycleFactory;
051: import javax.faces.event.PhaseEvent;
052: import javax.faces.event.PhaseId;
053: import javax.faces.event.PhaseListener;
054:
055: /**
056: * A utility class for radiobutton and checkbox components used to select rows
057: * of a table.
058: * <p>
059: * Note: UI guidelines recomend that rows should be unselected when no longer in
060: * view. For example, when a user selects rows of the table and navigates to
061: * another page. Or, when a user applies a filter or sort that may hide
062: * previously selected rows from view. If a user invokes an action to delete the
063: * currently selected rows, they may inadvertently remove rows not displayed on
064: * the current page. Using TableSelectPhaseListener ensures that invalid row
065: * selections are not rendered by clearing selected state after the render
066: * response phase. That said, there are cases when maintaining state across
067: * table pages is necessary. In this scenario, use the keepSelected method to
068: * prevent state from being cleared by this instance.
069: * </p><p>
070: * Note: To see the messages logged by this class, set the following global
071: * defaults in your JDK's "jre/lib/logging.properties" file.
072: * </p><p><pre>
073: * java.util.logging.ConsoleHandler.level = FINE
074: * com.sun.rave.web.ui.event.TableSelectPhaseListener.level = FINE
075: * </pre></p>
076: */
077: public class TableSelectPhaseListener implements PhaseListener {
078: private Object unselected = null; // Unselected object for primitve values.
079: private HashMap selected = new HashMap(); // Selected values map.
080: private boolean keepSelected = false; // Do not clear selected flag.
081:
082: /** Default constructor */
083: public TableSelectPhaseListener() {
084: // Add phase listener.
085: LifecycleFactory factory = (LifecycleFactory) FactoryFinder
086: .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
087: Lifecycle lifecycle = factory
088: .getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
089: lifecycle.addPhaseListener(this );
090: }
091:
092: /**
093: * Construct an instance with the given flag indicating that selected
094: * objects should not be cleared after the render response phase.
095: *
096: * @param keepSelected If true, ojects are not cleared.
097: */
098: public TableSelectPhaseListener(boolean keepSelected) {
099: this ();
100: keepSelected(keepSelected);
101: }
102:
103: /** Construct an instance with an unselected parameter.
104: * <p>
105: * The unselected parameter is only required if a primitve value is being
106: * used for the selecteValue attribute of the checkbox or radiobutton. If
107: * the selectedValue property is an Object value then unselected can be
108: * null. If however it is a primitive type then it should be the MIN_VALUE
109: * constant instance of the wrapper Object type. For example if the
110: * application is assigning int values to selectedValue then unselected
111: * should be new Integer(Integer.MIN_VALUE).
112: * </p>
113: * @param unselected the object to return for an unselected checkbox.
114: */
115: public TableSelectPhaseListener(Object unselected) {
116: this ();
117: this .unselected = unselected;
118: }
119:
120: /**
121: * Called during the JSF Lifecycle after the RENDER_RESPONSE phase.
122: *
123: * @param event The PhaseEvent object.
124: */
125: public void afterPhase(PhaseEvent event) {
126: if (!keepSelected) {
127: selected.clear();
128: } else {
129: log("afterPhase", //NOI18N
130: "Selected values not cleared, keepSelected is false");
131: }
132: }
133:
134: /**
135: * Called during the JSF Lifecycle before the RENDER_RESPONSE phase.
136: *
137: * @param event The PhaseEvent object.
138: */
139: public void beforePhase(PhaseEvent event) {
140: // Not needed
141: }
142:
143: /** Get the phase id. */
144: public PhaseId getPhaseId() {
145: return PhaseId.RENDER_RESPONSE;
146: }
147:
148: /**
149: * Clear all selected objects.
150: */
151: public void clear() {
152: selected.clear();
153: }
154:
155: /**
156: * Get the selected object from this instance.
157: * <p>
158: * Note: Call this method from the get method that that is bound to the
159: * selected attribute.
160: * </p>
161: * @param rowKey The current RowKey.
162: * @return The selected object.
163: */
164: public Object getSelected(RowKey rowKey) {
165: Object object = (rowKey != null) ? selected.get(rowKey
166: .getRowId()) : null;
167:
168: // If null, return the unselected value.
169: return (object != null) ? object : unselected;
170: }
171:
172: /**
173: * Test if the flag indicating that selected objects should be cleared
174: * after the render response phase.
175: *
176: * @return true if ojects are not to be cleared.
177: */
178: public boolean isKeepSelected() {
179: return keepSelected;
180: }
181:
182: /**
183: * Test if the object associated with the given RowKey is selected.
184: *
185: * @param rowKey The current RowKey.
186: * @return A true or false value.
187: */
188: public boolean isSelected(RowKey rowKey) {
189: Object object = getSelected(rowKey);
190: return (object != null && object != unselected);
191: }
192:
193: /**
194: * Set the flag indicating that selected objects should be cleared after
195: * the render response phase.
196: *
197: * @param keepSelected Selected objects are kept true, cleared if false.
198: */
199: public void keepSelected(boolean keepSelected) {
200: this .keepSelected = keepSelected;
201: }
202:
203: /**
204: * Set the selected object for this instance.
205: * <p>
206: * Note: Call this method from the set method that that is bound to the
207: * selected attribute.
208: * </p>
209: * @param rowKey The current RowKey.
210: * @param object The selected object.
211: */
212: public void setSelected(RowKey rowKey, Object object) {
213: if (rowKey != null) {
214: selected.put(rowKey.getRowId(), object);
215: }
216: }
217:
218: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219: // Private methods
220: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221:
222: /**
223: * Log fine messages.
224: */
225: private void log(String method, String message) {
226: // Get class.
227: Class clazz = this .getClass();
228: if (LogUtil.fineEnabled(clazz)) {
229: // Log method name and message.
230: LogUtil.fine(clazz, clazz.getName() + "." + method + ": "
231: + message); //NOI18N
232: }
233: }
234: }
|