KickJava   Java API By Example, From Geeks To Geeks.

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


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
65 package com.jcorporate.expresso.core.controller;
66
67 import com.jcorporate.expresso.core.controller.session.PersistentSession;
68 import com.jcorporate.expresso.core.dbobj.DBObject;
69 import com.jcorporate.expresso.core.misc.StringUtil;
70 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
71 import org.apache.log4j.Logger;
72 import org.apache.oro.text.regex.MalformedPatternException;
73 import org.apache.oro.text.regex.Pattern;
74 import org.apache.oro.text.regex.PatternCompiler;
75 import org.apache.oro.text.regex.PatternMatcher;
76 import org.apache.oro.text.regex.Perl5Compiler;
77 import org.apache.oro.text.regex.Perl5Matcher;
78
79 import java.io.Serializable JavaDoc;
80 import java.util.ArrayList JavaDoc;
81 import java.util.HashMap JavaDoc;
82 import java.util.Iterator JavaDoc;
83 import java.util.List JavaDoc;
84 import java.util.Map JavaDoc;
85 import java.util.Vector JavaDoc;
86
87
88 /**
89  * A State embodies a single state in the finite state machine of a
90  * Controller object. Transitioning to a new state causes a Controller
91  * to generate a set of Input, Output and Action objects. In order
92  * to transition to a new state a controller can require that certain
93  * parameters be supplied
94  * <p/>
95  * <b>A state is not inherantly threadsafe.</b> The framework clones the
96  * state and hands it off to the multithreaded controller with each state
97  * invocation.
98  */

