KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > controller > ControllerResponse


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64 package com.jcorporate.expresso.core.controller;
65
66 import com.jcorporate.expresso.core.controller.session.SimplePersistentSession;
67 import com.jcorporate.expresso.core.dataobjects.DataObjectMetaData;
68 import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCObjectMetaData;
69 import com.jcorporate.expresso.core.db.DBException;
70 import com.jcorporate.expresso.core.dbobj.DBField;
71 import com.jcorporate.expresso.core.dbobj.DBObject;
72 import com.jcorporate.expresso.core.i18n.Messages;
73 import com.jcorporate.expresso.core.misc.StringUtil;
74 import com.jcorporate.expresso.kernel.util.ClassLocator;
75 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
76 import org.apache.log4j.Logger;
77 import org.apache.struts.Globals;
78 import org.apache.struts.action.ActionError;
79 import org.w3c.dom.NamedNodeMap JavaDoc;
80 import org.w3c.dom.Node JavaDoc;
81 import org.w3c.dom.NodeList JavaDoc;
82
83 import javax.servlet.http.HttpServletRequest JavaDoc;
84 import java.io.Serializable JavaDoc;
85 import java.util.Enumeration JavaDoc;
86 import java.util.HashMap JavaDoc;
87 import java.util.Hashtable JavaDoc;
88 import java.util.Iterator JavaDoc;
89 import java.util.Locale JavaDoc;
90 import java.util.Map JavaDoc;
91 import java.util.Stack JavaDoc;
92 import java.util.Vector JavaDoc;
93
94
95 /**
96  * A ControllerResponse object contains the vector of Inputs, Outputs and
97  * Transitions that results from a call to "newState(String)" for a particular
98  * controller.
99  * <p>Once a state has been processed, the ControllerResponse object is usually
100  * saved in the Servlet Request Context where it can be retrieved by JSP tags
101  * by querying the request context for an object named &quot;controllerResponse&quot;
102  * </p>
103  */

