KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > methodhead > aikp > AikpAction


1 /*
2  * Copyright (C) 2006 Methodhead Software LLC. All rights reserved.
3  *
4  * This file is part of TransferCM.
5  *
6  * TransferCM is free software; you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation; either version 2 of the License, or (at your option) any later
9  * version.
10  *
11  * TransferCM is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * TransferCM; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
18  * Fifth Floor, Boston, MA 02110-1301 USA
19  */

20
21 package com.methodhead.aikp;
22
23 import java.text.DateFormat JavaDoc;
24 import java.text.ParseException JavaDoc;
25
26 import java.util.Date JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import javax.servlet.http.HttpServletRequest JavaDoc;
32 import javax.servlet.http.HttpServletResponse JavaDoc;
33
34 import com.methodhead.auth.AuthAction;
35 import com.methodhead.util.StrutsUtil;
36
37 import com.methodhead.persistable.PersistableException;
38 import com.methodhead.MhfException;
39
40 import org.apache.log4j.Logger;
41
42 import org.apache.struts.action.ActionForm;
43 import org.apache.struts.action.ActionForward;
44 import org.apache.struts.action.ActionMapping;
45 import org.apache.struts.action.ActionMessage;
46 import org.apache.struts.action.ActionMessages;
47
48 import org.apache.struts.validator.DynaValidatorForm;
49 import org.apache.struts.action.DynaActionForm;
50 import org.apache.commons.beanutils.DynaProperty;
51 import com.methodhead.util.StrutsUtil;
52 import com.methodhead.util.OperationContext;
53 import com.methodhead.auth.AuthUser;
54 import com.methodhead.auth.AuthUtil;
55 import org.apache.commons.lang.StringUtils;
56
57 /**
58 <p>
59   An Struts action with which to build a web interface for {@link
60   com.methodhead.aikp.AutoIntKeyPersistable
61   AutoIntKeyPersistable}s. This action will perform the following
62   operations: new, edit, save, and delete. Methods for these operations
63   and a number of support methods can be overloaded to achieve more
64   sophisticated behaviour.
65 </p>
66 <p>
67   Using this action requires at least this Struts configuration:
68 </p>
69 <xmp>
70   <form-bean
71     name ="yourObjectForm"
72     dynamic="true"
73     type ="com.methodhead.aikp.AikpForm">
74
75     <form-property name="action" type="java.lang.String"/>
76     <form-property name="id" type="java.lang.String"/>
77     <form-property name="submit" type="java.lang.String"/>
78     <form-property name="cancel" type="java.lang.String"/>
79     <form-property name="delete" type="java.lang.String"/>
80     <form-property name="list" type="java.util.List"/>
81
82     <!--
83       - properties for your object's field...
84       -->
85
86   </form-bean>
87
88   <action-mappings>
89
90     <action
91       path ="/yourObject"
92       type ="com.methodhead.aikp.AikpAction"
93       parameter="com.your.Policy"
94       name ="yourObjectForm"
95       scope ="request"
96       input ="/yourObject.jsp"
97       validate ="true">
98       <forward name="list" path="/yourObjectList.jsp"/>
99     </action>
100
101   </action-mappings>
102 </xmp>
103 <p>
104   In addition, the following message resources should be defined:
105 </p>
106 <xmp>
107   aikpaction.confirm=Delete {0}?
108   aikpaction.deleted=Deleted {0}.
109   aikpaction.saved=Saved {0}.
110 </xmp>
111 <p>
112   What operation is performed depends on the <tt>action</tt> parameter
113   (and sometimes the <tt>submit</tt> parameter). A minimal form looks
114   like:
115 </p>
116 <xmp>
117   <%@ page import="com.methodhead.aikp.AikpForm"%>
118
119   <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
120   <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
121
122
123   <html:errors/>
124   <html:form action="/yourObject">
125     <html:hidden property="id"/>
126     <html:hidden property="action"/>
127
128     <!--
129       - inputs for your object...
130       -->
131
132     <input type="submit" name="submit" value="Submit"></input> <%
133
134     if ( !form.get( "action" ).equals( "saveNew" ) ) { %>
135       <input type="submit" name="submit" value="Delete"></input> <%
136     } %>
137   </html:form>
138 </xmp>
139 <p>
140   A minimal list form looks like:
141 </p>
142 <xmp>
143   <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
144   <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
145   <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
146
147   <logic:iterate
148     name="yourObjectForm"
149     property="list"
150     id="yourObject"
151     type="com.your.Object">
152
153     <a HREF="yourObject.do?action=edit&id=<%= yourObject.get( "id" ) %>"><%= yourObject.get( "yourField" ) %></a><br>
154
155   </logic:iterate>
156 </xmp>
157  */