99 public class State
100         implements Cloneable JavaDoc,
101         Serializable JavaDoc {
102
103     /**
104      * Name of this state, referred to by the "state" parameter
105      */

106     private String JavaDoc name;
107
108     /**
109      * Long description of the state
110      */

111     private String JavaDoc descrip;
112     private static final String JavaDoc className = State.class.getName();
113
114     /**
115      * Parameters needed by this state. It is possible for a state
116      * to need other parameters, but the ones listed here can be
117      * verified as present when transitioning into the state
118      */

119     private List JavaDoc requiredParameters = new ArrayList JavaDoc();
120
121     /**
122      * Parameters defined by this state, but not necessarily
123      * required.
124      */

125     private List JavaDoc optionalParameters = new ArrayList JavaDoc();
126
127     /**
128      * Hashmap that provides regular expressions to validate input parameters
129      */

130     private Map JavaDoc paramMasks = null;
131
132     /**
133      * Map that stores friendly error messages if a parameter fails
134      * an error check.
135      */

136     private Map JavaDoc paramMaskErrors = null;
137
138     /**
139      * Current controller that this state is assigned to.
140      */

141     private Controller myController = null;
142
143     /**
144      * The request for this particular state handler. [Different for each thread]
145      */

146     private ControllerRequest myRequest = null;
147
148     /**
149      * The ControllerResponse for this particular state handler
150      * [Different for each thread]
151      */

152     private ControllerResponse myResponse = null;
153
154     /**
155      * Log4J category for this state handler
156      */

157     private static Logger log = Logger.getLogger(State.class);
158     private String JavaDoc handlerName = null;
159     private String JavaDoc errorState = null;
160     private String JavaDoc stateFormClass = null;
161     private Transition returnToSender;
162
163     /**
164      * The transition performed if state completes without errors. Can be overriden at runtime.
165      */

166     private Transition successTransition = null;
167
168     /**
169      * The transition performed if state completes with errors. Can be overriden at runtime.
170      */

171     private Transition errorTransition = null;
172
173     /**
174      * A Pattern Matcher for examining fields vs validation regular expressions
175      * It has been modified for thead local instantiation to reduce synchronization.
176      */

177     transient private static ThreadLocal JavaDoc patternMatcher = new ThreadLocal JavaDoc() {
178         protected synchronized Object JavaDoc initialValue() {
179             return new Perl5Matcher();
180         }
181     };
182
183     /**
184      * Retrieve a thread local instance of the Perl5 pattern matcher. Allows
185      * for optimization of # of instances of pattern matcher vs synchronization.
186      *
187      * @return PatternMatcher
188      */

189     protected PatternMatcher getPatternMatcher() {
190         return (PatternMatcher) patternMatcher.get();
191     }
192
193
194     /**
195      * Regular expression to check for at least one character, including newline
196      * (?s) puts the expressoion in single-line mode so that . (a period) will match newlines
197      */

198     public static final String JavaDoc NOTEMPTY_MASK = "(?s).+";
199
200     /**
201      * Is this state to run within an SSL setting?
202      *
203      * @todo implement
204      */

205     protected boolean secure;
206
207     /**
208      * Set the 'parent' controller
209      *
210      * @param newController The controller instance to set for the state
211      * @throws ControllerException upon error or null parameter
212      */

213     public void setController(Controller newController)
214             throws ControllerException {
215         if (newController == null) {
216             throw new ControllerException("Cannot set a null Controller here");
217         }
218
219         myController = newController;
220     }
221
222     /**
223      * Sets the state that defines the error state.
224      *
225      * @param newErrorState The name of the state to set as the error state
226      */

227     public synchronized void setErrorState(String JavaDoc newErrorState) {
228         errorState = newErrorState;
229     }
230
231     /**
232      * Retrieves the state that has been set as the error state
233      *
234      * @return java.lang.String
235      */

236     public String JavaDoc getErrorState() {
237         return errorState;
238     }
239
240     /**
241      * Set a regular expression "mask" for a particular parameter
242      * The parameter value is checked against this mask before the
243      * transition into the new state begins Also precompiles the regular
244      * expression to allow for quick parameter checking.
245      *
246      * @param paramName parameter name to check against the regular expression
247      * @param mask The regular Expression
248      * @throws IllegalArgumentException if the paramName or mask is blank.
249      */

250     public synchronized void setMask(String JavaDoc paramName, String JavaDoc mask) {
251         StringUtil.assertNotBlank(paramName,
252                 "You may not specify a blank parameter name");
253         StringUtil.assertNotBlank(mask,
254                 "You may not specify a blank mask here");
255
256         try {
257             PatternCompiler compiler = new Perl5Compiler();
258             Pattern pattern = null;
259             pattern = compiler.compile(mask, Perl5Compiler.READ_ONLY_MASK);
260
261             if (paramMasks == null) {
262                 paramMasks = new HashMap JavaDoc();
263             }
264
265             paramMasks.put(paramName, pattern);
266
267             if (mask.equals(DBObject.INT_MASK)) {
268                 String JavaDoc err = "Value supplied for parameter '" + paramName +
269                         "' must be an integer number.";
270                 this.setMaskError(paramName, err);
271             }
272         } catch (MalformedPatternException rre) {
273             log.error("Error Compiling Regular Expression for parameter: " +
274                     paramName, rre);
275             throw new IllegalArgumentException JavaDoc(rre.getMessage());
276         }
277     }
278
279     /**
280      * Set a regular expression "mask" for a particular parameter
281      * The parameter value is checked against this mask before the
282      * transition into the new state begins
283      *
284      * @param paramName The parameter name to check against the regular expression
285      * @param mask The regular Expression
286      * @param errorMsg The error message to use if the state fails.
287      * @throws IllegalArgumentException if the paramName or mask is blank.
288      */

289     public synchronized void setMask(String JavaDoc paramName, String JavaDoc mask,
290                                      String JavaDoc errorMsg) {
291         this.setMask(paramName, mask);
292         this.setMaskError(paramName, errorMsg);
293     }
294
295     /**
296      * If a state fails a parameter check on a mask, then the error specified will
297      * be stored in the error collections
298      *
299      * @param paramName The parameter name to check against the regular expression
300      * set in <code>setMask</code>
301      * @param errorMsg The error message to display. It may be a string that
302      * exists in a resource bundle, in which case that will be displayed instead
303      */

304     public void setMaskError(String JavaDoc paramName, String JavaDoc errorMsg) {
305         StringUtil.assertNotBlank(errorMsg,
306                 "You may not specify a blank errorMessage");
307
308         if (paramMaskErrors == null) {
309             paramMaskErrors = new HashMap JavaDoc();
310         }
311
312         String JavaDoc i18nString = null;
313
314         try {
315             i18nString = StringUtil.notNull(this.getString(errorMsg));
316         } catch (ControllerException e) {
317             System.err.println(e);
318         }
319         if (i18nString.length() != 0) {
320             paramMaskErrors.put(paramName, i18nString);
321         } else {
322             paramMaskErrors.put(paramName, errorMsg);
323         }
324     }
325
326     /**
327      * Set the ControllerResponse object associated with this state
328      *
329      * @param res The controller response associated with the state's instance.
330      * @throws ControllerException upon invalid parameter
331      */

332     protected void setResponse(ControllerResponse res)
333             throws ControllerException {
334         if (res == null) {
335             throw new ControllerException("Null response object not allowed here");
336         }
337
338         myResponse = res;
339     }
340
341     /**
342      * Set the return-to-sender transition. This is the transition that will be
343      * serialized and passed to any state that is invoked via a transition that
344      * has return-to-sender enabled.
345      *
346      * @param newReturnToSender Transition instance.
347      */

348     public void setReturnToSender(Transition newReturnToSender) {
349         returnToSender = newReturnToSender;
350     }
351
352     /**
353      * Set the class name of the state form associated with this state.
354      *
355      * @param newStateFormClass The class name of the object to use as an action form.
356      */

357     public void setStateFormClass(String JavaDoc newStateFormClass) {
358         stateFormClass = newStateFormClass;
359     }
360
361     /**
362      * Set the success transition. This is the transition that will be
363      * executed if this state returns without errors in the error collection.
364      *
365      * @param newSuccessTransition The transition to use for successful state executions.
366      */

367     public void setSuccessTransition(Transition newSuccessTransition) {
368         successTransition = newSuccessTransition;
369     }
370
371     public ControllerResponse getResponse() {
372         return myResponse;
373     }
374
375     /**
376      * retrieve the controller instance that is associated with this state
377      *
378      * @return A controller instance.
379      * @throws ControllerException [usually never thrown]
380      */

381     public Controller getController()
382             throws ControllerException {
383         return myController;
384     }
385
386     /**
387      * A convenience method that allows you to get a secured controller
388      * which is a subclass of a regular controller.
389      *
390      * @return DBController instance
391      * @throws ControllerException if the controller is not an instance of
392      * DBController.
393      * @deprecated 4/04 v5.5 use getController and cast.
394      */

395     protected DBController getDBController()
396             throws ControllerException {
397         if (myController instanceof DBController) {
398             return (DBController) myController;
399         } else {
400             throw new ControllerException("This state's controller was not " +
401                     "an DBController");
402         }
403     }
404
405     /**
406      * The no-args constructor is not normally used directly, but only
407      * by the mechanism that runs the states in order to invoke a state
408      * dynamically. Use the detailed constructor instead.
409      */

410     public State() {
411
412     }
413
414     /**
415      * Convenience constructor to allow us to specify
416      * a new state with a name and description. This is the preferred
417      * constructor for a controller, and is used within the constructor
418      * of a Controller to define the states that this controller
419      * has available to it.
420      *
421      * @param newName The name of the new state
422      * @param newDescrip A description for the new state - this may be
423      * (preferrably) a key into the local language file in order to facilitate
424      * internationalization, or just a simple string.
425      */

426     public State(String JavaDoc newName, String JavaDoc newDescrip) {
427         setName(newName);
428         setDescription(newDescrip);
429     } /* State(String, String) */
430
431     /**
432      * Set the internal "name" of this state. Normally done via the
433      * constructor when the state is "declared" in the appropriate
434      * controller.
435      *
436      * @param newName The new name of the state.
437      */

438     public void setName(String JavaDoc newName) {
439         name = newName;
440         this.calculateHandlerName(newName);
441     }
442
443     /**
444      * Sets the "should be secure" flag. Ie, if SSL is available, this state
445      * should be run within SSL.
446      *
447      * @param newSecure Such a true if you want to use SSL for the state.
448      */

449     public void setSecure(boolean newSecure) {
450         this.secure = newSecure;
451     }
452
453     /**
454      * Set a description (human-readable) for this state. This is normally
455      * done via the constructor. The description may be just a string
456      * describing the state in a few words, or (preferrably) it may
457      * be a key into the local language file, facilitation internationalization
458      *
459      * @param newDescrip The new description for the state.
460      */

461     public void setDescription(String JavaDoc newDescrip) {
462         descrip = newDescrip;
463     }
464
465     /**
466      * Add a required parameter to this state
467      *
468      * @param newParam The name of the new parameter
469      */

470     public void addRequiredParameter(String JavaDoc newParam) {
471         requiredParameters.add(newParam);
472         setMask(newParam, NOTEMPTY_MASK);
473     }
474
475     /**
476      * Add a required parameter to this state
477      *
478      * @param newParam The name of the new parameter
479      */

480     public void addOptionalParameter(String JavaDoc newParam) {
481         optionalParameters.add(newParam);
482     }
483
484     /**
485      * Add a new parameter to this state
486      *
487      * @param newParam The name of the new parameter
488      * @param mask The regular expression mask to compare against.
489      */

490     public void addParameter(String JavaDoc newParam, String JavaDoc mask) {
491         addRequiredParameter(newParam);
492         setMask(newParam, mask);
493     }
494
495     /**
496      * Add a new parameter to this state
497      *
498      * @param newParam The name of the new parameter
499      * @param required should an exception be thrown if this parameter isn't included?
500      * @param mask The regular expression mask to compare against.
501      */

502     public void addParameter(String JavaDoc newParam, boolean required, String JavaDoc mask) {
503         if (required) {
504             addRequiredParameter(newParam);
505         } else {
506             addOptionalParameter(newParam);
507         }
508
509         setMask(newParam, mask);
510     }
511
512     /**
513      * Add a new parameter to this state
514      *
515      * @param newParam The name of the new parameter
516      * @param required should an exception be thrown if this parameter isn't included?
517      * @param mask The regular expression mask to compare against.
518      * @param maskError The error message to give if mask validation fails.
519      */

520     public void addParameter(String JavaDoc newParam, boolean required, String JavaDoc mask,
521                              String JavaDoc maskError) {
522         if (required) {
523             addRequiredParameter(newParam);
524         } else {
525             addOptionalParameter(newParam);
526         }
527         setMask(newParam, mask);
528         setMaskError(newParam, maskError);
529     }
530
531     /**
532      * Get the description of this state, as supplied when the
533      * state is created. Try to use the description as a key
534      * in the current local-language file - if available. If we can't
535      * do that, or it's not a valid key, just return the description as
536      * it was originally specified.
537      *
538      * @return A description of this state
539      */

540     public String JavaDoc getDescription() {
541         ControllerResponse theResponse = getControllerResponse();
542
543         if (theResponse == null) {
544             return descrip;
545         }
546         try {
547             return theResponse.getString(descrip);
548         } catch (Exception JavaDoc ee) {
549             return descrip;
550         }
551     } /* getDescription() */
552
553     /**
554      * Get the name of this state. This is the "internal" name used
555      * to refer to the state, not the "human readable" description. This
556      * name is suitable as a parameter to the newState method, for example.
557      *
558      * @return The name of this state
559      */

560     public String JavaDoc getName() {
561         return name;
562     } /* getName() */
563
564     /**
565      * Return the list of parameters required by this State
566      *
567      * @return A Vector of the parameter names required by this State
568      */

569     public Vector JavaDoc getParameters() {
570         return new Vector JavaDoc(requiredParameters);
571     } /* getParameters() */
572
573     /**
574      * Same as getParameters, but returns a List instead
575      *
576      * @return a List collection giving all optional paramaters
577      */

578     public List JavaDoc getRequiredParametersList() {
579         return new ArrayList JavaDoc(requiredParameters);
580     }
581
582     /**
583      * Returns a list of optional parameters
584      *
585      * @return a vector of optional parameter names.
586      * @deprecated 3/5/04 v5.5 Use getOptionalParametersList instead
587      */

588     public Vector JavaDoc getOptionalParameters() {
589         return new Vector JavaDoc(optionalParameters);
590     }
591
592     /**
593      * Returns a list of optional parameters. Same as
594      * getOptionalParameters() but returns an List instead
595      *
596      * @return a List collection giving all optional parameters
597      */

598     public List JavaDoc getOptionalParametersList() {
599         return new ArrayList JavaDoc(optionalParameters);
600     }
601
602     /**
603      * Returns the string of this state. Good for debugging error messages
604      *
605      * @return The object class name
606      */

607     public String JavaDoc toString() {
608         return className + "[" + name + " " + descrip + "]";
609     } /* toString() */
610
611     /**
612      * Overrides default Object.equals(Object) behavior
613      *
614      * @param o The object to compare against.
615      * @return true if the objects are equal
616      * @deprecated use direct comparison of state name instead. this algorithm which allows 2 kinds of objects is ugly, and no longer used in expresso as of 5/04, v.5.5.1 LAH
617      */

618     public boolean equals(Object JavaDoc o) {
619         if (o instanceof String JavaDoc) {
620             String JavaDoc cmp = (String JavaDoc) o;
621
622             if (cmp != null) {
623                 return cmp.equals(name);
624             } else {
625                 return false;
626             }
627         } else {
628             if (o instanceof State) {
629                 State cmp = (State) o;
630
631                 return name.equals(cmp.getName());
632             }
633         }
634
635         return false;
636     } /* equals(Object) */
637
638     /**
639      * Return the error transition. This is the transition that will be
640      * executed if this state returns any errors in the error collection.
641      *
642      * @return The Error Transition
643      */

644     public Transition getErrorTransition() {
645         return errorTransition;
646     }
647
648     /**
649      * A state may implement a "run" method to actually perform it's
650      * logic by overriding this method.
651      *
652      * @param newRequest The controller request object that has been prepared by the framework,
653      * that contains all the parameters needed to execute state
654      * @param newResponse The controller response object that you use to populate with
655      * inputs, outputs and transitions.
656      * @throws ControllerException upon error
657      * @throws NonHandleableException upon fatal error
658      */

659     public void run(ControllerRequest newRequest,
660                     ControllerResponse newResponse)
661             throws ControllerException, NonHandleableException {
662         myRequest = newRequest;
663         myResponse = newResponse;
664         checkParamMasks();
665     }
666
667     /**
668      * A state may implement a "perform" method to actually perform it's
669      * logic by overriding this method. Any associated state form will
670      * be passed in with its data populated.
671      * If this method is not implemented by a child class then the "run" method will be
672      * called to be backwards compatible with previous versions.
673      *
674      * @param stateForm unused, useful for matching with Struts API
675      * @param newRequest The controller request object that has been prepared by the framework,
676      * that contains all the parameters needed to execute state
677      * @param newResponse The controller response object that you use to populate with
678      * inputs, outputs and transitions.
679      * @throws ControllerException upon error
680      * @throws NonHandleableException upon fatal error
681      */

682     public void perform(StateForm stateForm, ControllerRequest newRequest,
683                         ControllerResponse newResponse)
684             throws NonHandleableException, ControllerException {
685         run(newRequest, newResponse);
686     }
687
688     /**
689      * Convenience method to allow us to add any ControllerElement to this
690      * controllers inputs, outputs or transitions
691      *
692      * @param t The controller element, either an input an output, a transition,
693      * or a block that gets added to the controller response.
694      * @throws ControllerException upon error
695      */

696     protected void add(ControllerElement t)
697             throws ControllerException {
698         myResponse.add(t);
699     } /* add(ControllerElement) */
700
701
702     /**
703      * Adds a transition to the controller response associated with a state.
704      *
705      * @param newTransition The transition to add.
706      * @throws ControllerException upon error
707      */

708     public void addTransition(Transition newTransition)
709             throws ControllerException {
710         myResponse.add(newTransition);
711     } /* addTransition(Transition) */
712
713
714     /**
715      * Adds a block to the controller response associated with this state.
716      *
717      * @param newBlock The block to add.
718      * @throws ControllerException upon error
719      */

720     protected void addBlock(Block newBlock)
721             throws ControllerException {
722         myResponse.addBlock(newBlock);
723     } /* addBlock(Block) */
724
725
726     /**
727      * addAutoInput is a convenience method that creates a new Input object based on
728      * the specified field parameters and adds the input object to this
729      * controller object.
730      * <p/>
731      * Creation date: (7/20/00 3:43:14 PM)
732      * author: Adam Rossi, PlatinumSolutions
733      *
734      * @param fieldName java.lang.String
735      * @param friendlyName the input's label
736      * @param defaultValue java.lang.String
737      * @param displayLength The size of the input text box
738      * @param maxLength The maximum input length of the input.
739      * @param validValues The valid value list associated with the input
740      * (for drop-down multivalue inputs only)
741      * @throws ControllerException upon error
742      */

743     protected void addAutoInput(String JavaDoc fieldName, String JavaDoc friendlyName,
744                                 String JavaDoc defaultValue, int displayLength,
745                                 int maxLength, Vector JavaDoc validValues)
746             throws ControllerException {
747         myResponse.addAutoInput(fieldName, friendlyName, defaultValue,
748                 displayLength, maxLength, validValues);
749     }
750
751     /**
752      * Adds an input object to the controller response
753      *
754      * @param newInput The input object to add
755      * @throws ControllerException upon error
756      */

757     protected void addInput(Input newInput)
758             throws ControllerException {
759         myResponse.addInput(newInput);
760     }
761
762     /**
763      * Adds an output object to the controller response
764      *
765      * @param newOutput The output object to add
766      * @throws ControllerException upon error
767      */

768     protected void addOutput(Output newOutput)
769             throws ControllerException {
770         myResponse.addOutput(newOutput);
771     }
772
773     /**
774      * addAutoInput is a convenience method that creates a new Input object based on
775      * the specified field parameters and adds the input object to this
776      * controller object.
777      * <p/>
778      * Creation date: (7/20/00 3:43:14 PM)
779      * <p/>
780      * author: Adam Rossi, PlatinumSolutions
781      *
782      * @param fieldName java.lang.String
783      * @param dbClassName java.lang.String
784      * @param defaultValue java.lang.String
785      * @throws ControllerException upon error
786      */

787     protected void addAutoInput(String JavaDoc fieldName, String JavaDoc dbClassName,
788                                 String JavaDoc defaultValue)
789             throws ControllerException {
790         myResponse.addAutoInput(fieldName, dbClassName, defaultValue);
791     }
792
793     /**
794      * addAutoInput is a convenience method that creates a new Input object based on
795      * the specified field parameters and adds the input object to this
796      * controller object.
797      * <p/>
798      * Creation date: (7/20/00 3:43:14 PM)
799      * author: Adam Rossi, PlatinumSolutions
800      *
801      * @param fieldName java.lang.String
802      * @param friendlyName The label of the new input
803      * @param dbClassName java.lang.String
804      * @param defaultValue java.lang.String
805      * @throws ControllerException upon error
806      */

807     protected void addAutoInput(String JavaDoc fieldName, String JavaDoc friendlyName,
808                                 String JavaDoc dbClassName, String JavaDoc defaultValue)
809             throws ControllerException {
810         myResponse.addAutoInput(fieldName, friendlyName, dbClassName,
811                 defaultValue);
812     }
813
814     /**
815      * AutoValidate is a quick way to validate the fields of a specified dbobj.
816      * <p/>
817      * Creation date: (7/19/00 6:06:21 PM)
818      * author: Adam Rossi, PlatinumSolutions
819      *
820      * @param checkClassName The class name to perform the error checking
821      * @param errorCollection The error collection to get populated with validation errors
822      * if validation on any particular field fails.
823      * @throws com.jcorporate.expresso.core.controller.ValidationException
824      * The exception description.
825      * @throws ControllerException upon error
826      */

827     protected void autoValidate(String JavaDoc checkClassName,
828                                 ErrorCollection errorCollection)
829             throws ValidationException, ControllerException {
830         myResponse.autoValidate(checkClassName, errorCollection);
831     }
832
833     /**
834      * AutoValidate is a quick way to validate the fields of a specified dbobj.
835      * This method has not been tested and may not be correct.
836      * This methods takes an optional requiredFields vector, which just tells the
837      * validation routine which inputs are required.
838      * <p/>
839      * Creation date: (7/19/00 6:06:21 PM)
840      * author: Adam Rossi, PlatinumSolutions
841      *
842      * @param checkClassName The class name to perform the error checking
843      * @param errorCollection The error collection to get populated with validation errors
844      * if validation on any particular field fails.
845      * @param requiredFields Vector of Strings: which inputs are required.
846      * @throws com.jcorporate.expresso.core.controller.ValidationException
847      * Upon validation error
848      * @throws ControllerException upon error
849      */

850     protected void autoValidate(String JavaDoc checkClassName,
851                                 ErrorCollection errorCollection,
852                                 Vector JavaDoc requiredFields)
853             throws ValidationException, ControllerException {
854         myResponse.autoValidate(checkClassName, errorCollection,
855                 requiredFields);
856     }
857
858     /**
859      * If a particular parameter represents an uploaded file (which can be determined
860      * by the isFileParameter(String) method) then this method retrieves the server-side
861      * file name - e.g. the location that has the data that was uploaded stored in it.
862      *
863      * @param paramName The parameter name that is expected to have a file associated with.
864      * @return java.lang.String the location on the filesystem of the temporary stored
865      * file.
866      */

867     protected String JavaDoc getFileName(String JavaDoc paramName) {
868         return myRequest.getFileName(paramName);
869     }
870
871     /**
872      * get attribute from request
873      *
874      * @param attrib The name of an "attribute" for this ControllerElement item
875      * @return java.lang.String The attribute value
876      */

877     protected String JavaDoc getAttribute(String JavaDoc attrib) {
878         return (String JavaDoc) myRequest.getAttrib(attrib);
879     }
880
881     /**
882      * ?
883      *
884      * @param paramName The parameter name to retrieve
885      * @return java.lang.Object
886      * @throws ControllerException upon conversion error
887      */

888     public Object JavaDoc getObjectParameter(String JavaDoc paramName)
889             throws ControllerException {
890         return myRequest.getObjectParameter(paramName);
891     }
892
893     /**
894      * Return the name of the method that will handle transitions to this
895      * state.
896      *
897      * @return the handler name, or possibly null if the
898      */

899     public String JavaDoc getHandlerName() {
900         return this.handlerName;
901     }
902
903     /**
904      * Use this function to bypass the automatic function naming that goes on
905      * based upon the state
906      *
907      * @param newName the name that you want the controller to automatically call when
908      * transitioning to this state.
909      */

910     public void setHandlerName(String JavaDoc newName) {
911         this.handlerName = newName;
912     }
913
914     /**
915      * ?
916      *
917      * @param paramName The parameter name to retrieve
918      * @return java.lang.String
919      */

920     public String JavaDoc getInitParameter(String JavaDoc paramName) {
921         return myRequest.getInitParameter(paramName);
922     }
923
924     /**
925      * Return the success transition. This is the transition that will be
926      * executed if this state returns without errors in the error collection.
927      *
928      * @return Transition object
929      */

930     public Transition getSuccessTransition() {
931         return successTransition;
932     }
933
934     /**
935      * Get the user name
936      *
937      * @return java.lang.String login name of the user
938      * @deprecated 3/5/04 use ControllerRequest getUid() instead.
939      */

940     public String JavaDoc getUser() {
941         return myRequest.getUser();
942     }
943
944     /**
945      * Fetch the value for the given parameter. Return null
946      * if there is no such parameter
947      *
948      * @param paramCode Code of the parameter desired
949      * @return java.lang.String The parameter value.
950      * @throws ControllerException upon error
951      */

952     public String JavaDoc getParameter(String JavaDoc paramCode)
953             throws ControllerException {
954         if (myRequest == null) {
955             throw new ControllerException("No request object available " +
956                     "- did this state's 'run' method called super.run?");
957         }
958
959         return myRequest.getParameter(paramCode);
960     }
961
962     /**
963      * Does a specified parameter refer to an uploaded file?
964      *
965      * @param paramName The parameter name to check.
966      * @return true if the parameter is a file parameter.
967      */

968     public boolean isFileParameter(String JavaDoc paramName) {
969         return myRequest.isFileParameter(paramName);
970     }
971
972     /**
973      * Should this state be run within an SSL protocol (if SSL is available)
974      *
975      * @return true if SSL should be used for this state
976      */

977     public boolean isSecure() {
978         return this.secure;
979     }
980
981     /**
982      * Return the name of the database connection we use - or null
983      * for the default connection
984      *
985      * @return java.lang.String
986      */

987     public String JavaDoc getDBName() {
988         return myRequest.getDataContext();
989     }
990
991     /**
992      * Return the name of the database connection we use - or null
993      * for the default connection
994      *
995      * @return java.lang.String
996      */

997     public String JavaDoc getDataContext() {
998         return myRequest.getDataContext();
999     }
1000
1001    /**
1002     * Gets the ControllerRequest object associated with this state.
1003     *
1004     * @return the ControllerRequest Object associated with this state.
1005     */

1006    protected ControllerRequest getControllerRequest() {
1007        return myRequest;
1008    }
1009
1010    /**
1011     * Retrieves the ControllerResponse object associated with this state
1012     *
1013     * @return ControllerResponse object associated with this state.
1014     */

1015    protected ControllerResponse getControllerResponse() {
1016        return myResponse;
1017    }
1018
1019    /**
1020     * Calculates the appropriate method name based upon the name of the state
1021     * to be used in setName. and sets the handlerName String to that value.
1022     *
1023     * @param stateName The name of the state to calculate the handler name.
1024     */

1025    protected void calculateHandlerName(String JavaDoc stateName) {
1026        FastStringBuffer fsb = FastStringBuffer.getInstance();
1027        try {
1028            fsb.append("run");
1029            fsb.append(Character.toUpperCase(stateName.charAt(0)));
1030            fsb.append(stateName.substring(1));
1031            fsb.append("State");
1032            handlerName = fsb.toString();
1033        } finally {
1034            fsb.release();
1035            fsb = null;
1036        }
1037    }
1038
1039    /**
1040     * returns a copy of itself
1041     *
1042     * @return a State instance
1043     * @throws java.lang.CloneNotSupportedException
1044     * as specified by the object API
1045     */

1046    public Object JavaDoc clone()
1047            throws java.lang.CloneNotSupportedException JavaDoc {
1048        Object JavaDoc o = (State) super.clone();
1049
1050        synchronized (this) {
1051            State s = (State) o;
1052            s.setName(getName());
1053            s.setDescription(getDescription());
1054            s.optionalParameters = new ArrayList JavaDoc(optionalParameters);
1055            s.requiredParameters = new ArrayList JavaDoc(requiredParameters);
1056
1057            if (paramMasks != null) {
1058                s.paramMasks = new HashMap JavaDoc(paramMasks);
1059            }
1060            if (paramMaskErrors != null) {
1061                s.paramMaskErrors = new HashMap JavaDoc(paramMaskErrors);
1062            }
1063
1064            s.errorState = errorState;
1065            s.stateFormClass = stateFormClass;
1066
1067            if (successTransition != null) {
1068                s.successTransition = (Transition) successTransition.clone();
1069            }
1070            if (errorTransition != null) {
1071                s.errorTransition = (Transition) errorTransition.clone();
1072            }
1073
1074            //Not cloning returnToSender since this would not be set in the controller's
1075
//constructor (that's where this is used).
1076
}
1077
1078        return o;
1079    }
1080
1081    /**
1082     * Saves the errors to the controller response
1083     *
1084     * @param e The error collection to save
1085     * @throws ControllerException upon error
1086     * @deprecated 3/4/04 [v5.5] Use response.saveErrors instead.
1087     */

1088    protected void saveErrors(ErrorCollection e)
1089            throws ControllerException {
1090        myResponse.saveErrors(e);
1091    }
1092
1093    /**
1094     * Set the error transition. This is the transition that will be
1095     * executed if this state returns any errors in the error collection.
1096     *
1097     * @param newErrorTransition A new transition object pointing to the error state
1098     */

1099    public void setErrorTransition(Transition newErrorTransition) {
1100        errorTransition = newErrorTransition;
1101    }
1102
1103    /**
1104     * To the form cache in the controller response
1105     *
1106     * @throws ControllerException upon error
1107     */

1108    protected void setFormCache()
1109            throws ControllerException {
1110        myResponse.setFormCache();
1111    }
1112
1113    /**
1114     * Clears the form cache in the controller response
1115     *
1116     * @throws ControllerException upon error
1117     */

1118    protected void clearFormCache()
1119            throws ControllerException {
1120        myResponse.clearFormCache();
1121    }
1122
1123    /**
1124     * Retrieve the form cash value
1125     *
1126     * @param fieldName The name of the field to retrieve
1127     * @return The field's value, may be null.
1128     * @throws ControllerException upon error
1129     */

1130    protected String JavaDoc getFormCache(String JavaDoc fieldName)
1131            throws ControllerException {
1132        return myResponse.getFormCache(fieldName);
1133    }
1134
1135    protected boolean isParameter(String JavaDoc paramName)
1136            throws ControllerException {
1137        return myRequest.isParameter(paramName);
1138    }
1139
1140    protected void transition(String JavaDoc newState, ControllerRequest req,
1141                              ControllerResponse res)
1142            throws ControllerException, NonHandleableException {
1143        getController().transition(newState, req, res);
1144    }
1145
1146    /**
1147     * Return the return-to-sender transition. This is the transition that will
1148     * serialized and passed to any state that is invoked via a transition that
1149     * has return-to-sender enabled.
1150     *
1151     * @return Transition object
1152     */

1153    public Transition getReturnToSender() {
1154        return returnToSender;
1155    }
1156
1157    public PersistentSession getSession()
1158            throws ControllerException {
1159        return myRequest.getSession();
1160    }
1161
1162    /**
1163     * Return the class name (if any) of the state form associated with
1164     * this state.
1165     *
1166     * @return java.lang.String
1167     */

1168    public String JavaDoc getStateFormClass() {
1169        return stateFormClass;
1170    }
1171
1172    /**
1173     * Retrieve the State user ID.
1174     *
1175     * @return integer user ID
1176     * @throws ControllerException upon error
1177     */

1178    protected int getUid()
1179            throws ControllerException {
1180        return myRequest.getUid();
1181    }
1182
1183    /**
1184     * If any parameters for this state have an associated regular
1185     * expression "mask", verify that the value for the parameter
1186     * matches the mask.
1187     *
1188     * @throws ControllerException upon error
1189     */

1190    public void checkParamMasks()
1191            throws ControllerException {
1192        if (paramMasks == null) {
1193            return;
1194        }
1195
1196        String JavaDoc oneParamName = null;
1197        String JavaDoc oneParamValue = null;
1198
1199        // for (Enumeration ee = getParameters().elements(); ee.hasMoreElements(); ) {
1200
// oneParamName = (String) ee.nextElement();
1201
// oneParamValue = getParameter(oneParamName);
1202
// checkMask(oneParamName, oneParamValue, (String) paramMasks.get(oneParamName));
1203
// }
1204
//
1205
// for (Enumeration eo = getOptionalParameters().elements(); eo.hasMoreElements(); ) {
1206
// oneParamName = (String) eo.nextElement();
1207
// oneParamValue = StringUtil.notNull(getParameter(oneParamName));
1208
// if (!oneParamValue.equals("")) {
1209
// checkMask(oneParamName, oneParamValue, (String) paramMasks.get(oneParamName));
1210
// }
1211
// }
1212
//First go through all required parameters
1213
for (Iterator JavaDoc i = this.requiredParameters.iterator(); i.hasNext();) {
1214            oneParamName = (String JavaDoc) i.next();
1215            oneParamValue = getParameter(oneParamName);
1216            checkMask(oneParamName, oneParamValue,
1217                    (Pattern) paramMasks.get(oneParamName));
1218        }
1219        //Now go through all optional parameters
1220
for (Iterator JavaDoc i = this.optionalParameters.iterator(); i.hasNext();) {
1221            oneParamName = (String JavaDoc) i.next();
1222            oneParamValue = StringUtil.notNull(getParameter(oneParamName));
1223
1224            if (oneParamValue.length() > 0) {
1225                checkMask(oneParamName, oneParamValue,
1226                        (Pattern) paramMasks.get(oneParamName));
1227            }
1228        }
1229    }
1230
1231    /**
1232     * Returns the errors collection of this current request and current state.
1233     *
1234     * @return The ControllerResponse error collection
1235     * @throws ControllerException upon error
1236     */

1237    public ErrorCollection getErrors()
1238            throws ControllerException {
1239        return myResponse.getErrors();
1240    }
1241
1242    /**
1243     * Adds an error to this controllerResponse's Error Collection
1244     *
1245     * @param newError The error string to add.
1246     * @throws ControllerException upon error
1247     */

1248    public void addError(String JavaDoc newError)
1249            throws ControllerException {
1250        myResponse.addError(newError);
1251    }
1252
1253    /**
1254     * Checks a parameter given to the controller against a defined regular
1255     * expression mask. Puts an error in the error collection if there is
1256     * a problem.
1257     *
1258     * @param paramName The state parameter name to check
1259     * @param paramValue The value given the state to check against
1260     * @param compiledRegExp The compiled Perl 5 regular expression.
1261     * @throws ControllerException if there's an error with the regular expression
1262     * mask.
1263     */

1264    protected void checkMask(String JavaDoc paramName, String JavaDoc paramValue,
1265                             Pattern compiledRegExp)
1266            throws ControllerException {
1267        if (compiledRegExp == null) {
1268            return;
1269        }
1270
1271
1272        if (!getPatternMatcher().matches(paramValue, compiledRegExp)) {
1273            String JavaDoc maskError = null;
1274
1275            if (paramMaskErrors != null) {
1276                maskError = StringUtil.notNull((String JavaDoc) paramMaskErrors.get(paramName));
1277            }
1278            if (maskError == null || maskError.length() == 0) {
1279                String JavaDoc err = "Value '" + paramValue +
1280                        "' supplied for parameter '" + paramName +
1281                        "' does not" +
1282                        " match the regular expression specified for this field.";
1283                addError(err);
1284            } else {
1285                if (maskError != null) {
1286                    addError(maskError);
1287                }
1288            }
1289        }
1290    } /* checkMask */
1291
1292
1293    /**
1294     * Convenience method - simply passes the request for a string on to
1295     * the ControllerResponse object associated with this State
1296     *
1297     * @param key The key to format
1298     * @param args The formatting arguments for the key.
1299     * @return The i18n message that key points to.
1300     * @throws ControllerException upon error
1301     */

1302    protected String JavaDoc getString(String JavaDoc key, Object JavaDoc[] args)
1303            throws ControllerException {
1304        if (myResponse != null) {
1305            return myResponse.getString(key, args);
1306        }
1307
1308        return key;
1309    }
1310
1311    /**
1312     * Convenience method - simply passes the request for a string on to
1313     * the ControllerResponse object associated with this State
1314     *
1315     * @param key the message bundle key
1316     * @return java.lang.String
1317     * @throws ControllerException upon error
1318     */

1319    protected String JavaDoc getString(String JavaDoc key)
1320            throws ControllerException {
1321        return getString(key, new Object JavaDoc[]{});
1322    }
1323
1324    /**
1325     * Returns a hash code value for the object.
1326     *
1327     * @return a hash code value for this object.
1328     * @todo Implement this java.lang.Object method
1329     */

1330    public int hashCode() {
1331        return name.hashCode();
1332    }
1333} /* State */
1334
Popular Tags