104 public class ControllerResponse implements Serializable JavaDoc {
105     /**
106      * The log4j logger.
107      */

108     private static final transient Logger log = Logger.getLogger(ControllerResponse.class);
109
110     /**
111      * The ControllerRequest object set for this response
112      */

113     protected ControllerRequest myRequest = null;
114
115
116     /**
117      * Object for setting the Locale object
118      */

119     protected Locale JavaDoc responseLocale = null;
120
121     /**
122      * A name to value map of blocks
123      */

124     protected HashMap JavaDoc blockCache = null;
125
126     /**
127      * The name to value map for inputs
128      */

129     protected HashMap JavaDoc inputCache = null;
130
131     /**
132      * A name to value map for outputs
133      */

134     protected HashMap JavaDoc outputCache = null;
135
136     /**
137      * A name to value map for Transitions
138      */

139     protected HashMap JavaDoc transitionCache = null;
140
141     /**
142      * The current state
143      */

144     protected State currentState = null;
145
146     /**
147      * The classname of this controller
148      */

149     protected String JavaDoc myControllerClass = null;
150
151     /**
152      * The data context for this controller response
153      */

154     protected String JavaDoc dataContext = "default";
155
156     /**
157      * The request path
158      */

159     protected String JavaDoc myRequestPath = null;
160
161     /**
162      * The requested state name
163      */

164     protected String JavaDoc requestedState = null;
165
166     /**
167      * The resulting style code
168      */

169     protected String JavaDoc style = null;
170
171     /**
172      * The title of the ControllerResponse
173      */

174     protected String JavaDoc title = null;
175
176     /**
177      * A list of all blocks in the order they were added to the response
178      */

179     protected Vector JavaDoc blockCacheOrdered = null;
180
181     /**
182      * A list of all inputs as added to the response
183      */

184     protected Vector JavaDoc inputCacheOrdered = null;
185
186     /**
187      * A list of all outputs in the order they were added to the response
188      */

189     protected Vector JavaDoc outputCacheOrdered = null;
190
191     /**
192      * A list of all transitions in the order they were added to the response
193      */

194     protected Vector JavaDoc transitionCacheOrdered = null;
195
196
197     /**
198      * NOTE: Any Controller that must access the HttpServletResponse object
199      * available from the ControllerRequest object and handle making it's own
200      * response to the client (e.g. a custom mime type, multimedia stream,
201      * etc), should call setCustomResponse(true) to tell the caller that it
202      * should not try to format the Outputs, Inputs, and Transitions from this
203      * controller call. Use only when absolutely required!
204      */

205     protected boolean customResponse = false;
206
207     /**
208      * Provides a hierarchy of schemas to check for messages bundles. The top
209      * of the stack is the lowest on the heirarchy and should be checked first
210      * for Messages, etc... then proceed on down the stack.
211      */

212     private java.util.Stack JavaDoc schemaStack;
213
214
215     /**
216      * Default constructor for the controller response
217      */

218     public ControllerResponse() {
219         super();
220     }
221
222     /**
223      * Set the named attribute of this Controller to the given value
224      *
225      * @param attrib The name of an "attribtue" for this ControllerElement item
226      * @param val The value for this attribute
227      * @throws ControllerException upon error
228      */

229     public void setAttribute(String JavaDoc attrib, String JavaDoc val)
230             throws ControllerException {
231         getRequest().setAttrib(attrib, val);
232     }
233
234     /* setAttributes(String, String) */
235
236     /**
237      * Retrieve an attribute as specified from the request
238      *
239      * @param attrib The name of an "attribute" for this ControllerElement item
240      * @return the attribute value (may be null)
241      * @throws ControllerException upon error
242      */

243     public String JavaDoc getAttribute(String JavaDoc attrib) throws ControllerException {
244         return (String JavaDoc) getRequest().getAttrib(attrib);
245     }
246
247     /* setAttributes(String, String) */
248
249     /**
250      * Set the attribute Map
251      *
252      * @param attributes the supplied attribute values
253      * @throws ControllerException upon error
254      */

255     public void setAttributes(Map JavaDoc attributes) throws ControllerException {
256         getRequest().setAttributes(attributes);
257     }
258
259     /* setAttributes(Map) */
260
261     /**
262      * Get the attribute Map
263      *
264      * @return an java.util.Map of Strings
265      * @throws ControllerException upon error
266      */

267     public Map JavaDoc getAttributes() throws ControllerException {
268         return getRequest().getAttributes();
269     }
270
271     /* getAttributes() */
272
273     /**
274      * Get a specific block.
275      *
276      * @param blockName the name of the Block
277      * @return Block instance or null if no block found.
278      * @throws ControllerException upon error
279      */

280     public Block getBlock(String JavaDoc blockName) throws ControllerException {
281         validState();
282
283         if (blockCache != null) {
284             return (Block) blockCache.get(blockName);
285         }
286
287         return null;
288     }
289
290     /* getBlock(String) */
291
292     /**
293      * Return the vector of Blocks for this controller state to the client
294      *
295      * @return Vector of Block objects
296      */

297     public final Vector JavaDoc getBlocks() {
298         validState();
299
300         if (blockCacheOrdered != null) {
301             return blockCacheOrdered;
302         }
303
304         return null;
305     }
306
307     /* getBlocks() */
308
309     /**
310      * Set public so that test classes can get into it.
311      *
312      * @param newClass the new controller class name
313      */

314     public void setControllerClass(String JavaDoc newClass) {
315         myControllerClass = newClass;
316     }
317
318     /**
319      * Retrieve the controller class name
320      *
321      * @return java.lang.String, the name of the controller class
322      */

323     public String JavaDoc getControllerClass() {
324         return myControllerClass;
325     }
326
327     /**
328      * Return the current State object, based on the state we last transitioned
329      * into
330      *
331      * @return java.lang.String the current state
332      */

333     public State getCurrentState() {
334         return currentState;
335     }
336
337     /**
338      * Return a specific Input item.
339      *
340      * @param inputName the name of the input to retrieve
341      * @return Input
342      */

343     public final Input getInput(String JavaDoc inputName) {
344         validState();
345
346         if (inputCache != null) {
347             return (Input) inputCache.get(inputName);
348         }
349
350         return null;
351     }
352
353     /* getInput(String) */
354
355     /**
356      * Return the vector of input items for this controller state to the
357      * client.
358      *
359      * @return java.util.Vector of Input objects
360      */

361     public final Vector JavaDoc getInputs() {
362         validState();
363
364         if (inputCacheOrdered != null) {
365             return inputCacheOrdered;
366         }
367
368         return new Vector JavaDoc();
369     }
370
371     /* getInptus() */
372
373     /**
374      * If absolutely necessary the Controller can access the ServletResponse
375      * object directly from the ServletControllerRequest object, if the
376      * controller is running in a servlet environment. For example, if a
377      * custom mime-type must be set, a multimedia data stream returned, or
378      * other special processing. If this is done, the method below should be
379      * called so that the "container" that called this Controller knows that
380      * the response object has been manipulated, and that it should not
381      * perform the normal processing of Inputs, Outputs and Transitions.
382      *
383      * @param newCustom set to true if you don't want Struts to render the
384      * response through JSP
385      */

386     public void setCustomResponse(boolean newCustom) {
387         customResponse = newCustom;
388     }
389
390     /**
391      * Did this Controller call directly manipulate the ServletResponse and
392      * handle it's own output to the client? (This is NOT recommended)
393      *
394      * @return true if the controller IS sending a custom response
395      */

396     public boolean isCustomResponse() {
397         return customResponse;
398     }
399
400     /**
401      * Set the db name of this ControllerResponse
402      *
403      * @param newDBName the new database name
404      * @throws ControllerException upon error
405      */

406     public synchronized void setDBName(String JavaDoc newDBName)
407             throws ControllerException {
408         this.dataContext = newDBName;
409     }
410
411     /**
412      * Get the database from the request, if there is a request available
413      *
414      * @return the database context that the system is set for.
415      * @throws ControllerException upon error
416      */

417     public String JavaDoc getDBName() throws ControllerException {
418         return getDataContext();
419     } /* getDBName() */
420
421     /**
422      * Get the database from the request, if there is a request available
423      *
424      * @return the database context that the system is set for.
425      * @throws ControllerException upon error
426      */

427     public String JavaDoc getDataContext() throws ControllerException {
428         if (dataContext != null) {
429             return dataContext;
430         }
431
432         return "default";
433     }
434
435     /**
436      * Automatically find all input fields and put them in the formCache.
437      * Creation date: (7/19/00 7:22:11 PM) author: Adam Rossi,
438      * PlatinumSolutions
439      *
440      * @throws ControllerException upon error
441      */

442     public void setFormCache() throws ControllerException {
443         getDefaultForm().saveForm(getRequest());
444     }
445
446     /* setFormCache() */
447
448     /**
449      * Save a name/value pair to the formCache. Creation date: (7/20/00 1:14:14
450      * PM)
451      *
452      * @param fieldName java.lang.String
453      * @param fieldValue java.lang.String
454      * @throws ControllerException upon error
455      */

456     public void setFormCache(String JavaDoc fieldName, String JavaDoc fieldValue)
457             throws ControllerException {
458         getDefaultForm().setField(fieldName, fieldValue);
459     }
460
461     /* setFormCache(String, String) */
462
463     /**
464      * Get the entire formResponseCache Hashtable Creation date: (7/19/00
465      * 7:18:51 PM) author: Adam Rossi, PlatinumSolutions
466      *
467      * @return Hashtable of ControllerElements
468      * @throws ControllerException upon error
469      */

470     public Hashtable JavaDoc getFormCache() throws ControllerException {
471         return getDefaultForm().getFields();
472     }
473
474     /* getFormCache() */
475
476     /**
477      * Fetch the requested field from the response cache. Return an empty
478      * string if not found. Creation date: (7/19/00 7:18:51 PM) author: Adam
479      * Rossi, PlatinumSolutions
480      *
481      * @param fieldName java.lang.String
482      * @return java.lang.String
483      * @throws ControllerException upon error
484      */

485     public String JavaDoc getFormCache(String JavaDoc fieldName) throws ControllerException {
486         return StringUtil.notNull(getDefaultForm().getField(fieldName));
487     }
488
489     /* getFormCache(String) */
490
491     /**
492      * Allows the generic setting of form attributes.
493      *
494      * @param fieldName the name of the field attribute to set
495      * @param fieldAttribute the attribute to set it to
496      * @throws ControllerException if the fieldName is blank or null
497      */

498     public void setFormCacheAttribute(String JavaDoc fieldName, Object JavaDoc fieldAttribute)
499             throws ControllerException {
500         getDefaultForm().setAttribute(fieldName, fieldAttribute);
501     }
502
503     /**
504      * Gets the saved cache attribute.
505      *
506      * @param fieldName the name of the field to retrieve
507      * @return Object the cache attribute
508      * @throws ControllerException if the fieldName specified is blank or null.
509      */

510     public Object JavaDoc getFormCacheAttribute(String JavaDoc fieldName)
511             throws ControllerException {
512         return getDefaultForm().getAttribute(fieldName);
513     }
514
515     /**
516      * Retrieve the Locale for the request
517      *
518      * @return Locale object or default locale if noen was set
519      * @throws ControllerException upon error
520      */

521     public Locale JavaDoc getLocale() throws ControllerException {
522         if (responseLocale == null) {
523             return Locale.getDefault();
524         }
525
526         return responseLocale;
527     }
528
529     /**
530      * Retrieve the Inputs as a map so that JSTL can cope with navigating the
531      * ControllerResponse through a named fashion
532      *
533      * @return java.util.Map
534      * @throws ControllerException upon error
535      */

536     public Map JavaDoc getNamedInputs() throws ControllerException {
537         validState();
538
539         return inputCache;
540     }
541
542     /**
543      * Get a specific output item.
544      *
545      * @param outputName the name of the output to retrieve
546      * @return <code>Output</code>
547      * @throws ControllerException upon error
548      */

549     public Output getOutput(String JavaDoc outputName) throws ControllerException {
550         validState();
551
552         if (outputCache != null) {
553             return (Output) outputCache.get(outputName);
554         }
555
556         return null;
557     }
558
559     /* getOutput(String) */
560
561     /**
562      * Get the contents of a particular Output item.
563      *
564      * @param outputName the name of the output to retrieve
565      * @return java.lang.String the content of the named output
566      * @throws ControllerException If there is no such output
567      */

568     public String JavaDoc getOutputContent(String JavaDoc outputName)
569             throws ControllerException {
570         validState();
571
572         Output o = getOutput(outputName);
573
574         if (o == null) {
575             return ("No Such Output named '" + outputName + "'");
576         }
577
578         return o.getContent();
579     }
580
581     /* getOutputContent(String) */
582
583     /**
584      * Get the named output, but throw if it's not found.
585      *
586      * @param outputName the name of the output to retrieve
587      * @return Output object
588      * @throws ControllerException if the output cannot be found
589      */

590     public Output getOutputRequired(String JavaDoc outputName)
591             throws ControllerException {
592         Output o = getOutput(outputName);
593
594         if (o == null) {
595             throw new ControllerException("There is no output named '" +
596                     outputName + "'");
597         }
598
599         return o;
600     }
601
602     /* getOutputRequired(String) */
603
604     /**
605      * The client calls this method for each state to determine what output to
606      * show to the user.
607      *
608      * @return Vector of Output objects
609      */

610     public final Vector JavaDoc getOutputs() {
611         validState();
612
613         if (outputCacheOrdered != null) {
614             return outputCacheOrdered;
615         }
616
617         return new Vector JavaDoc();
618     }
619
620     /* getOutputs() */
621
622     /**
623      * Retrieve the error collection for this response
624      *
625      * @return ErrorCollection (may be null)
626      * @throws ControllerException upon error reading from the session
627      */

628     public ErrorCollection getErrors() throws ControllerException {
629         ErrorCollection errs = (ErrorCollection) getRequest().getSession()
630                 .getAttribute(Globals.ERROR_KEY);
631
632         return errs;
633     }
634
635     /**
636      * Retrieve the parameter
637      *
638      * @param paramName the name of the parameter to retrieve
639      * @return java.lang.String or null if the parameter doesn't exist
640      * @throws ControllerException upon error
641      */

642     public String JavaDoc getParameter(String JavaDoc paramName) throws ControllerException {
643         return getRequest().getParameter(paramName);
644     }
645
646     /**
647      * Set the controller request - this is done as part of the processing of
648      * the controller so that the response has access to all of the request
649      * fields
650      *
651      * @param newRequest the new controller request.
652      * @throws ControllerException upon error
653      */

654     public void setRequest(ControllerRequest newRequest)
655             throws ControllerException {
656         if (newRequest == null) {
657             throw new ControllerException("You cannot set a null Controller Request here");
658         }
659
660         myRequest = newRequest;
661         requestedState = StringUtil.notNull(myRequest.getParameter(Controller.STATE_PARAM_KEY));
662         this.dataContext = newRequest.getDataContext();
663         this.responseLocale = newRequest.getLocale();
664     }
665
666     /**
667      * Retrieve the ControllerRequest associated with this object
668      *
669      * @return <code>ControllerRequest</code> object
670      * @throws IllegalArgumentException if the setRequest() object has not
671      * been set yet.
672      */

673     public ControllerRequest getRequest() {
674         if (myRequest == null) {
675             throw new IllegalStateException JavaDoc("ControllerResponse.setRequest() must be set before calling getRequest()");
676         }
677         return myRequest;
678     }
679
680
681     /**
682      * Sets the request path
683      *
684      * @param newPath the URL path without the .do at the end of it.
685      */

686     public synchronized void setRequestPath(String JavaDoc newPath) {
687         myRequestPath = newPath + ".do";
688     }
689
690     /**
691      * Returns the request path set earlier. (Note we moved the +".do" to
692      * setRequestPath because we set less often than we get, so we do less
693      * string allocations)
694      *
695      * @return java.lang.String
696      */

697     public String JavaDoc getRequestPath() {
698         return myRequestPath;
699     }
700
701     /**
702      * Retrieve the requested state
703      *
704      * @return state name requested
705      */

706     public String JavaDoc getRequestedState() {
707         return requestedState;
708     }
709
710     /**
711      * Get the name of the schema object that this Controller belongs to
712      *
713      * @return java.lang.String, the Schema classname associated with this
714      * ControllerResponse.
715      */

716     public String JavaDoc getSchema() {
717         if ((schemaStack == null) || schemaStack.isEmpty()) {
718             return "com.jcorporate.expresso.core.ExpressoSchema";
719         } else {
720             return (String JavaDoc) schemaStack.peek();
721         }
722     }
723
724     /* getSchema() */
725
726     /**
727      * Sets the schema stack for message bundle retrieval
728      *
729      * @param schemaStack the Stack to use.
730      */

731     public void setSchemaStack(java.util.Stack JavaDoc schemaStack) {
732         this.schemaStack = schemaStack;
733     }
734
735     /**
736      * Retrieve the schema stack. Walk up the schema stack to check a
737      * hierarchy of MessagesBundles for a possible message
738      *
739      * @return java.util.Stack
740      */

741     public java.util.Stack JavaDoc getSchemaStack() {
742         if (schemaStack == null) {
743             schemaStack = new Stack JavaDoc();
744         }
745
746         if (schemaStack.isEmpty()) {
747             schemaStack.push(com.jcorporate.expresso.core.ExpressoSchema.class.getName());
748         }
749
750         return schemaStack;
751     }
752
753     /**
754      * retrieve an appropriate localized string from the
755      * correct Schema object. This version of the call is overridden with more
756      * sophisticated versions in DBController (which knows the username)
757      *
758      * @param stringCode the String code to retrieve
759      * @param args the formatting arguments
760      * @return translated string or stringCode if not found
761      * @throws ControllerException upon error
762      */

763     public String JavaDoc getString(String JavaDoc stringCode, Object JavaDoc[] args)
764             throws ControllerException {
765         StringUtil.assertNotBlank(stringCode, "You must specify a string key");
766
767         if (myRequest == null) {
768             log.error("No request object was established for this controller response, " +
769                     " for controller class '" +
770                     StringUtil.notNull(myControllerClass) + "'");
771
772             return null;
773         }
774
775         Stack JavaDoc s = this.getSchemaStack();
776         try {
777             return Messages.getString(s, this.responseLocale, stringCode, args);
778         } catch (IllegalArgumentException JavaDoc ex) {
779             throw new IllegalArgumentException JavaDoc("Unable to locate string " + stringCode + " for any schema");
780         }
781     }
782
783
784     /**
785      * Convenience version of the above with no arguments.
786      *
787      * @param stringCode the string code to retrieve
788      * @return java.lang.String
789      * @throws ControllerException upon error
790      */

791     public String JavaDoc getString(String JavaDoc stringCode) throws ControllerException {
792         Object JavaDoc[] args = {};
793
794         return getString(stringCode, args);
795     }
796
797     /* getString(String) */
798
799     /**
800      * Convenience method of getString(String,Object[]) where first (and only) param of args will be string1
801      *
802      * @param stringCode the string code to retrieve
803      * @param string1 a single parameter for message format (the first argument to replace)
804      * @return translated string or stringCode if not found
805      * @throws ControllerException upon error
806      */

807     public String JavaDoc getString(String JavaDoc stringCode, String JavaDoc string1)
808             throws ControllerException {
809         Object JavaDoc[] args = {string1};
810
811         return getString(stringCode, args);
812     }
813
814     /**
815      * Convenience method to retrieve the string with two formatting parameters
816      *
817      * @param stringCode the string code to retrieve
818      * @param string1 formatting parameter one
819      * @param string2 formatting parameter two
820      * @return java.lang.String
821      * @throws ControllerException upon error
822      */

823     public String JavaDoc getString(String JavaDoc stringCode, String JavaDoc string1, String JavaDoc string2)
824             throws ControllerException {
825         Object JavaDoc[] args = {string1, string2};
826
827         return getString(stringCode, args);
828     }
829
830     /**
831      * Retrieve a localized string with 3 formatting parameters
832      *
833      * @param stringCode the string code to retrieve
834      * @param string1 formatting parameter one
835      * @param string2 formatting parameter two
836      * @param string3 formatting parameter number three
837      * @return java.lang.String
838      * @throws ControllerException upon error
839      */

840     public String JavaDoc getString(String JavaDoc stringCode, String JavaDoc string1, String JavaDoc string2,
841                             String JavaDoc string3) throws ControllerException {
842         Object JavaDoc[] args = {string1, string2, string3};
843
844         return getString(stringCode, args);
845     }
846
847     /**
848      * Retrieve a localized string with 4 formatting parameters
849      *
850      * @param stringCode the string code to retrieve
851      * @param string1 formatting parameter one
852      * @param string2 formatting parameter two
853      * @param string3 formatting parameter number three
854      * @param string4 formatting parameter number four
855      * @return java.lang.String
856      * @throws ControllerException upon error
857      */

858     public String JavaDoc getString(String JavaDoc stringCode, String JavaDoc string1, String JavaDoc string2,
859                             String JavaDoc string3, String JavaDoc string4) throws ControllerException {
860         Object JavaDoc[] args = {string1, string2, string3, string4};
861
862         return getString(stringCode, args);
863     }
864
865     /**
866      * Use setStyle to specify a different Struts ActionForward to send the
867      * rendering to rather then the default one.
868      *
869      * @param newStyle the new style string. Must be in one of the
870      * struts-config.xml files.
871      */

872     public void setStyle(String JavaDoc newStyle) {
873         style = newStyle;
874     }
875
876     /**
877      * Retrieve the style that the controller response is set to
878      *
879      * @return java.lang.String
880      */

881     public String JavaDoc getStyle() {
882         return style;
883     }
884
885     /**
886      * Sets the title of the controller
887      *
888      * @param newTitle the new title for the controller
889      */

890     public void setTitle(String JavaDoc newTitle) {
891         title = newTitle;
892     }
893
894     /**
895      * Assemble a ControllerResponse from an xml document (may be document
896      * fragment).
897      *
898      * @param n a DOM node to assemble the response from.
899      * @return an instantiated ControllerResponse object
900      * @throws ControllerException upon error
901      */

902     public static ControllerResponse fromXML(Node JavaDoc n) throws ControllerException {
903         //If we're at the root node, then it'll be doc instead of input.
904
if (n.getNodeName().equals("#document")) {
905             return fromXML(n.getChildNodes().item(0));
906         }
907
908         if (!n.getNodeName().equals("controller-response")) {
909             throw new ControllerException("Failed To Get DOM Node of " +
910                     " type 'controller-response' Got " + n.getNodeName() +
911                     " instead.");
912         }
913
914         ControllerResponse cr = new ControllerResponse();
915
916         //
917
//Since we technically need a controller request to be able to deal with
918
//error collection. Then we need to create a dummy session for such
919
//usage.
920
//
921
SimplePersistentSession session = new SimplePersistentSession();
922         ControllerRequest request = new ControllerRequest();
923         request.setUid(3);
924         request.setSession(session);
925         cr.setRequest(request);
926
927         //
928
// Load The Controller Response Attributes
929
//
930
NamedNodeMap JavaDoc attributes = n.getAttributes();
931         Node JavaDoc oneAttribute = attributes.getNamedItem("name");
932
933         if (oneAttribute != null) {
934             cr.setControllerClass(oneAttribute.getNodeValue());
935         }
936
937         oneAttribute = attributes.getNamedItem("title");
938
939         if (oneAttribute != null) {
940             cr.setTitle(oneAttribute.getNodeValue());
941         }
942
943         oneAttribute = attributes.getNamedItem("requestedState");
944
945         if (oneAttribute != null) {
946             cr.requestedState = oneAttribute.getNodeValue();
947         }
948
949         oneAttribute = attributes.getNamedItem("style");
950
951         if (oneAttribute != null) {
952             cr.setStyle(oneAttribute.getNodeValue());
953         }
954
955         try {
956             NodeList JavaDoc children = n.getChildNodes();
957
958             for (int index = 0; index < children.getLength(); index++) {
959                 Node JavaDoc oneChild = children.item(index);
960                 String JavaDoc nodeName = oneChild.getNodeName();
961
962                 if (nodeName != null) {
963                     if (nodeName.equals("block")) {
964                         Block b = (Block) Block.fromXML(oneChild);
965
966                         if (b != null) {
967                             cr.addBlock(b);
968                         }
969                     } else if (nodeName.equals("input")) {
970                         Input i = (Input) Input.fromXML(oneChild);
971
972                         if (i != null) {
973                             cr.addInput(i);
974                         }
975                     } else if (nodeName.equals("output")) {
976                         Output o = (Output) Output.fromXML(oneChild);
977
978                         if (o != null) {
979                             cr.addOutput(o);
980                         }
981                     } else if (nodeName.equals("transition")) {
982                         Transition t = (Transition) Transition.fromXML(oneChild);
983
984                         if (t != null) {
985                             cr.addTransition(t);
986                         }
987                     }
988                 }
989
990                 /* if nodeName != null */
991             }
992
993             /* For each child node */
994         } catch (ClassCastException JavaDoc cce) {
995             cce.printStackTrace();
996             throw new ControllerException("Error Loading Subobjects " +
997                     "for ControllerResponse: " + cce.getMessage());
998         }
999
1000        return cr;
1001    }
1002
1003    /**
1004     * get title
1005     * title and name are synonymous--easier for JSTL
1006     *
1007     * @return java.lang.String The Title of the controller
1008     */

1009    public String JavaDoc getName() {
1010        return getTitle();
1011    }
1012
1013    /**
1014     * get title
1015     * title and name are synonymous--easier for JSTL
1016     *
1017     * @return java.lang.String The Title of the controller
1018     */

1019    public String JavaDoc getTitle() {
1020        try {
1021            String JavaDoc temp = getString(title);
1022
1023            if (temp == null) {
1024                temp = title;
1025            }
1026
1027            return temp;
1028        } catch (Exception JavaDoc e) {
1029            return title;
1030        }
1031    }
1032
1033    /**
1034     * Get a specific transition item.
1035     *
1036     * @param transitionName the name of the transition
1037     * @return Transition named in parameter
1038     * @throws ControllerException upon error
1039     */

1040    public Transition getTransition(String JavaDoc transitionName)
1041            throws ControllerException {
1042        validState();
1043
1044        if (transitionCache != null) {
1045            return (Transition) transitionCache.get(transitionName);
1046        }
1047
1048        return null;
1049    }
1050
1051    /* getTransition(String) */
1052
1053    /**
1054     * The getTransitions method is called by the client to this controller in
1055     * order to determine what the possible next states are from the current
1056     * state. The controller uses the contents of the current state (e.g.
1057     * parameters) to determine where it is possible for this user to go next.
1058     *
1059     * @return A Vector of Transition objects representing the transitions that
1060     * can be taken by the user at this point to select new states
1061     */

1062    public final Vector JavaDoc getTransitions() {
1063        validState();
1064
1065        if (transitionCacheOrdered != null) {
1066            return transitionCacheOrdered;
1067        }
1068
1069        return null;
1070    }
1071
1072    /* getTransitions() */
1073
1074    /**
1075     * Retrieve the Blocks as a map so that JSTL can cope with navigating the
1076     * ControllerResponse through a named fashion
1077     *
1078     * @return java.util.Map
1079     * @throws ControllerException upon error
1080     */

1081    public Map JavaDoc getNamedBlocks() throws ControllerException {
1082        validState();
1083
1084        return blockCache;
1085    }
1086
1087    /**
1088     * Retrieve the Outputs as a map so that JSTL can cope with navigating the
1089     * ControllerResponse through a named fashion
1090     *
1091     * @return java.util.Map
1092     * @throws ControllerException upon error
1093     */

1094    public Map JavaDoc getNamedOutputs() throws ControllerException {
1095        validState();
1096
1097        return outputCache;
1098    }
1099
1100    /**
1101     * Retrieve the Transitions as a map so that JSTL can cope with navigating
1102     * the ControllerResponse through a named fashion
1103     *
1104     * @return java.util.Map
1105     * @throws ControllerException upon error
1106     */

1107    public Map JavaDoc getNamedTransitions() throws ControllerException {
1108        validState();
1109
1110        return transitionCache;
1111    }
1112
1113    /**
1114     * Set the user string value
1115     *
1116     * @param newUser the new user.
1117     * @throws ControllerException upon error
1118     */

1119    public synchronized void setUser(String JavaDoc newUser) throws ControllerException {
1120        getRequest().setUser(newUser);
1121    }
1122
1123    /**
1124     * Get the database from the request, if there is a request available
1125     *
1126     * @return the User as specified by the request.
1127     * @throws ControllerException upon error
1128     */

1129    public String JavaDoc getUser() throws ControllerException {
1130        return getRequest().getUser();
1131    }
1132
1133    /* getUser() */
1134
1135    /**
1136     * Convenience method to allow us to add any ControllerElement to this
1137     * controllers inputs, outputs or transitions
1138     *
1139     * @param t the new ControllerElement
1140     * @throws ControllerException upon error [Such as if the ControllerElement
1141     * is an unrecognized type]
1142     */

1143    public void add(ControllerElement t) throws ControllerException {
1144        if (t instanceof Input) {
1145            addInput((Input) t);
1146        } else if (t instanceof Output) {
1147            addOutput((Output) t);
1148        } else if (t instanceof Transition) {
1149            addTransition((Transition) t);
1150        } else if (t instanceof Block) {
1151            addBlock((Block) t);
1152        } else {
1153            throw new ControllerException("Element " + t.getName() +
1154                    " is not a Block, Input, Output or Transition");
1155        }
1156    }
1157
1158    /* add(ControllerElement) */
1159
1160    /**
1161     * addAutoInput is a convenience method that creates a new Input object
1162     * based on the specified field parameters and adds the input object to
1163     * this controller object. Creation date: (7/20/00 3:43:14 PM)
1164     *
1165     * @param fieldName java.lang.String
1166     * @param friendlyName the friendly name
1167     * @param defaultValue java.lang.String
1168     * @param displayLength the length of the display
1169     * @param maxLength the maximum length of the input
1170     * @param validValues a Vector of valid value objects for dropdowns
1171     * @throws ControllerException upon error
1172     */

1173    public void addAutoInput(String JavaDoc fieldName, String JavaDoc friendlyName,
1174                             String JavaDoc defaultValue, int displayLength, int maxLength,
1175                             Vector JavaDoc validValues) throws ControllerException {
1176        addAutoInput(fieldName, friendlyName, defaultValue, displayLength,
1177                maxLength, validValues, "text");
1178    }
1179
1180    /* addAutoInput(STring, String, String, int, int, Vector) */
1181
1182    /**
1183     * addAutoInput is a convenience method that creates a new Input object
1184     * based on the specified field parameters and adds the input object to
1185     * this controller object. Creation date: (7/20/00 3:43:14 PM) author:
1186     * Shash Chatterjee
1187     *
1188     * @param fieldName java.lang.String
1189     * @param dbobj com.jcorporate.expresso.core.dbobj.DBObject
1190     * @param defaultValue java.lang.String
1191     * @throws ControllerException upon error
1192     */

1193    public void addAutoInput(String JavaDoc fieldName, DBObject dbobj,
1194                             String JavaDoc defaultValue) throws ControllerException {
1195        int displayLength = 0;
1196        int maxLength = 0;
1197        String JavaDoc friendlyName = null;
1198        Vector JavaDoc validValues = null;
1199        JDBCObjectMetaData metadata = dbobj.getJDBCMetaData();
1200
1201        try {
1202            if (!metadata.isField(fieldName)) {
1203                throw new ControllerException("The field name specified is not valid for this DBObject.");
1204            }
1205
1206            friendlyName = metadata.getDescription(fieldName);
1207            maxLength = Integer.parseInt(metadata.getLength(fieldName));
1208            displayLength = maxLength;
1209
1210            if (displayLength > 40) {
1211                displayLength = 40;
1212            }
1213
1214            if (metadata.isMultiValued(fieldName)) {
1215                validValues = dbobj.getValidValues(fieldName);
1216            }
1217
1218            if (defaultValue == null) {
1219                defaultValue = dbobj.getField(fieldName);
1220            }
1221
1222            addAutoInput(fieldName, friendlyName, defaultValue, displayLength,
1223                    maxLength, validValues, metadata.getType(fieldName));
1224        } catch (DBException dbe) {
1225            throw new ControllerException("There was a problem accessing the " +
1226                    "DBObject for autoInput generation", dbe);
1227        }
1228    }
1229
1230    /* addAutoInput(String, DBObject, String) */
1231
1232    /**
1233     * addAutoInput is a convenience method that creates a new Input object
1234     * based on the specified field parameters and adds the input object to
1235     * this controller object. Creation date: (7/20/00 3:43:14 PM) author:
1236     * Adam Rossi, PlatinumSolutions
1237     *
1238     * @param fieldName java.lang.String
1239     * @param dbClassName java.lang.String
1240     * @param defaultValue java.lang.String
1241     * @throws ControllerException upon error
1242     */

1243    public void addAutoInput(String JavaDoc fieldName, String JavaDoc dbClassName,
1244                             String JavaDoc defaultValue) throws ControllerException {
1245        DBObject dbobj = null;
1246        int displayLength = 0;
1247        int maxLength = 0;
1248        String JavaDoc friendlyName = null;
1249        Vector JavaDoc validValues = null;
1250
1251        try {
1252            try {
1253                Class JavaDoc clazz = ClassLocator.loadClass(dbClassName);
1254                dbobj = (DBObject) clazz.newInstance();
1255            } catch (Exception JavaDoc e) {
1256                throw new ControllerException("The dbClass specified could not be loaded.");
1257            }
1258
1259            DataObjectMetaData metadata = dbobj.getMetaData();
1260
1261            if (!metadata.isField(fieldName)) {
1262                throw new ControllerException("The field name specified is not valid for this DBObject.");
1263            }
1264
1265            friendlyName = metadata.getDescription(fieldName);
1266            maxLength = Integer.parseInt(metadata.getLength(fieldName));
1267            displayLength = maxLength;
1268
1269            if (displayLength > 40) {
1270                displayLength = 40;
1271            }
1272
1273            if (metadata.isMultiValued(fieldName)) {
1274                validValues = dbobj.getValidValues(fieldName);
1275            }
1276
1277            if (defaultValue == null) {
1278                defaultValue = dbobj.getField(fieldName);
1279            }
1280
1281            addAutoInput(fieldName, friendlyName, defaultValue, displayLength,
1282                    maxLength, validValues, metadata.getType(fieldName));
1283        } catch (DBException dbe) {
1284            throw new ControllerException("There was a problem accessing the " +
1285                    "DBObject for autoInput generation", dbe);
1286        }
1287    }
1288
1289    /* addAutoInput(String, String, String) */
1290
1291    /**
1292     * Convenience method to add an input for every non-secret field in a db
1293     * object to the current response, using the default values and valid
1294     * values provided by the db object itself
1295     *
1296     * @param myDBObj the dbobject to render to the controller response
1297     * @throws ControllerException upon error
1298     */

1299    public void addAutoInput(DBObject myDBObj) throws ControllerException {
1300        try {
1301            String JavaDoc oneFieldName = null;
1302            DataObjectMetaData metadata = myDBObj.getMetaData();
1303            String JavaDoc className = myDBObj.getClass().getName();
1304
1305            for (Iterator JavaDoc e = metadata.getFieldListArray().iterator();
1306                 e.hasNext();) {
1307                oneFieldName = (String JavaDoc) e.next();
1308
1309                if (!metadata.isSecret(oneFieldName)) {
1310                    addAutoInput(oneFieldName,
1311                            metadata.getDescription(oneFieldName), className,
1312                            myDBObj.getField(oneFieldName));
1313                }
1314            }
1315
1316            /* for each field */
1317        } catch (DBException de) {
1318            throw new ControllerException(de);
1319        }
1320    }
1321
1322    /* addAutoInput(DBOBject) */
1323
1324    /**
1325     * addAutoInput is a convenience method that creates a new Input object
1326     * based on the specified field parameters and adds the input object to
1327     * this controller object. Creation date: (7/20/00 3:43:14 PM) author:
1328     * Adam Rossi, PlatinumSolutions
1329     *
1330     * @param fieldName java.lang.String
1331     * @param friendlyName the description of the Input to set.
1332     * @param dbClassName java.lang.String
1333     * @param defaultValue java.lang.String
1334     * @throws ControllerException upon error
1335     */

1336    public void addAutoInput(String JavaDoc fieldName, String JavaDoc friendlyName,
1337                             String JavaDoc dbClassName, String JavaDoc defaultValue) throws ControllerException {
1338        DBObject dbobj = null;
1339        int displayLength = 0;
1340        int maxLength = 0;
1341        Vector JavaDoc validValues = null;
1342
1343        try {
1344            try {
1345                Class JavaDoc clazz = ClassLocator.loadClass(dbClassName);
1346                dbobj = (DBObject) clazz.newInstance();
1347            } catch (Exception JavaDoc e) {
1348                throw new ControllerException("The dbClass specified could not be loaded.");
1349            }
1350
1351            DataObjectMetaData metadata = dbobj.getMetaData();
1352
1353            if (!metadata.isField(fieldName)) {
1354                throw new ControllerException("The field name specified is not valid for this DBObject.");
1355            }
1356
1357            maxLength = Integer.parseInt(metadata.getLength(fieldName));
1358            displayLength = maxLength;
1359
1360            if (displayLength > 40) {
1361                displayLength = 40;
1362            }
1363
1364            if (metadata.isMultiValued(fieldName)) {
1365                validValues = dbobj.getValidValues(fieldName);
1366            }
1367
1368            if (defaultValue == null) {
1369                defaultValue = dbobj.getField(fieldName);
1370            }
1371
1372            this.addAutoInput(fieldName, friendlyName, defaultValue,
1373                    displayLength, maxLength, validValues,
1374                    metadata.getType(fieldName));
1375        } catch (DBException dbe) {
1376            throw new ControllerException("There was a problem accessing the " +
1377                    "DBObject for autoInput generation: " + dbe.getMessage());
1378        }
1379    }
1380
1381    /* addAuotoInput(String, String, String, String) */
1382
1383    /**
1384     * addAutoInput is a convenience method that creates a new Input object
1385     * based on the specified field parameters and adds the input object to
1386     * this controller object. Creation date: (7/20/00 3:43:14 PM)
1387     *
1388     * @param fieldName java.lang.String
1389     * @param friendlyName the description of the input
1390     * @param defaultValue java.lang.String
1391     * @param displayLength display size of the Input
1392     * @param maxLength the maximum input length
1393     * @param validValues valid value Vector if needed for dropdown boxes
1394     * @param fieldType the type of the field such as "datetime", "varchar",
1395     * etc
1396     * @throws ControllerException upon error
1397     */

1398    public void addAutoInput(String JavaDoc fieldName, String JavaDoc friendlyName,
1399                             String JavaDoc defaultValue, int displayLength, int maxLength,
1400                             Vector JavaDoc validValues, String JavaDoc fieldType) throws ControllerException {
1401        Input oneInput = new Input();
1402
1403        if ((displayLength == 0) || (maxLength == 0)) {
1404            if (fieldType.equalsIgnoreCase(DBField.DATETIME_TYPE)) {
1405                displayLength = maxLength = 19;
1406            }
1407        }
1408
1409        oneInput.setName(fieldName);
1410        oneInput.setLabel(friendlyName);
1411        oneInput.setDisplayLength(displayLength);
1412        oneInput.setDefaultValue(StringUtil.notNull(defaultValue));
1413        oneInput.setMaxLength(maxLength);
1414
1415        //Here we do a little more intelligent probing to determine the input
1416
//type.
1417
//Normally, we use a TEXTAREA only for text fields. However, if the
1418
//VARCHAR area is bigger than 150, we will use a textarea for that as well.
1419
boolean expandToTextArea = false;
1420
1421        if (fieldType.equalsIgnoreCase(DBField.VARCHAR_TYPE)) {
1422            if (displayLength > 150) {
1423                expandToTextArea = true;
1424            }
1425        }
1426
1427        if (validValues != null) {
1428            oneInput.setValidValues(validValues);
1429            oneInput.setType("LISTBOX");
1430        } else {
1431            if (fieldType.equalsIgnoreCase("text") || expandToTextArea) {
1432                oneInput.setType("TEXTAREA");
1433            } else if (fieldType.equalsIgnoreCase(DBField.VARCHAR_TYPE)) {
1434                oneInput.setType("TEXTFIELD");
1435            } else if (fieldType.equalsIgnoreCase("date")) {
1436                oneInput.setType("TEXTFIELD");
1437                oneInput.setDisplayLength(10);
1438                oneInput.setMaxLength(10);
1439            } else if (fieldType.equalsIgnoreCase("time")) {
1440                oneInput.setType("TEXTFIELD");
1441                oneInput.setDisplayLength(10);
1442                oneInput.setMaxLength(10);
1443            } else if (fieldType.equalsIgnoreCase(DBField.DATETIME_TYPE)) {
1444                oneInput.setType("TEXTFIELD");
1445                oneInput.setDisplayLength(21);
1446                oneInput.setMaxLength(21);
1447            } else {
1448                oneInput.setType("TEXTFIELD");
1449            }
1450        }
1451
1452        addInput(oneInput);
1453    }
1454
1455    /* addAutoInput(String, String, String, int, int, Vector) */
1456
1457    /**
1458     * addAutoInputRenameField is a convenience method that creates a new Input
1459     * object based on the specified field parameters and adds the input
1460     * object to this controller object. This variation on addAutoInput allows
1461     * a user to force a field to be renamed in the INPUT object. This is
1462     * important when you have two DBOBjects with the same field name
1463     * rendering on the same page, and you still want to use AddAutoInput.
1464     * Creation date: 1/17/2002
1465     *
1466     * @param fieldName java.lang.String
1467     * @param renameFieldTo the field to rename to
1468     * @param dbobj com.jcorporate.expresso.core.dbobj.DBObject
1469     * @param defaultValue java.lang.String
1470     * @throws ControllerException upon error
1471     */

1472    public void addAutoInputRenameField(String JavaDoc fieldName, String JavaDoc renameFieldTo,
1473                                        DBObject dbobj, String JavaDoc defaultValue) throws ControllerException {
1474        //NOTE: I cut and pasted this method, and I have to do that.
1475
//All of the AddAuto* methods need to be rewritten, this is
1476
//getting out of hand. - Adam
1477
int displayLength = 0;
1478        int maxLength = 0;
1479        String JavaDoc friendlyName = null;
1480        Vector JavaDoc validValues = null;
1481        JDBCObjectMetaData metadata = dbobj.getJDBCMetaData();
1482
1483        try {
1484            if (!metadata.isField(fieldName)) {
1485                throw new ControllerException("The field name specified is not valid for this DBObject.");
1486            }
1487
1488            friendlyName = metadata.getDescription(fieldName);
1489            maxLength = Integer.parseInt(metadata.getLength(fieldName));
1490            displayLength = maxLength;
1491
1492            if (displayLength > 40) {
1493                displayLength = 40;
1494            }
1495
1496            if (metadata.isMultiValued(fieldName)) {
1497                validValues = dbobj.getValidValues(fieldName);
1498            }
1499
1500            if (defaultValue == null) {
1501                defaultValue = dbobj.getField(fieldName);
1502            }
1503
1504            addAutoInput(renameFieldTo, friendlyName, defaultValue,
1505                    displayLength, maxLength, validValues,
1506                    metadata.getType(fieldName));
1507        } catch (DBException dbe) {
1508            throw new ControllerException("There was a problem accessing the " +
1509                    "DBObject for autoInput generation", dbe);
1510        }
1511    }
1512
1513    /* addAutoInputRenameField(String, DBObject, String) */
1514
1515    /**
1516     * Adds a Block to the response that will be formatted by the controller
1517     * handler
1518     *
1519     * @param newBlock the block instance to add
1520     * @throws ControllerException upon error
1521     */

1522    public void addBlock(Block newBlock) throws ControllerException {
1523        if (blockCache == null) {
1524            blockCache = new HashMap JavaDoc();
1525        }
1526
1527        if (StringUtil.notNull(newBlock.getName()).equals("")) {
1528            int nextNum = blockCache.size() + 1;
1529            newBlock.setName("" + nextNum);
1530        }
1531
1532        newBlock.setControllerResponse(this);
1533
1534        synchronized (blockCache) {
1535            blockCache.put(newBlock.getName(), newBlock);
1536        }
1537
1538        if (blockCacheOrdered == null) {
1539            blockCacheOrdered = new Vector JavaDoc();
1540        }
1541
1542        blockCacheOrdered.addElement(newBlock);
1543    }
1544
1545    /* addBlock(Block) */
1546
1547    /**
1548     * @param errorMessage
1549     */

1550    public void addError(String JavaDoc errorMessage) throws ControllerException {
1551        ErrorCollection errs = getErrors();
1552
1553        if (errs == null) {
1554            errs = new ErrorCollection();
1555        }
1556
1557        errs.addError(errorMessage);
1558        saveErrors(errs);
1559    }
1560
1561    /**
1562     * add an error code, and an associated arg for translating that error code
1563     *
1564     * @param errorMessage key to error msg found in message bundle
1565     * @param arg a replacement value to use in ${} replacement template
1566     * @see com.jcorporate.expresso.core.i18n.MessageBundle#getString(java.lang.String, java.lang.Object[])
1567     */

1568    public void addError(String JavaDoc errorMessage, Object JavaDoc arg) throws ControllerException {
1569        ErrorCollection errs = getErrors();
1570
1571        if (errs == null) {
1572            errs = new ErrorCollection();
1573        }
1574
1575        errs.addError(errorMessage, arg);
1576        saveErrors(errs);
1577    }
1578
1579
1580    /**
1581     * add an error code, and associated args for translating that error code
1582     *
1583     * @param errorMessage key to error msg found in message bundle
1584     * @param args an array of replacement value to use in ${} replacement templates
1585     * @see com.jcorporate.expresso.core.i18n.MessageBundle#getString(java.lang.String, java.lang.Object[])
1586     */

1587    public void addError(String JavaDoc errorMessage, Object JavaDoc[] args) throws ControllerException {
1588        ErrorCollection errs = getErrors();
1589
1590        if (errs == null) {
1591            errs = new ErrorCollection();
1592        }
1593
1594        errs.addError(errorMessage, args);
1595        saveErrors(errs);
1596    }
1597
1598    /**
1599     * @param propName
1600     * @param errorMessage
1601     * @deprecated 7/04 v5.5 expresso uses only one property name, the default; use addError(String errmsg) instead
1602     */

1603    public void addError(String JavaDoc propName, String JavaDoc errorMessage)
1604            throws ControllerException {
1605        ErrorCollection errs = getErrors();
1606
1607        if (errs == null) {
1608            errs = new ErrorCollection();
1609        }
1610
1611        errs.addError(propName, errorMessage);
1612        saveErrors(errs);
1613    }
1614
1615    /**
1616     * Add an Input to the ControllerResponse
1617     *
1618     * @param newInput the Input to add to the ControllerResponse
1619     * @throws ControllerException upon error
1620     */

1621    public void addInput(Input newInput) throws ControllerException {
1622        if (inputCache == null) {
1623            inputCache = new HashMap JavaDoc();
1624        }
1625
1626        newInput.setControllerResponse(this);
1627
1628        if (StringUtil.notNull(newInput.getName()).equals("")) {
1629            int nextNum = inputCache.size() + 1;
1630            newInput.setName("i" + nextNum);
1631        }
1632
1633        synchronized (inputCache) {
1634            inputCache.put(newInput.getName(), newInput);
1635        }
1636
1637        if (inputCacheOrdered == null) {
1638            inputCacheOrdered = new Vector JavaDoc();
1639        }
1640
1641        inputCacheOrdered.addElement(newInput);
1642    }
1643
1644    /* addInput(Input) */
1645
1646    /**
1647     * Add an Output to the controller response object
1648     *
1649     * @param newOutput the new output to add
1650     * @throws ControllerException upon error
1651     */

1652    public void addOutput(Output newOutput) throws ControllerException {
1653        if (outputCache == null) {
1654            outputCache = new HashMap JavaDoc();
1655        }
1656
1657        newOutput.setControllerResponse(this);
1658
1659        if (StringUtil.notNull(newOutput.getName()).equals("")) {
1660            int nextNum = outputCache.size() + 1;
1661            newOutput.setName("o" + nextNum);
1662        }
1663
1664        synchronized (outputCache) {
1665            outputCache.put(newOutput.getName(), newOutput);
1666        }
1667
1668        if (outputCacheOrdered == null) {
1669            outputCacheOrdered = new Vector JavaDoc();
1670        }
1671
1672        outputCacheOrdered.addElement(newOutput);
1673    }
1674
1675    /* addOutput(Output) */
1676
1677    /**
1678     * Add a Transition to this ControllerResponse
1679     *
1680     * @param newTransition the new Transition to add
1681     * @throws ControllerException upon error
1682     */

1683    public void addTransition(Transition newTransition)
1684            throws ControllerException {
1685        if (transitionCache == null) {
1686            transitionCache = new HashMap JavaDoc();
1687        }
1688
1689        if (StringUtil.notNull(newTransition.getName()).equals("")) {
1690            /* Assign it a name */
1691            int nextNum = transitionCache.size() + 1;
1692            newTransition.setName("t" + nextNum);
1693        }
1694
1695        synchronized (transitionCache) {
1696            transitionCache.put(newTransition.getName(), newTransition);
1697        }
1698
1699        newTransition.setControllerResponse(this);
1700
1701        if (transitionCacheOrdered == null) {
1702            transitionCacheOrdered = new Vector JavaDoc();
1703        }
1704
1705        transitionCacheOrdered.addElement(newTransition);
1706    }
1707
1708    /* addTransition(Transition) */
1709
1710    /**
1711     * AutoValidate is a quick way to validate the fields of a specified dbobj.
1712     * Creation date: (7/19/00 6:06:21 PM)
1713     *
1714     * @param checkClassName the class name to validate
1715     * @param errorCollection where Errors are saved to
1716     * @throws ValidationException The exception description.
1717     * @throws ControllerException upon error
1718     */

1719    public void autoValidate(String JavaDoc checkClassName,
1720                             ErrorCollection errorCollection)
1721            throws ValidationException, ControllerException {
1722        String JavaDoc paramName = null;
1723        ValidationItem vi = null;
1724        StringUtil.assertNotBlank(checkClassName,
1725                "The checkClassName cannot be null");
1726
1727        ValidationSet validSet = new ValidationSet();
1728
1729        for (Enumeration JavaDoc e = getRequest().getParameters().keys();
1730             e.hasMoreElements();) {
1731            paramName = (String JavaDoc) e.nextElement();
1732            vi = new ValidationItem(paramName, false, checkClassName);
1733            validSet.setValidationItem(vi);
1734        }
1735
1736        validate(validSet, errorCollection);
1737    }
1738
1739    /* autoValidate(String, ErrorCollection) */
1740
1741    /**
1742     * AutoValidate is a quick way to validate the fields of a specified dbobj.
1743     * This method has not been tested and may not be correct. This methods
1744     * takes an optional requiredFields vector, which just tells the
1745     * validation routine which inputs are required. Creation date: (7/19/00
1746     * 6:06:21 PM)
1747     *
1748     * @param checkClassName the class name to cehck
1749     * @param errorCollection the error collection to save errors to
1750     * @param requiredFields the field anmes that are required
1751     * @throws ValidationException The exception description.
1752     * @throws ControllerException upon error
1753     */

1754    public void autoValidate(String JavaDoc checkClassName,
1755                             ErrorCollection errorCollection, Vector JavaDoc requiredFields)
1756            throws ValidationException, ControllerException {
1757        if (requiredFields == null) {
1758            requiredFields = new Vector JavaDoc();
1759        }
1760
1761        String JavaDoc fieldName = null;
1762        ValidationItem vi = null;
1763
1764        if ((checkClassName == null) || "".equals(checkClassName)) {
1765            throw new ValidationException("The checkClassName cannot be null");
1766        }
1767
1768        ValidationSet validSet = new ValidationSet();
1769        DBObject dbobj = null;
1770
1771        try {
1772            Class JavaDoc clazz = ClassLocator.loadClass(checkClassName);
1773            dbobj = (DBObject) clazz.newInstance();
1774        } catch (Exception JavaDoc e) {
1775            throw new ControllerException("The dbClass specified could not be loaded.");
1776        }
1777
1778        DataObjectMetaData metadata = dbobj.getMetaData();
1779        Iterator JavaDoc it = null;
1780
1781        it = metadata.getFieldListArray().iterator();
1782
1783        boolean requireField = false;
1784
1785        while (it.hasNext()) {
1786            fieldName = (String JavaDoc) it.next();
1787
1788            if (requiredFields.contains(fieldName)) {
1789                requireField = true;
1790            } else {
1791                requireField = false;
1792            }
1793
1794            vi = new ValidationItem(fieldName, requireField, checkClassName);
1795            validSet.setValidationItem(vi);
1796        }
1797
1798        validate(validSet, errorCollection);
1799    }
1800
1801    /* autoValidate(String, ErrorCollection, Vector) */
1802
1803    /**
1804     * Clear the Attribute values
1805     */

1806    public void clearAttributes() {
1807        myRequest.setAttributes(null);
1808    }
1809
1810    /* clearAttributes() */
1811    /**
1812     *
1813     */

1814    public void clearBlockCache() {
1815        blockCache = null;
1816    }
1817
1818    /* clearBlockCache() */
1819
1820    /**
1821     * Completely clear the internal formResponseCache Creation date: (7/19/00
1822     * 6:53:58 PM) author: Adam Rossi, PlatinumSolutions
1823     *
1824     * @throws ControllerException upon error
1825     */

1826    public void clearFormCache() throws ControllerException {
1827        getDefaultForm().clear();
1828    }
1829
1830    /* clearFormCache() */
1831
1832    /**
1833     * Clear the input cache
1834     */

1835    public void clearInputCache() {
1836        inputCache = null;
1837    }
1838
1839    /* clearInputCache() */
1840
1841    /**
1842     * Clear the output cache
1843     */

1844    public void clearOutputCache() {
1845        outputCache = null;
1846    }
1847
1848    /* clearOutputCache() */
1849    /**
1850     *
1851     */

1852    public void clearTransitionCache() {
1853        transitionCache = null;
1854    }
1855
1856    /* clearTransitionCache() */
1857
1858    /**
1859     * determine whether response has errors
1860     *
1861     * @return true if response has errors
1862     * @throws ControllerException if there is a problem
1863     */

1864    public boolean hasErrors() throws ControllerException {
1865        ErrorCollection errs = getErrors();
1866
1867        if (errs == null) {
1868            return false;
1869        }
1870
1871        if (errs.getErrorCount() > 0) {
1872            return true;
1873        }
1874
1875        return false;
1876    }
1877
1878    /**
1879     * determine whether response has errors of the particular label
1880     *
1881     * @return true if response has errors of the particular label
1882     * @throws ControllerException if there is a problem
1883     */

1884    public boolean hasErrors(String JavaDoc label) throws ControllerException {
1885        ErrorCollection errs = getErrors();
1886
1887        if (errs == null) {
1888            return false;
1889        }
1890
1891        if (errs.getErrors(label).hasNext()) {
1892            return true;
1893        }
1894
1895        return false;
1896    }
1897
1898    /**
1899     * Restore the controller form
1900     */

1901    public void restoreForm() throws ControllerException {
1902        getDefaultForm().restoreForm(getRequest());
1903    }
1904
1905    /**
1906     * This method saves an ErrorCollection object to the request attributes
1907     * collection. The ErrorCollection is saved with the
1908     * ErrorCollection.ERRORCOLLECTIONKEY key. To retrieve the ErrorCollection
1909     * in a JSP or servlet: ErrorCollection errors =
1910     * (ErrorCollection)pageContext.getValue(
1911     * ErrorCollection.ERRORCOLLECTIONKEY, PageContext.REQUEST_SCOPE); Note:
1912     * This method does not need to be updated to GenericSession...it is
1913     * saving to the pageContext, not the session. Creation date: (7/19/00
1914     * 7:25:05 PM) author: Adam Rossi, PlatinumSolutions
1915     *
1916     * @param errorCollection java.jcorporate.expresso.core.controller.ErrorCollection
1917     * @throws ControllerException upon error
1918     */

1919    public void saveErrors(ErrorCollection errorCollection)
1920            throws ControllerException {
1921        ControllerRequest req = getRequest();
1922        HttpServletRequest JavaDoc hreq = null;
1923
1924        if (req instanceof ServletControllerRequest) {
1925            ServletControllerRequest sreq = (ServletControllerRequest) req;
1926            hreq = (HttpServletRequest JavaDoc) sreq.getServletRequest();
1927        }
1928
1929        // Remove any errorCollection attribute if none are required
1930
if ((errorCollection == null) ||
1931                (errorCollection.getErrorCount() == 0)) {
1932            req.getSession().setAttribute(Globals.ERROR_KEY, null);
1933
1934            if (hreq != null) {
1935                hreq.setAttribute(Globals.ERROR_KEY, null);
1936            }
1937
1938            return;
1939        }
1940
1941        // Save the errorCollection
1942
req.getSession().setAttribute(Globals.ERROR_KEY, errorCollection);
1943
1944        if (hreq != null) {
1945            hreq.setAttribute(Globals.ERROR_KEY, errorCollection);
1946        }
1947    }
1948
1949    /* saveErrors(ErrorCollection) */
1950
1951    /**
1952     * Convert the controller response to an xml document fragment.
1953     *
1954     * @return an xml document
1955     * @throws ControllerException upon error
1956     */

1957    public synchronized String JavaDoc toXML() throws ControllerException {
1958        FastStringBuffer returnBuffer = FastStringBuffer.getInstance();
1959        String JavaDoc returnValue = null;
1960
1961        try {
1962            returnBuffer.append("<controller-response name=\"" +
1963                    myControllerClass + "\"");
1964
1965            if (title != null) {
1966                returnBuffer.append(" title=\"" + title + "\"");
1967            }
1968
1969            if (requestedState != null) {
1970                returnBuffer.append(" requestedState=\"" + requestedState +
1971                        "\"");
1972            }
1973
1974            if (style != null) {
1975                returnBuffer.append(" style=\"" + style + "\"");
1976            }
1977
1978            returnBuffer.append(">\n");
1979
1980            ErrorCollection ec = getErrors();
1981
1982            if ((ec != null) && (ec.getErrorCount() > 0)) {
1983                returnBuffer.append("<errors>");
1984
1985                for (Iterator JavaDoc i = ec.getErrors(); i.hasNext();) {
1986                    ActionError oneError = (ActionError) i.next();
1987                    returnBuffer.append("<error-message>");
1988                    returnBuffer.append(oneError.getKey());
1989                    returnBuffer.append("</error-message>");
1990                }
1991
1992                returnBuffer.append("</errors>");
1993            }
1994
1995            Vector JavaDoc blockList = getBlocks();
1996            Block oneBlock = null;
1997
1998            if (blockList != null) {
1999                /* for each block */
2000                for (Enumeration JavaDoc bl = blockList.elements();
2001                     bl.hasMoreElements();) {
2002                    oneBlock = (Block) bl.nextElement();
2003                    returnBuffer = oneBlock.toXML(returnBuffer);
2004                }
2005
2006                /* each block */
2007            }
2008
2009            Vector JavaDoc outputs = getOutputs();
2010
2011            if (outputs != null) {
2012                for (Enumeration JavaDoc eo = outputs.elements(); eo.hasMoreElements();) {
2013                    returnBuffer = ((ControllerElement) eo.nextElement()).toXML(returnBuffer);
2014                }
2015            }
2016
2017            Vector JavaDoc inputs = getInputs();
2018
2019            if (inputs != null) {
2020                for (Enumeration JavaDoc ei = inputs.elements(); ei.hasMoreElements();) {
2021                    returnBuffer = ((ControllerElement) ei.nextElement()).toXML(returnBuffer);
2022                }
2023            }
2024
2025            Vector JavaDoc transitions = getTransitions();
2026
2027            if (transitions != null) {
2028                for (Enumeration JavaDoc et = transitions.elements();
2029                     et.hasMoreElements();) {
2030                    returnBuffer = ((ControllerElement) et.nextElement()).toXML(returnBuffer);
2031                }
2032            }
2033
2034            returnBuffer.append("</controller-response>");
2035            returnValue = returnBuffer.toString();
2036        } finally {
2037            returnBuffer.release();
2038            returnBuffer = null;
2039        }
2040
2041        return returnValue;
2042    }
2043
2044    /**
2045     * The validate method is a quick and easy way to test user input. We are
2046     * trying to ensure that required fields are completed, and that the input
2047     * is correct based on the corresponding dbobj.checkField() method.
2048     * Creation date: (7/19/00 3:49:16 PM)
2049     *
2050     * @param validSet com.jcorporate.expresso.core.controller.ValidationSet
2051     * @param errorCollection com.jcorporate.expresso.core.controller.ErrorCollection
2052     * @throws ValidationException upon error
2053     * @deprecated See ControllerRequest.validateDBObject instead....
2054     */

2055    public void validate(ValidationSet validSet, ErrorCollection errorCollection)
2056            throws ValidationException {
2057        Vector JavaDoc validationVector = validSet.getValidationItems();
2058        ValidationItem vi = null;
2059        Hashtable JavaDoc checkClassCache = new Hashtable JavaDoc();
2060        String JavaDoc fieldValue = null;
2061        String JavaDoc fieldName = null;
2062        String JavaDoc friendlyFieldName = null;
2063        String JavaDoc checkClassName = null;
2064        String JavaDoc dbFieldName = null;
2065        DBObject dbobject = null;
2066        boolean oneErrorFlag = false;
2067        boolean isDBField = false;
2068
2069        /* Here we validate 2 things:
2070        1. If the field is required, but there is no value, we add an error
2071        2. If the field is there, we check to see if the checkField() method of the
2072        corresponding dbobject passes the input
2073        */

2074        try {
2075            for (int i = 0; i < validationVector.size(); i++) {
2076                vi = (ValidationItem) validationVector.elementAt(i);
2077                vi.checkThisItem();
2078                fieldName = StringUtil.notNull(vi.getFieldName());
2079                fieldValue = this.getFormCache(fieldName);
2080                friendlyFieldName = StringUtil.notNull(vi.getFriendlyFieldName());
2081                checkClassName = StringUtil.notNull(vi.getCheckClassName());
2082                dbFieldName = StringUtil.notNull(vi.getDbFieldName());
2083
2084                // The dbFieldName is optional. If it is blank, we assume the
2085
// fieldName is the same as the dbFieldName
2086
if (dbFieldName.equals("")) {
2087                    dbFieldName = fieldName;
2088                }
2089
2090                oneErrorFlag = false;
2091
2092                // We first make sure that we have a cached copy of the checker
2093
// DBObject class, if one is specified in the ValidationItem
2094
if (!checkClassName.equals("")) {
2095                    if (!checkClassCache.contains(checkClassName)) {
2096                        //instantiate a new DBObject
2097
Class JavaDoc clazz = ClassLocator.loadClass(checkClassName);
2098                        dbobject = (DBObject) clazz.newInstance();
2099                        checkClassCache.put(checkClassName, dbobject);
2100
2101                        DataObjectMetaData metadata = dbobject.getMetaData();
2102                        isDBField = metadata.isField(dbFieldName);
2103
2104                        if (isDBField) {
2105                            // If the ValidationItem object was not given a friendly
2106
// name, we use the field Description from the DBObject
2107
if ("".equals(friendlyFieldName)) {
2108                                friendlyFieldName = metadata.getDescription(dbFieldName);
2109                            }
2110                        }
2111                    }
2112                }
2113
2114                // End object cache check
2115
// Now we check to see if the field is required but not there
2116
if (vi.isRequired() && "".equals(fieldValue)) {
2117                    oneErrorFlag = true;
2118
2119                    if (!"".equals(friendlyFieldName)) {
2120                        errorCollection.addError("The " + friendlyFieldName +
2121                                " field is required. Please complete this field.");
2122                    }
2123                }
2124
2125                // end required check
2126
// Now we check to see if the DBOBject accepts the input
2127
if ((!oneErrorFlag) && (isDBField)) {
2128                    // Check to see if the field passes the dbobject validation
2129
if (checkClassCache.containsKey(checkClassName)) {
2130                        dbobject = (DBObject) checkClassCache.get(checkClassName);
2131
2132                        try {
2133                            dbobject.checkField(dbFieldName, fieldValue);
2134                        } catch (DBException dbe) {
2135                            oneErrorFlag = true;
2136
2137                            if (!"".equals(friendlyFieldName)) {
2138                                errorCollection.addError("There was a problem " +
2139                                        "with your input for the " +
2140                                        friendlyFieldName + " field: " +
2141                                        dbe.getMessage());
2142                            }
2143                        }
2144                    }
2145                }
2146            }
2147        } catch (Exception JavaDoc e) {
2148            e.printStackTrace();
2149            throw new ValidationException("Unable to validate '" +
2150                    checkClassName + "'", e);
2151        }
2152    }
2153
2154    /* validate(ValidationSet, ErrorCollection) */
2155
2156    /**
2157     * Retrieve the DefaultForm object
2158     *
2159     * @return DefaultForm
2160     * @throws ControllerException upon error
2161     */

2162    protected DefaultForm getDefaultForm() throws ControllerException {
2163        String JavaDoc formKey = getRequest().getFormAttribute();
2164
2165        if (StringUtil.notNull(formKey).equals("")) {
2166            throw new ControllerException("No ActionForm has been specified for this Controller mapping," +
2167                    " unable to utilize form cache. Please set an action form in struts-config.xml or similar files" +
2168                    " by setting name=\"default\" in the Action mapping. (i.e., use the default expresso formbean)");
2169        }
2170
2171        DefaultForm myForm = (DefaultForm) getRequest().getSession()
2172                .getAttribute(formKey);
2173
2174        if (myForm == null) {
2175            myForm = (DefaultForm) getRequest().getSession()
2176                    .getPersistentAttribute(formKey);
2177        }
2178
2179        if (myForm == null) {
2180            throw new ControllerException("No ActionForm found for key '" +
2181                    formKey + "' in request or session scope.");
2182        }
2183
2184        return myForm;
2185    }
2186
2187    /**
2188     * Tell this Controller object what Schema it belongs to. This is used when
2189     * the Controller tries to use it's "getString(String, Object[])" method
2190     * to prepare internationalized messages - it passes the call along to the
2191     * appropriate schema which knows how to locate the proper message file.
2192     *
2193     * @param schemaClass the schema class name to associate with this
2194     * controllerresposne
2195     */

2196    protected void setSchema(String JavaDoc schemaClass) {
2197        StringUtil.assertNotBlank(schemaClass, "Must specify a non-blank schema");
2198
2199        if (schemaStack == null) {
2200            schemaStack = new Stack JavaDoc();
2201        }
2202
2203        schemaStack.push(schemaClass);
2204    }
2205
2206    /* setSchema(String) */
2207
2208    /**
2209     * Check to see if we are currently in a valid state
2210     *
2211     * @return true if the state name is valid
2212     */

2213    protected boolean validState() {
2214        if (getCurrentState() == null) {
2215            return false;
2216        }
2217
2218        return true;
2219    }
2220
2221    /**
2222     * Set the current State object
2223     *
2224     * @param newState the new current state
2225     */

2226    void setCurrentState(State newState) {
2227        currentState = newState;
2228    }
2229
2230    /**
2231     * Useful for JSTL iteration of all items in response.
2232     *
2233     * @return a Map of all nested elements keyed by controllerElement name.
2234     */

2235    public Map JavaDoc getNestedMap() throws ControllerException {
2236        HashMap JavaDoc mappedNested = new HashMap JavaDoc();
2237
2238        Map JavaDoc map = this.getNamedBlocks();
2239        if (map != null) {
2240            mappedNested.putAll(map);
2241        }
2242
2243        map = this.getNamedInputs();
2244        if (map != null) {
2245            mappedNested.putAll(map);
2246        }
2247
2248        map = this.getNamedOutputs();
2249        if (map != null) {
2250            mappedNested.putAll(map);
2251        }
2252
2253        map = this.getNamedTransitions();
2254        if (map != null) {
2255            mappedNested.putAll(map);
2256        }
2257
2258        return mappedNested;
2259    }
2260
2261    /**
2262     * return raw key, without running through msg bundle string translation--useful for when 'cloning' in Transition
2263     */

2264    public String JavaDoc getTitleKey() {
2265        return title;
2266    }
2267
2268}
2269
Popular Tags