001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.presentation.portlet.component;
051:
052: import java.util.*;
053: import org.jaffa.presentation.portlet.FormKey;
054: import org.jaffa.presentation.portlet.session.UserSession;
055: import org.apache.log4j.*;
056: import java.util.Enumeration;
057: import org.jaffa.util.StringHelper;
058: import java.lang.reflect.Method;
059: import java.lang.reflect.InvocationTargetException;
060: import javax.servlet.http.HttpServletRequest;
061: import org.jaffa.exceptions.ApplicationExceptions;
062: import org.jaffa.exceptions.FrameworkException;
063: import org.jaffa.util.BeanHelper;
064: import org.jaffa.datatypes.DateTime;
065: import org.jaffa.presentation.portlet.FormKeyChangeEvent;
066: import org.jaffa.presentation.portlet.FormKeyChangeListener;
067:
068: /** The base class for all Components
069: */
070: public abstract class Component implements IComponent {
071: private static Logger log = Logger.getLogger(Component.class);
072:
073: private String m_componentId = null;
074: private ComponentDefinition m_componentDefinition = null;
075: private UserSession m_userSession = null;
076: private FormKey m_returnToFormKey = null;
077: private FormKey m_containerFormKey = null;
078: private Collection m_formKeyChangeListeners = null;
079: private DateTime m_lastActivityDate = new DateTime();
080: private Collection m_childComponents = null;
081: private String m_token = null;
082:
083: // *****************************************
084: // METHODS INVOKED BY THE ComponentManager
085: // *****************************************
086: void setComponentId(String componentId) {
087: m_componentId = componentId;
088: }
089:
090: void setComponentDefinition(ComponentDefinition componentDefinition) {
091: m_componentDefinition = componentDefinition;
092: }
093:
094: void setUserSession(UserSession userSession) {
095: m_userSession = userSession;
096: }
097:
098: // ******************************
099: // IMPLEMENTATION METHODS
100: // ******************************
101:
102: /** Returns a FormKey, which has the componentId & the formName to which control should be passed
103: * @throws FrameworkException if any framework error occurs.
104: * @throws ApplicationExceptions if any application error occurs.
105: * @return the FormKey object
106: */
107: public abstract FormKey display() throws FrameworkException,
108: ApplicationExceptions;
109:
110: /** This will kill all the Forms
111: * Finally de-register itself from the UserSession
112: */
113: public void quit() {
114: if (m_componentId != null) {
115: if (log.isDebugEnabled())
116: log.debug("Quitting Component...");
117:
118: if (log.isDebugEnabled())
119: log.debug("Removing Component From UserSession");
120: m_userSession.removeComponent(this );
121:
122: // Nullify all the references
123: m_componentId = null;
124: m_componentDefinition = null;
125: m_userSession = null;
126:
127: // Pass the ReturnToFormKey to all the registered FormKeyChangeListeners
128: if (m_formKeyChangeListeners != null
129: && m_formKeyChangeListeners.size() > 0) {
130: FormKeyChangeEvent e = new FormKeyChangeEvent(this ,
131: getReturnToFormKey());
132: for (Iterator i = m_formKeyChangeListeners.iterator(); i
133: .hasNext();)
134: ((FormKeyChangeListener) i.next())
135: .formKeyChanged(e);
136: m_formKeyChangeListeners.clear();
137: }
138: m_containerFormKey = null;
139: m_formKeyChangeListeners = null;
140: } else {
141: if (log.isDebugEnabled())
142: log
143: .debug("Component's quit() method has already been invoked");
144: }
145: }
146:
147: /** This should invoke the quit() method, and then return the FormKey for the calling screen.
148: * The FormKey should have been set by a call to setReturnToFormKey().
149: * @return The FormKey for the caling screen. A null will be returned, if no calling screen was specified.
150: */
151: public FormKey quitAndReturnToCallingScreen() {
152: quit();
153: return getReturnToFormKey();
154: }
155:
156: /** Returns the Id for the component
157: * @return The componentId
158: */
159: public String getComponentId() {
160: return m_componentId;
161: }
162:
163: /** Returns the ComponentDefinition based on which this Component was created
164: * @return The ComponentDefintion object for the Component
165: */
166: public ComponentDefinition getComponentDefinition() {
167: return m_componentDefinition;
168: }
169:
170: /** Returns the UserSession, under which the Component was created
171: * @return The UserSession object
172: */
173: public UserSession getUserSession() {
174: return m_userSession;
175: }
176:
177: /** Getter for property returnToFormKey.
178: * This FormKey determines the screen to display when quitting from a component.
179: * @return Value of property returnToFormKey.
180: */
181: public FormKey getReturnToFormKey() {
182: return m_returnToFormKey;
183: }
184:
185: /** Setter for property returnToFormKey.
186: * This FormKey determines the screen to display when quitting from a component.
187: * @param returnToFormKey New value of property returnToFormKey.
188: */
189: public void setReturnToFormKey(FormKey returnToFormKey) {
190: m_returnToFormKey = returnToFormKey;
191: }
192:
193: /** Getter for property containerFormKey.
194: * This property is useful when this component is being rendered as a tile inside another component.
195: * The outer component is expected to set this property on this component.
196: * The outer component is also expected to register the FormKeyChangeListener on this component.
197: * The ActionBase will intercept all FormKeys for this component. It will then fire the FormKeyChangeEvents on the listeners. The ActionBase will then return the ContainerFormKey.
198: * The Component will fire the FormKeyChangeEvents on the listeners during the quit(), passing the ReturnToFormKey.
199: * All this helps render the tiles correctly.
200: * @return Value of property containerFormKey.
201: *
202: */
203: public FormKey getContainerFormKey() {
204: return m_containerFormKey;
205: }
206:
207: /** Setter for property containerFormKey.
208: * This property is useful when this component is being rendered as a tile inside another component.
209: * The outer component is expected to set this property on this component.
210: * The outer component is also expected to register the FormKeyChangeListener on this component.
211: * The ActionBase will intercept all FormKeys for this component. It will then fire the FormKeyChangeEvents on the listeners. The ActionBase will then return the ContainerFormKey.
212: * The Component will fire the FormKeyChangeEvents on the listeners during the quit(), passing the ReturnToFormKey.
213: * All this helps render the tiles correctly.
214: * @param containerFormKey New value of property containerFormKey.
215: *
216: */
217: public void setContainerFormKey(FormKey containerFormKey) {
218: m_containerFormKey = containerFormKey;
219: }
220:
221: /** Registers listener so that it will receive FormKeyChangeEvents.
222: * The ActionBase typically creates the FormKeyChangeEvent object, when processing an event for a component, that has a ContainerFormKey.
223: * It will then fire the FormKeyChangeListener registered with the component, passing the FormKeyChangeEvent object.
224: * The Component will fire the FormKeyChangeEvents on the listeners during the quit(), passing the ReturnToFormKey.
225: * @param listener the FormKeyChangeListener to register.
226: */
227: public void addFormKeyChangeListener(FormKeyChangeListener listener) {
228: if (m_formKeyChangeListeners == null)
229: m_formKeyChangeListeners = new HashSet();
230: m_formKeyChangeListeners.add(listener);
231: }
232:
233: /** Unregisters listener so that it will no longer receive FormKeyChangeEvents.
234: * @param listener the FormKeyChangeListener to be removed.
235: */
236: public void removeFormKeyChangeListener(
237: FormKeyChangeListener listener) {
238: if (m_formKeyChangeListeners != null)
239: m_formKeyChangeListeners.remove(listener);
240: }
241:
242: /** Returns an array of all the FormKeyChangeListeners registered on this component.
243: * @return all of the component's FormKeyChangeListeners or a null if no ancestor listeners are currently registered.
244: */
245: public FormKeyChangeListener[] getFormKeyChangeListeners() {
246: if (m_formKeyChangeListeners != null)
247: return (FormKeyChangeListener[]) m_formKeyChangeListeners
248: .toArray(new FormKeyChangeListener[0]);
249: else
250: return null;
251: }
252:
253: /** Returns a true if the component is still active. The component will be set to inactive status after a quit().
254: * @return a true if the component is still active.
255: */
256: public boolean isActive() {
257: // m_componentId is set to null after a quit()
258: return m_componentId != null;
259: }
260:
261: /** Getter for property token.
262: * @return Value of property token.
263: *
264: */
265: public String getToken() {
266: return m_token;
267: }
268:
269: /** Setter for property token.
270: * @param token New value of property token.
271: *
272: */
273: public void setToken(String token) {
274: m_token = token;
275: }
276:
277: // ******************************
278: // ADDITIONAL METHODS
279: // ******************************
280: /** Convenience Method for 'ComponentManager.run()'.
281: * This may throw the runtime ComponentCreationRuntimeException
282: * @param component The name of the component to create. There should be a valid definition for this name in the 'components.xml' file
283: * @return An instance of the Component
284: */
285: public Component run(String component) {
286: Component comp = ComponentManager.run(component, m_userSession);
287: addChildComponent(comp);
288: return comp;
289: }
290:
291: /** Invoke the setters on the component passing the parameters in the request-stream
292: * This is a convenience method which can be invoked after creation of a new Component
293: * @param request The HTTP request we are processing
294: */
295: public void reflectAndSetParms(HttpServletRequest request) {
296: Class clazz = this .getClass();
297: for (Enumeration enum = request.getParameterNames(); enum.hasMoreElements();) {
298: String parameterName = (String) enum.nextElement();
299: try {
300: BeanHelper.setField(this , parameterName, request.getParameter(parameterName));
301: } catch (Exception e) {
302: // do nothing
303: }
304: }
305: }
306:
307: /** This updates the activity timestamp on the component. This will ideally be called by the central servlet that services an event on a component.
308: */
309: public void updateLastActivityDate() {
310: m_lastActivityDate = new DateTime();
311: }
312:
313: /** This returns the timestamp for the last known activity on the component.
314: * @return The timestamp for the last known activity on the component.
315: */
316: public DateTime returnLastActivityDate() {
317: return m_lastActivityDate;
318: }
319:
320: /** This adds a child component to an internal list. A child component instantiated via the run() method, will be implicitly added to the internal list.
321: * @param component The child component.
322: */
323: public void addChildComponent(Component component) {
324: if (m_childComponents == null)
325: m_childComponents = new LinkedList();
326: m_childComponents.add(component);
327: }
328:
329: /** This returns a collection of components which were created by this component.
330: * @return a collection of components which were created by this component.
331: */
332: public Collection returnChildComponents() {
333: return m_childComponents;
334: }
335:
336: }
|