158 public abstract class AikpAction extends AuthAction {
159
160   // constructors /////////////////////////////////////////////////////////////
161

162   // constants ////////////////////////////////////////////////////////////////
163

164   // classes //////////////////////////////////////////////////////////////////
165

166   // methods //////////////////////////////////////////////////////////////////
167

168   /**
169    * Returns a new instance of the persistable to be managed by this action.
170    */

171   protected abstract AutoIntKeyPersistable createPersistable(
172     OperationContext op );
173
174   /**
175    * Returns the forward used when the persistable is saved; by default, a
176    * forward to input is returned.
177    */

178   protected ActionForward getForwardForSave(
179     OperationContext op,
180     Object JavaDoc policy ) {
181
182     return new ActionForward( op.mapping.getInput() );
183   }
184
185   /**
186    * Returns the forward used when the persistable is deleted; by default, a
187    * the <tt>status</tt> forward is returned.
188    */

189   protected ActionForward getForwardForDelete(
190     OperationContext op,
191     Object JavaDoc policy ) {
192
193     return op.mapping.findForward( "status" );
194   }
195
196   /**
197    * Populates the specified form property with the corresponding value from
198    * <tt>persistable</tt> using it's <tt>toString()</tt> method (unless it's a
199    * date, in which case it is formatted with <tt>DateFormat.getDateInstance(
200    * DateFormat.SHORT )</tt>).
201    */

202   protected static void populateFormProperty(
203     String JavaDoc name,
204     DynaActionForm form,
205     AutoIntKeyPersistable persistable ) {
206
207     if ( persistable.getDynaClass().getDynaProperty( name ).getType() ==
208            Date JavaDoc.class ) {
209       DateFormat JavaDoc dateFormat = DateFormat.getDateInstance( DateFormat.SHORT );
210       form.set( name, dateFormat.format( persistable.getDate( name ) ) );
211     }
212     else {
213       form.set( name, persistable.get( name ).toString() );
214     }
215   }
216
217   /**
218    * Populates the specified persistable property with the corresponding
219    * property from <tt>form</tt>, using {@link
220    * com.methodhead.persistable.Persistable#setAsObject
221    * Persistable.setAsObject()} to set the value.
222    */

223   protected static void populatePersistableField(
224     String JavaDoc name,
225     AutoIntKeyPersistable persistable,
226     DynaActionForm form ) {
227
228     persistable.setAsObject( name, form.get( name ) );
229   }
230
231   /**
232    * Populates the <tt>form</tt> with <tt>persistable</tt>'s field values. All
233    * form fields are expected to be of type <tt>String</tt>.
234    */

235   protected void populateForm(
236     DynaActionForm form,
237     AutoIntKeyPersistable persistable ) {
238
239     DynaProperty[] dynaProperties =
240       persistable.getDynaClass().getDynaProperties();
241
242     for ( int i = 0; i < dynaProperties.length; i++ ) {
243       populateFormProperty( dynaProperties[ i ].getName(), form, persistable );
244     }
245   }
246
247   /**
248    * Populates the <tt>persistable</tt>'s field values with <tt>form</tt>. All
249    * form fields are expected to be of type <tt>String</tt>. Date fields are
250    * parsed using a <tt>DateFormat</tt> as returned by
251    * <tt>DateFormat.getDateTimeInstance()</tt>.
252    */

253   protected void populatePersistable(
254     AutoIntKeyPersistable persistable,
255     DynaActionForm form ) {
256
257     DynaProperty[] dynaProperties =
258       persistable.getDynaClass().getDynaProperties();
259
260     for ( int i = 0; i < dynaProperties.length; i++ ) {
261       populatePersistableField(
262         dynaProperties[ i ].getName(), persistable, form );
263     }
264   }
265
266   /**
267    * Loads all elements from the database using {@link
268    * AutoIntKeyPersistable#loadAll loadAll()} and forwards to <tt>list</tt>.
269    */

270   protected ActionForward doList(
271     OperationContext op,
272     Object JavaDoc policy ) {
273
274     AutoIntKeyPersistable persistable = createPersistable( op );
275     op.form.set(
276       "list", persistable.loadAll( null, null ) );
277     return StrutsUtil.findForward( op.mapping, "list" );
278   }
279
280   /**
281    * Uses the persistable's default values to initialize the form; a forward to
282    * input is returned.
283    */

284   protected ActionForward doNew(
285     OperationContext op,
286     Object JavaDoc policy ) {
287
288     populateForm( op.form, createPersistable( op ) );
289     op.form.set( "action", "saveNew" );
290
291     return new ActionForward( op.mapping.getInput() );
292   }
293
294   /**
295    * Loads the persistable using the form's <tt>id</tt> property and uses its
296    * field values to initialize the form; a forward to input is returned.
297    */

298   protected ActionForward doEdit(
299     OperationContext op,
300     Object JavaDoc policy ) {
301
302     AutoIntKeyPersistable persistable = createPersistable( op );
303     persistable.load( new IntKey( op.form.get( "id" ) ) );
304     populateForm( op.form, persistable );
305     op.form.set( "action", "save" );
306
307     return new ActionForward( op.mapping.getInput() );
308   }
309
310   /**
311    * <p>
312    * Called when an persistable is to be deleted, adds the
313    * <tt>aikpaction.confirm</tt> to the action's messages (accessible by the
314    * Struts <tt>html:messages</tt> tag) and returns a forward to
315    * <tt>confirm</tt>. <b>Note:</b> The persistable itself is argument 0 to
316    * the message, so make sure its <tt>toString()</tt> method returns
317    * something reasonable if you include <tt>{0}</tt> in your message.
318    * </p>
319    */

320   protected ActionForward doConfirm(
321     OperationContext op,
322     Object JavaDoc policy ) {
323
324     AutoIntKeyPersistable persistable = createPersistable( op );
325     persistable.load( new IntKey( op.form.get( "id" ) ) );
326
327     StrutsUtil.addMessage(
328       op.request, "aikpaction.confirm", persistable, null, null );
329
330     op.form.set( "action", "delete" );
331
332     return StrutsUtil.findForward( op.mapping, "confirm" );
333   }
334
335   /**
336    * Creates the persistable, sets its fields and calls its <tt>saveNew()</tt>
337    * method. The form is then repopulated with values from the saved
338    * persistable. The <tt>aikpaction.saved</tt> message is added to the action
339    * and a forward to input is returned.
340    */

341   protected ActionForward doSaveNew(
342     OperationContext op,
343     Object JavaDoc policy ) {
344
345     AutoIntKeyPersistable persistable = createPersistable( op );
346     populatePersistable( persistable, op.form );
347     persistable.saveNew();
348     populateForm( op.form, persistable );
349     StrutsUtil.addMessage(
350       op.request, "aikpaction.saved", persistable, null, null );
351     op.form.set( "action", "save" );
352
353     return getForwardForSave( op, policy );
354   }
355
356   /**
357    * Loads the persistable using the form's <tt>id</tt> property, sets its
358    * fields, and calls its <tt>save()</tt> method. The form is then
359    * repopulated with values from the saved persistable. The
360    * <tt>aikpaction.saved</tt> message is added to the action and a forward to
361    * input is returned.
362    */

363   protected ActionForward doSave(
364     OperationContext op,
365     Object JavaDoc policy ) {
366
367     AutoIntKeyPersistable persistable = createPersistable( op );
368     persistable.load( new IntKey( op.form.get( "id" ) ) );
369     populatePersistable( persistable, op.form );
370     persistable.save();
371     populateForm( op.form, persistable );
372     StrutsUtil.addMessage(
373       op.request, "aikpaction.saved", persistable, null, null );
374     op.form.set( "action", "save" );
375
376     return getForwardForSave( op, policy );
377   }
378
379   /**
380    * Like <tt>doEdit()</tt>, <tt>doCancel()</tt> loads the persistable using
381    * the form's <tt>id</tt> property, populates the form, adds the
382    * <tt>aikpaction.cancelled</tt> message to the action, and returns a forward
383    * to input.
384    * @deprecated Use {@link #doCancelDelete}
385    */

386   protected ActionForward doCancel(
387     OperationContext op,
388     Object JavaDoc policy ) {
389
390     AutoIntKeyPersistable persistable = createPersistable( op );
391     persistable.load( new IntKey( op.form.get( "id" ) ) );
392     populateForm( op.form, persistable );
393     op.form.set( "action", "save" );
394     StrutsUtil.addMessage(
395       op.request, "aikpaction.cancelled", persistable, null, null );
396
397     return new ActionForward( op.mapping.getInput() );
398   }
399
400   /**
401    * Like <tt>doEdit()</tt>, <tt>doCancelDelete()</tt> loads the persistable using
402    * the form's <tt>id</tt> property, populates the form, adds the
403    * <tt>aikpaction.cancelled</tt> message to the action, and returns a forward
404    * to input.
405    */

406   protected ActionForward doCancelDelete(
407     OperationContext op,
408     Object JavaDoc policy ) {
409
410     AutoIntKeyPersistable persistable = createPersistable( op );
411     persistable.load( new IntKey( op.form.get( "id" ) ) );
412     populateForm( op.form, persistable );
413     op.form.set( "action", "save" );
414     StrutsUtil.addMessage(
415       op.request, "aikpaction.cancelled", persistable, null, null );
416
417     return new ActionForward( op.mapping.getInput() );
418   }
419
420   /**
421    * Like <tt>doEdit()</tt>, <tt>doCancelSave()</tt> loads the persistable using
422    * the form's <tt>id</tt> property, populates the form, adds the
423    * <tt>aikpaction.cancelled</tt> message to the action, and returns a forward
424    * to input.
425    */

426   protected ActionForward doCancelSave(
427     OperationContext op,
428     Object JavaDoc policy ) {
429
430     AutoIntKeyPersistable persistable = createPersistable( op );
431     persistable.load( new IntKey( op.form.get( "id" ) ) );
432     populateForm( op.form, persistable );
433     op.form.set( "action", "save" );
434     StrutsUtil.addMessage(
435       op.request, "aikpaction.cancelled", persistable, null, null );
436
437     return new ActionForward( op.mapping.getInput() );
438   }
439
440   /**
441    * Simply calls <tt>doList()</tt>
442    */

443   protected ActionForward doCancelSaveNew(
444     OperationContext op,
445     Object JavaDoc policy ) {
446
447     return doList( op, policy );
448   }
449
450   /**
451    * <p>
452    * Loads the persistable using the form's <tt>id</tt> property, and invokes
453    * its <tt>delete()</tt> method; a the <tt>status</tt> forward is returned.
454    * </p>
455    * <p>
456    * The <tt>aikpaction.deleted</tt> message is added to the action's messages
457    * (accessible by the Struts <tt>html:messages</tt> tag). <b>Note:</b> The
458    * persistable itself is argument 0 to the message, so make sure its
459    * <tt>toString()</tt> method returns something reasonable if you include
460    * <tt>{0}</tt> in your message.
461    * </p>
462    */

463   protected ActionForward doDelete(
464     OperationContext op,
465     Object JavaDoc policy ) {
466
467     AutoIntKeyPersistable persistable = createPersistable( op );
468     persistable.load( new IntKey( op.form.get( "id" ) ) );
469     persistable.delete();
470
471     StrutsUtil.addMessage(
472       op.request, "aikpaction.deleted", persistable, null, null );
473
474     return getForwardForDelete( op, policy );
475   }
476
477   /**
478    * Executes the action, calling the appropriate method (<tt>doNew()</tt>,
479    * <tt>doEdit()</tt>, etc.) according to the form's properties.
480    */

481   public ActionForward doExecute(
482     ActionMapping mapping,
483     ActionForm form,
484     HttpServletRequest JavaDoc request,
485     HttpServletResponse JavaDoc response ) {
486
487     DynaValidatorForm dynaForm = ( DynaValidatorForm )form;
488     Object JavaDoc policy = StrutsUtil.getPolicy( mapping );
489     AuthUser user = AuthUtil.getUser( request );
490
491     OperationContext op =
492       new OperationContext( mapping, dynaForm, request, response, user );
493
494     String JavaDoc aikpaction = dynaForm.get( "action" ).toString();
495
496     if ( "list".equals( aikpaction ) ) {
497       return doList( op, policy );
498     }
499
500     if ( "new".equals( aikpaction ) ) {
501       return doNew( op, policy );
502     }
503
504     else if ( "edit".equals( aikpaction ) ) {
505       return doEdit( op, policy );
506     }
507
508     else if ( "saveNew".equals( aikpaction ) ) {
509       if ( !StringUtils.isBlank( ( String JavaDoc )dynaForm.get( "cancel" ) ) )
510         return doCancelSaveNew( op, policy );
511       else
512         return doSaveNew( op, policy );
513     }
514
515     else if ( "save".equals( aikpaction ) ) {
516
517       if ( !StringUtils.isBlank( ( String JavaDoc )dynaForm.get( "cancel" ) ) )
518         return doCancelSave( op, policy );
519       else if ( !StringUtils.isBlank( ( String JavaDoc )dynaForm.get( "delete" ) ) )
520         return doConfirm( op, policy );
521       else
522         return doSave( op, policy );
523     }
524
525     else if ( "delete".equals( aikpaction ) ) {
526
527       if ( !StringUtils.isBlank( ( String JavaDoc )dynaForm.get( "cancel" ) ) )
528         return doCancelDelete( op, policy );
529       else
530         return doDelete( op, policy );
531     }
532
533     else {
534       throw new MhfException( "Unexpected aikpaction \"" + aikpaction + "\"" );
535     }
536   }
537
538   // properties ///////////////////////////////////////////////////////////////
539

540   // attributes ///////////////////////////////////////////////////////////////
541

542   Logger logger_ = Logger.getLogger( AikpAction.class );
543 }
544
Popular Tags