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.components.maint;
051:
052: import java.lang.NoSuchMethodException;
053: import java.lang.reflect.Method;
054: import java.util.*;
055: import javax.servlet.http.HttpServletRequest;
056: import org.apache.log4j.Logger;
057: import org.apache.struts.action.ActionErrors;
058: import org.jaffa.presentation.portlet.ActionBase;
059: import org.jaffa.presentation.portlet.FormKey;
060: import org.jaffa.exceptions.FrameworkException;
061: import org.jaffa.exceptions.ApplicationExceptions;
062: import org.jaffa.exceptions.ApplicationException;
063: import org.jaffa.presentation.portlet.EventHandlerMissingRuntimeException;
064: import org.jaffa.presentation.portlet.HistoryNav;
065:
066: /** This is the base class for all Maintenance Component Actions.
067: * @author GautamJ
068: */
069: public class MaintAction extends ActionBase {
070:
071: private static final Logger log = Logger
072: .getLogger(MaintAction.class);
073:
074: /** Quits the component and returns the FormKey for the calling screen.
075: * @return The FormKey for the calling screen. A null will be returned, if no calling screen was specified.
076: */
077: public FormKey do_Cancel_Clicked() {
078: return ((MaintForm) form).getComponent()
079: .quitAndReturnToCallingScreen();
080: }
081:
082: /** Invokes the create() or update() method on the component, depending on the mode. It then quits the component.
083: * @return The FormKey for the calling screen. A null will be returned, if no calling screen was specified.
084: */
085: public FormKey do_Finish_Clicked() {
086: MaintForm myForm = (MaintForm) form;
087: MaintComponent2 myComp = (MaintComponent2) myForm
088: .getComponent();
089:
090: FormKey fk = do_Save_Clicked();
091: if (myForm.hasErrors(request))
092: return fk;
093: else
094: return myComp.quitAndReturnToCallingScreen();
095: }
096:
097: /** Invokes the create() or update() method on the component, depending on the mode.
098: * @return The FormKey for the screen.
099: */
100: public FormKey do_Save_Clicked() {
101: MaintForm myForm = (MaintForm) form;
102: MaintComponent2 myComp = (MaintComponent2) myForm
103: .getComponent();
104:
105: try {
106: // This will stop double submits
107: performTokenValidation(request);
108:
109: // First validate the current screen
110: if (invokeDoValidateForScreen(myComp
111: .getCurrentScreenCounter())) {
112: // Now validate all the other screens
113: if (invokeDoValidateForScreensOtherThanCurrent(myComp)) {
114: if (myComp.isCreateMode()) {
115: myComp.create();
116: myComp.setMode(IMaintComponent.MODE_UPDATE);
117:
118: // move to next screen, if the current screen is unavailable in update mode
119: if (!myComp.determineCurrentScreen()
120: .isAvailableInUpdateMode())
121: myComp.determineAndSetNextScreen();
122:
123: // Remove links from the HistoryNav, which are not supported in the update mode
124: fixHistoryNavList(myComp);
125: } else {
126: myComp.update(true);
127: }
128: }
129: }
130: } catch (ApplicationExceptions e) {
131: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR, e);
132: } catch (FrameworkException e) {
133: log.error(null, e);
134: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR,
135: "error.framework.general");
136: }
137:
138: return myComp.determineFormKey();
139: }
140:
141: /** Invokes the delete() method on the component. It then quits the component.
142: * @return The FormKey for the calling screen. A null will be returned, if no calling screen was specified.
143: */
144: public FormKey do_Delete_Clicked() {
145: MaintForm myForm = (MaintForm) form;
146: MaintComponent2 myComp = (MaintComponent2) myForm
147: .getComponent();
148:
149: try {
150: // This will stop double submits
151: performTokenValidation(request);
152:
153: myComp.delete(true);
154: return myComp.quitAndReturnToCallingScreen();
155: } catch (ApplicationExceptions e) {
156: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR, e);
157: } catch (FrameworkException e) {
158: e.printStackTrace();
159: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR,
160: "error.framework.general");
161: }
162:
163: return myComp.determineFormKey();
164: }
165:
166: /** Invokes the retrieve() method on the component.
167: * @return The FormKey for the screen.
168: */
169: public FormKey do_Refresh_Clicked() {
170: MaintForm myForm = (MaintForm) form;
171: MaintComponent2 myComp = (MaintComponent2) myForm
172: .getComponent();
173:
174: try {
175: myComp.retrieve();
176: } catch (ApplicationExceptions e) {
177: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR, e);
178: } catch (FrameworkException e) {
179: e.printStackTrace();
180: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR,
181: "error.framework.general");
182: }
183:
184: return myComp.determineFormKey();
185: }
186:
187: /** Determines the currentFormKey
188: * This event is invoked when a user changes the settings of the UserGrid in the Results screen.
189: * @return The FormKey for the Results screen.
190: */
191: public FormKey do_refresh() {
192: MaintForm myForm = (MaintForm) form;
193: MaintComponent2 myComp = (MaintComponent2) myForm
194: .getComponent();
195: return myComp.determineFormKey();
196: }
197:
198: /** This will invoke the prevalidate method on the component if required for the current screen.
199: * It then moves to the next screen
200: * @return The FormKey for the next screen.
201: */
202: public FormKey do_Next_Clicked() {
203: MaintForm myForm = (MaintForm) form;
204: MaintComponent2 myComp = (MaintComponent2) myForm
205: .getComponent();
206:
207: if (invokeDoValidateForScreen(myComp.getCurrentScreenCounter())) {
208: try {
209: MaintComponent2.Screen currentScreen = myComp
210: .determineCurrentScreen();
211: if (currentScreen.isPerformTxValidationOnNextAction()) {
212: if (myComp.isCreateMode())
213: myComp.prevalidateCreate();
214: else
215: myComp.prevalidateUpdate(true);
216: }
217: myComp.determineAndSetNextScreen();
218: } catch (ApplicationExceptions e) {
219: myForm
220: .raiseError(request, ActionErrors.GLOBAL_ERROR,
221: e);
222: } catch (FrameworkException e) {
223: log.error(null, e);
224: myForm.raiseError(request, ActionErrors.GLOBAL_ERROR,
225: "error.framework.general");
226: }
227: }
228: return myComp.determineFormKey();
229: }
230:
231: /** It moves to the previous screen
232: * @return The FormKey for the previous screen.
233: */
234: public FormKey do_Previous_Clicked() {
235: MaintForm myForm = (MaintForm) form;
236: MaintComponent2 myComp = (MaintComponent2) myForm
237: .getComponent();
238:
239: //if (invokeDoValidateForScreen(myComp.getCurrentScreenCounter()))
240: // myComp.determineAndSetPreviousScreen();
241:
242: myComp.determineAndSetPreviousScreen();
243: return myComp.determineFormKey();
244: }
245:
246: /* This will invoke the 'public boolean doValidate{n}(HttpServletRequest request)' method
247: */
248: private boolean invokeDoValidateForScreen(int screenCounter) {
249: String methodName = "doValidate" + screenCounter;
250: Method method = null;
251: try {
252: method = form.getClass().getMethod(methodName,
253: new Class[] { HttpServletRequest.class });
254: if (method.getReturnType() != Boolean.TYPE)
255: throw new NoSuchMethodException();
256: } catch (NoSuchMethodException e) {
257: String str = "The method 'public boolean doValidate"
258: + screenCounter
259: + "(HttpServletRequest request) needs to be defined in the class "
260: + form.getClass().getName();
261: log.error(str, e);
262: throw new EventHandlerMissingRuntimeException(str);
263: }
264:
265: try {
266: Boolean output = (Boolean) method.invoke(form,
267: new Object[] { request });
268: return output.booleanValue();
269: } catch (Exception e) {
270: // should never happen
271: throw new RuntimeException(e);
272: }
273: }
274:
275: /* This will invoke the 'public boolean doValidate{n}(HttpServletRequest request)' method
276: * for all the screens of the component except the current screen.
277: */
278: private boolean invokeDoValidateForScreensOtherThanCurrent(
279: MaintComponent2 myComp) {
280: boolean valid = true;
281: for (int i = 0; i < myComp.getScreens().length; i++) {
282: if (i != myComp.getCurrentScreenCounter()) {
283: if (!invokeDoValidateForScreen(i))
284: valid = false;
285: }
286: }
287: return valid;
288: }
289:
290: /** Remove links from the HistoryNav, which are not supported in the update mode.
291: */
292: private void fixHistoryNavList(MaintComponent2 myComp) {
293: try {
294: List historyNavList = HistoryNav.obtainHistoryNav(request);
295: if (historyNavList != null && historyNavList.size() > 0) {
296: // create a Map of Screen.FormName/Screen objects
297: MaintComponent2.Screen[] screens = myComp.getScreens();
298: if (screens != null && screens.length > 0) {
299: Map screenMap = new HashMap();
300: for (int i = 0; i < screens.length; i++) {
301: MaintComponent2.Screen screen = screens[i];
302: screenMap.put(screen.getFormName(), screen);
303: }
304:
305: for (Iterator itr = historyNavList.iterator(); itr
306: .hasNext();) {
307: FormKey fk = (FormKey) itr.next();
308: // Check the FormKeys for our component only
309: if (myComp.getComponentId().equals(
310: fk.getComponentId())
311: && fk.getFormName() != null) {
312: MaintComponent2.Screen screen = (MaintComponent2.Screen) screenMap
313: .get(fk.getFormName());
314: if (screen != null
315: && !screen
316: .isAvailableInUpdateMode())
317: itr.remove();
318: }
319: }
320: }
321: }
322: request.setAttribute(HistoryNav.HISTORY_NAV_PARAMETER,
323: historyNavList);
324: } catch (Exception e) {
325: // do nothing
326: }
327: }
328: }
|