KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > controller > dbmaint > DynamicCmd


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.services.controller.dbmaint;
66
67 import com.jcorporate.expresso.core.controller.Block;
68 import com.jcorporate.expresso.core.controller.Controller;
69 import com.jcorporate.expresso.core.controller.ControllerException;
70 import com.jcorporate.expresso.core.controller.ControllerRequest;
71 import com.jcorporate.expresso.core.controller.ControllerResponse;
72 import com.jcorporate.expresso.core.controller.Input;
73 import com.jcorporate.expresso.core.controller.NonHandleableException;
74 import com.jcorporate.expresso.core.controller.Output;
75 import com.jcorporate.expresso.core.controller.State;
76 import com.jcorporate.expresso.core.controller.Transition;
77 import com.jcorporate.expresso.core.controller.session.PersistentSession;
78 import com.jcorporate.expresso.core.dataobjects.DataObject;
79 import com.jcorporate.expresso.core.dataobjects.Defineable;
80 import com.jcorporate.expresso.core.dataobjects.Securable;
81 import com.jcorporate.expresso.core.db.DBException;
82 import com.jcorporate.expresso.core.dbobj.DBObject;
83 import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
84 import com.jcorporate.expresso.core.dbobj.ValidValue;
85 import com.jcorporate.expresso.core.misc.ConfigManager;
86 import com.jcorporate.expresso.core.misc.ConfigurationException;
87 import com.jcorporate.expresso.core.misc.StringUtil;
88 import com.jcorporate.expresso.core.misc.URLUTF8Encoder;
89 import com.jcorporate.expresso.core.security.User;
90 import com.jcorporate.expresso.kernel.util.ClassLocator;
91 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
92 import com.jcorporate.expresso.services.dbobj.DBObjLimit;
93 import com.jcorporate.expresso.services.dbobj.Setup;
94 import org.apache.log4j.Logger;
95
96 import java.util.HashMap JavaDoc;
97 import java.util.Iterator JavaDoc;
98 import java.util.Map JavaDoc;
99 import java.util.StringTokenizer JavaDoc;
100
101
102 /**
103  * Base class for all command classes. This class provides the execute()
104  * method which all subclasses need to override. IT does some basic functionality
105  * that all the DBMaint states need, such as load the given DBObject as
106  * specified.
107  *
108  * @author Michael Nash, contributions by Kevin King et al
109  */

110 public abstract class DynamicCmd
111         extends State {
112
113
114     /**
115      * Flag to determine if we need to show the 'next page' icon
116      */

117     protected boolean showNext = false;
118
119     /**
120      * Flag to determine if we need to show the 'previous page' icon
121      */

122     protected boolean showPrev = false;
123
124     private String JavaDoc searchParam = "";
125
126     /**
127      * If we are handing master/detail DB objects, then the block containing
128      * /* the transitions to navigate the master/detail records is stored in session
129      * /* under this key
130      */

131     public static String JavaDoc masterObjKey = "com.jcorporate.expresso.services.controller.DBMaint.MasterObj";
132
133     /* fieldsParam indicates the fields for this command that have a */
134     /* predetermined value - e.g. fields that are prompted for */
135     /* during an add or search and are always part of the search */
136     /* criteria during a search */
137     private String JavaDoc fieldsParam = "";
138
139     /**
140      * The current dataobject used by the DBMaint subclasses.
141      */

142     private DataObject myDataObject = null;
143
144     /**
145      * The log4j logger for this system.
146      */

147     private static transient Logger log = Logger.getLogger(DynamicCmd.class);
148
149     /**
150      * A map of fields that have fixed values (ie cannot be modified by
151      * user input)
152      */

153     private Map JavaDoc fixedFields = null;
154
155     /**
156      * Allows counting total records to be skipped so we can improve
157      * performance on large tables.
158      */

159     protected boolean countTotalRecords = true;
160
161
162     private String JavaDoc controllerName = null;
163
164     /**
165      * Default constructor
166      */

167     public DynamicCmd() {
168
169     }
170
171     /**
172      * Constructor most often used
173      *
174      * @param code The internal name of the state
175      * @param descrip The friendly name of the state
176      */

177     public DynamicCmd(String JavaDoc code, String JavaDoc descrip) {
178         super(code, descrip);
179     } /* DynamicCmd(String, String) */
180
181     /**
182      * @param newParam The new searching paramter String
183      */

184     protected void setSearchParam(String JavaDoc newParam) {
185         searchParam = StringUtil.notNull(newParam);
186     } /* setSearchParam(String) */
187
188     /**
189      * Return the "decoded" search parameter, consisting of a series
190      * of fields and values pipe-delimited
191      *
192      * @return The decoded URL serach parameter
193      * @throws ControllerException upon error
194      */

195     protected String JavaDoc getSearchParam()
196             throws ControllerException {
197         if (searchParam.equals("")) {
198             searchParam = URLUTF8Encoder.decode(StringUtil.notNull(getParameter("search")));
199         }
200
201         return searchParam;
202     } /* getSearchParam() */
203
204
205     /**
206      * Set a encoded 'fields' parameter,
207      * consisting of a series of pipe-delimited fields and values
208      *
209      * @param newParam ??
210      */

211     protected void setFieldsParam(String JavaDoc newParam) {
212         if (newParam != null) {
213             fieldsParam = newParam;
214         } else {
215             fieldsParam = "";
216         }
217     } /* setFieldsParam(String) */
218
219     /**
220      * Return the "decoded" 'fields' parameter,
221      * consisting of a series of pipe-delimited fields and values
222      *
223      * @return The fields Parameter as java.lang.String
224      */

225     protected String JavaDoc getFieldsParam()
226             throws ControllerException {
227         if (fieldsParam.equals("")) {
228             fieldsParam = URLUTF8Encoder.decode(StringUtil.notNull(getParameter("fields")));
229         }
230
231         return fieldsParam;
232     } /* getFieldsParam() */
233
234
235     /**
236      * <p>Fixed fields are a hastable of field values keyed to field names that
237      * should not be modified. The Input of a fixed field should be rendered
238      * read only.</p>
239      * <p>The fields that are fixed can be defined in the 'fields' parameter
240      * by specifying which fields should be fixed. This is useful for master/
241      * detail relationship specifications</p>
242      *
243      * @return java.util.Map
244      */

245     protected Map JavaDoc getFixedFields()
246             throws ControllerException {
247         if (fixedFields == null) {
248             fixedFields = new HashMap JavaDoc();
249
250             if (!StringUtil.notNull(getFieldsParam()).equals("")) {
251                 StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(getFieldsParam(),
252                         "|");
253                 String JavaDoc oneFieldName = null;
254                 String JavaDoc oneFieldValue = null;
255
256                 while (stk.hasMoreTokens()) {
257                     oneFieldName = stk.nextToken();
258
259                     if (!stk.hasMoreTokens()) {
260                         throw new ControllerException("Parameter 'fields' must contain " +
261                                 "name/value pairs seperated with the '|' symbol");
262                     }
263
264                     oneFieldValue = stk.nextToken();
265                     fixedFields.put(oneFieldName, oneFieldValue);
266                 }
267             }
268         }
269
270         return fixedFields;
271     }
272
273     /**
274      * Remove %20 from a string replacing it with spaces
275      *
276      * @param orig Original string
277      * @return String Result string with %20 replaced by spaces
278      */

279     protected String JavaDoc decode(String JavaDoc orig) {
280         String JavaDoc newString = orig;
281         int pos;
282
283         while ((pos = newString.indexOf("%20")) > -1) {
284             System.out.println("pos:" + pos);
285             newString = newString.substring(0, pos) + " " +
286                     newString.substring(pos + 3);
287         }
288         while ((pos = newString.indexOf("%2B")) > -1) {
289             System.out.println("pos:" + pos);
290             newString = newString.substring(0, pos) + "+" +
291                     newString.substring(pos + 3);
292         }
293
294         return newString;
295     } /* decode(String) */
296
297     /**
298      * All of the sub-classes of DynamicCmd extend the run method to perform their
299      * functionality.
300      * <p>This part of run is an important part in the it adds what is known as
301      * the 'nav block' to the jsp pages. It also loads a dbobject into memory
302      * corresponding to the dbobject specified by the DBMaint parameters</p>
303      *
304      * @param newParams The <code>ControllerRequest</code> object
305      * @param newResponse The <code>ControllerResponse</code> object
306      * @throws NonHandleableException upon fatal error
307      */

308     public void run(ControllerRequest newParams,
309                     ControllerResponse newResponse)
310             throws ControllerException, NonHandleableException {
311         super.run(newParams, newResponse);
312
313         try {
314             initializeDBObj();
315             add(new Output("dbobj", URLUTF8Encoder.decode(StringUtil.notNull(getParameter("dbobj")))));
316
317             if (newParams.getParameters().containsKey("nocount")) {
318                 this.countTotalRecords = false;
319             }
320
321             /* if any key values present then recover them */
322             setFields(myDataObject, URLUTF8Encoder.decode(StringUtil.notNull(getParameter("fields"))));
323
324             if (StringUtil.notNull(getParameter("details")).equals("y")) {
325                 PersistentSession mySession = getSession();
326                 Block navBlock = (Block) mySession.getPersistentAttribute(masterObjKey);
327
328                 if (navBlock != null) {
329                     add(navBlock);
330                 } else {
331                     throw new ControllerException("'detail' was specified, but no navigation block" +
332                             " was found in session");
333                 }
334             }
335         } catch (DBException de) {
336             throw new ControllerException(de);
337         }
338     } /* run() */
339
340
341     /**
342      * Base class
343      * Is this field a key in the given database object?
344      *
345      * @param fieldName The name of the field to check
346      * @return boolean True if the fieldname is a key field for the
347      * current object
348      * @throws DBException If unable to determine if the field is a key
349      * due to other errors
350      */

351     protected boolean isKeyField(String JavaDoc fieldName)
352             throws DBException, ControllerException {
353         for (Iterator JavaDoc e = getDataObject().getMetaData().getKeyFieldListArray().iterator();
354              e.hasNext();) {
355             if (fieldName.equalsIgnoreCase((String JavaDoc) e.next())) {
356                 return true;
357             }
358         }
359
360         return false;
361     } /* isKeyField(String) */
362
363
364     /**
365      * <p>Display a small table of icons giving the user the option to proceed
366      * directly to a search, add, or list function from this form. Only
367      * the functions this user are allowed to do are shown</p>
368      * <p>If the record being displayed is a 'detail' record, then 'search' and
369      * 'fields' paramters are added. This helps specify the criteria (meaning
370      * all items here must have the same key as the master</p>
371      * *
372      *
373      * @throws DBException If an error occurrs determining what functions
374      * this user is allowed to perform
375      */

376     protected void showOptions()
377             throws DBException, ControllerException {
378         Block myTable = new Block("buttons");
379         DataObject myDBObj = getDataObject();
380         String JavaDoc myDBObjName = ((Object JavaDoc) myDBObj).getClass().getName();
381         String JavaDoc tempParam = null;
382         addBlock(myTable);
383
384         boolean canSearch = false;
385         boolean allowInsecure = "y".equalsIgnoreCase(Setup.getValue(this.getDBName(), "insecureDBMaint"));
386         if (getUid() == SecuredDBObject.SYSTEM_ACCOUNT
387                 || User.getUserFromId(getUid(), this.getControllerRequest().getDataContext()).isAdmin()) {
388             // all access ok
389
canSearch = true;
390         } else {
391             if (myDBObj instanceof Securable) {
392                 try {
393                     ((Securable) myDBObj).isAllowed("S");
394                     canSearch = true;
395                 } catch (SecurityException JavaDoc ex) {
396                     canSearch = false;
397                 }
398             } else {
399                 canSearch = allowInsecure;
400             }
401         }
402
403         Integer JavaDoc pageLimitObj = (Integer JavaDoc) myDBObj.getAttribute("pageLimit");
404         int pageLimit;
405
406         if (pageLimitObj != null) {
407             pageLimit = pageLimitObj.intValue();
408         } else {
409             pageLimit = 0;
410         }
411         if ((pageLimit > 0) && (getPageNumber() > 1) && (showPrev)) {
412
413             Transition prevSet = new Transition();
414             prevSet.setName("prevSet");
415             prevSet.setDescription("Previous " + pageLimit + " records");
416             prevSet.addParam("dbobj", myDBObjName);
417             prevSet.addParam(Controller.STATE_PARAM_KEY, "List");
418             prevSet.addParam("page",
419                     Integer.toString(getPageNumber() - 1));
420
421             if (myDBObj instanceof Defineable) {
422                 prevSet.addParam("definition", ((Defineable) myDBObj).getDefinitionName());
423             }
424
425             //Do this if then stuff to clean up the URLS for non-specified
426
//parameters
427
tempParam = getFieldsParam();
428
429             if (tempParam.length() > 0) {
430                 prevSet.addParam("fields", URLUTF8Encoder.encode(tempParam));
431             }
432
433             tempParam = getSearchParam();
434
435             if (tempParam.length() > 0) {
436                 prevSet.addParam("search", URLUTF8Encoder.encode(tempParam));
437             }
438
439             tempParam = getParameter("back");
440
441             if (tempParam != null && tempParam.length() > 0) {
442                 prevSet.addParam("back", getParameter("back"));
443             }
444             if (StringUtil.notNull(getParameter("details")).equals("y")) {
445                 prevSet.addParam("details", "y");
446             }
447             if (countTotalRecords == false) {
448                 prevSet.addParam("nocount", "");
449             }
450
451             myTable.add(prevSet);
452         }
453         if (canSearch) {
454             Transition listAction = new Transition();
455             listAction.setName("List");
456             listAction.setLabel("List");
457             listAction.addParam("dbobj", myDBObjName);
458             listAction.addParam(Controller.STATE_PARAM_KEY, "SearchList");
459             tempParam = getFieldsParam();
460
461             if (tempParam.length() > 0) {
462                 listAction.addParam("fields", URLUTF8Encoder.encode(tempParam));
463             }
464             if (StringUtil.notNull(getParameter("details")).equals("y")) {
465                 listAction.addParam("details", "y");
466                 tempParam = getSearchParam();
467
468                 if (tempParam.length() > 0) {
469                     listAction.addParam("search",
470                             URLUTF8Encoder.encode(tempParam));
471                 }
472             }
473             if (countTotalRecords == false) {
474                 listAction.addParam("nocount", "");
475             }
476
477             tempParam = getParameter("back");
478
479             if (tempParam != null && tempParam.length() > 0) {
480                 listAction.addParam("back", tempParam);
481             }
482
483             if (myDBObj instanceof Defineable) {
484                 listAction.addParam("definition", ((Defineable) myDBObj).getDefinitionName());
485             }
486
487
488             listAction.setDescription("List Selected Records");
489             myTable.add(listAction);
490         }
491
492         boolean canAdd;
493         if (myDBObj instanceof Securable) {
494             try {
495                 ((Securable) myDBObj).isAllowed("A");
496                 canAdd = true;
497             } catch (SecurityException JavaDoc ex) {
498                 canAdd = false;
499             }
500         } else {
501             canAdd = allowInsecure;
502         }
503
504
505         if (canAdd) {
506             Transition addAction = new Transition();
507             addAction.setName("Add");
508             addAction.setLabel("Add");
509             addAction.addParam("dbobj", myDBObjName);
510             addAction.addParam(Controller.STATE_PARAM_KEY, "Add");
511             if (myDBObj instanceof Defineable) {
512                 addAction.addParam("definition", ((Defineable) myDBObj).getDefinitionName());
513             }
514
515             tempParam = getFieldsParam();
516             if (tempParam.length() > 0) {
517                 addAction.addParam("fields", URLUTF8Encoder.encode(tempParam));
518             }
519
520             tempParam = getSearchParam();
521
522             if (tempParam.length() > 0) {
523                 addAction.addParam("search", URLUTF8Encoder.encode(tempParam));
524             }
525             if (countTotalRecords == false) {
526                 addAction.addParam("nocount", "");
527             }
528             if (StringUtil.notNull(getParameter("details")).equals("y")) {
529                 addAction.addParam("details", "y");
530             }
531
532             tempParam = getParameter("back");
533
534             if (tempParam != null && tempParam.length() > 0) {
535                 addAction.addParam("back", tempParam);
536             }
537
538             addAction.setDescription("Add New Record");
539             myTable.add(addAction);
540         }
541
542         if (canSearch) {
543             Transition searchAction = new Transition();
544             searchAction.setName("Search");
545             searchAction.setLabel("Search");
546             searchAction.addParam("dbobj", myDBObjName);
547             searchAction.addParam(Controller.STATE_PARAM_KEY, "Search");
548             if (myDBObj instanceof Defineable) {
549                 searchAction.addParam("definition", ((Defineable) myDBObj).getDefinitionName());
550             }
551
552             if (countTotalRecords == false) {
553                 searchAction.addParam("nocount", "");
554             }
555
556             tempParam = getFieldsParam();
557
558             if (tempParam.length() > 0) {
559                 searchAction.addParam("fields",
560                         URLUTF8Encoder.encode(tempParam));
561             }
562
563 // if (StringUtil.notNull(getParameter("details")).equals("y")) {
564
//
565
// tempParam = getSearchParam();
566
//
567
// if (tempParam.length() > 0) {
568
// searchAction.addParam("search",
569
// URLUTF8Encoder.encode(tempParam));
570
// }
571
// }
572

573             tempParam = getParameter("back");
574
575             if (tempParam != null && tempParam.length() > 0) {
576                 searchAction.addParam("back", tempParam);
577             }
578             if (StringUtil.notNull(getParameter("details")).equals("y")) {
579                 searchAction.addParam("details", "y");
580             }
581
582             searchAction.setDescription("Search for Records");
583             myTable.add(searchAction);
584         }
585         if ((pageLimit > 0) && (showNext)) {
586
587             /* next set */
588             Transition nextSet = new Transition();
589             nextSet.setName("nextSet");
590             nextSet.addParam("dbobj", myDBObjName);
591             if (myDBObj instanceof Defineable) {
592                 nextSet.addParam("definition", ((Defineable) myDBObj).getDefinitionName());
593             }
594             nextSet.addParam(Controller.STATE_PARAM_KEY, "List");
595             nextSet.addParam("page",
596                     Integer.toString(getPageNumber() + 1));
597
598
599             tempParam = getFieldsParam();
600
601             if (tempParam.length() > 0) {
602                 nextSet.addParam("fields", URLUTF8Encoder.encode(tempParam));
603             }
604
605             tempParam = getSearchParam();
606
607             if (tempParam.length() > 0) {
608                 nextSet.addParam("search", URLUTF8Encoder.encode(tempParam));
609             }
610
611             tempParam = getParameter("back");
612
613             if (tempParam != null && tempParam.length() > 0) {
614                 nextSet.addParam("back", tempParam);
615             }
616             if (StringUtil.notNull(getParameter("details")).equals("y")) {
617                 nextSet.addParam("details", "y");
618             }
619             if (countTotalRecords == false) {
620                 nextSet.addParam("nocount", "");
621             }
622
623             nextSet.setDescription("Next " + pageLimit + " records");
624             myTable.add(nextSet);
625         }
626     } /* showOptions() */
627
628
629     /**
630      * @param theDescrip The Page header to add as String
631      */

632     protected void showUserName(String JavaDoc theDescrip)
633             throws ControllerException {
634         Output unTable = new Output("untable", "");
635         String JavaDoc userName = null;
636         try {
637             userName = User.getLoginFromId(this.getUid(), this.getDataContext());
638         } catch (DBException ex) {
639             log.error("Error retrieving user name", ex);
640             throw new ControllerException("Error retrieving user name");
641         }
642
643         String JavaDoc db = getDBName();
644
645         if (db.equals("")) {
646             db = "default";
647         }
648         if (userName.equals("") || userName.equals("NONE")) {
649             unTable.addNested(new Output("userDescrip", "Not logged in"));
650         } else {
651             unTable.addNested(new Output("userDescrip", userName));
652         }
653
654         unTable.addNested(new Output("pageHeader", theDescrip));
655
656         String JavaDoc dbDescrip = "";
657
658         try {
659             dbDescrip = StringUtil.notNull(ConfigManager.getContext(db).getDescription());
660         } catch (ConfigurationException ce) {
661             throw new ControllerException(ce);
662         }
663         if (dbDescrip.equals("")) {
664             dbDescrip = getDBName();
665         }
666
667         unTable.addNested(new Output("dbDescrip", dbDescrip));
668         addOutput(unTable);
669     } /* showUserName(String) */
670
671
672     /**
673      * Given a class name that contains a DBObject, instantiate an
674      * instance of the object & return it. Also associates the current user
675      * name (from the session) with the object so
676      * that requests to maniupluate the object can be passed through
677      * appropriate security (If the DBObject is of type SecuredDBObject)
678      *
679      * @throws ControllerException if the object cannot be created or set up
680      */

681     protected void initializeDBObj()
682             throws ControllerException {
683         try {
684             String JavaDoc myDBObjName = URLUTF8Encoder.decode(StringUtil.notNull(getParameter("dbobj")));
685             if (log.isDebugEnabled()) {
686                 log.debug("Initializing dbobject '" + myDBObjName + "'");
687             }
688
689             if (myDBObjName.equals("")) {
690                 throw new DBException("Database object name is not specified");
691             }
692             if (myDBObjName.equals("NONE")) {
693                 throw new DBException("Database object name is NONE");
694             }
695
696             //
697
//Special Case Hack....
698
//@todo check for class type and throw error if not possible.
699
//
700
if (com.jcorporate.expresso.core.security.User.class.getName().equals(myDBObjName)) {
701                 myDBObjName = ((Object JavaDoc) new User().getUserInfo()).getClass().getName();
702             }
703
704             try {
705                 myDataObject = (DataObject) ClassLocator.loadClass(myDBObjName).newInstance();
706
707                 if (myDataObject == null) {
708                     throw new DBException("Null object - " +
709                             "instantiate failed for database object " +
710                             myDBObjName);
711                 }
712
713                 if (myDataObject instanceof Defineable) {
714                     boolean initialized = false;
715
716                     //
717
//Special backwards compatible case for AutoDBObjects. They can
718
//be initialized with the 'table' paramter
719
//
720
if (myDBObjName.equals(com.jcorporate.expresso.core.dbobj.AutoDBObject.class.getName())) {
721                         String JavaDoc tableName = getParameter("table");
722
723                         if (tableName.equals("")) {
724                             throw new DBException("Must specify table name for AutoDBObject");
725                         }
726
727                         ((com.jcorporate.expresso.core.dbobj.AutoDBObject) myDataObject).setTargetTable(tableName);
728                         initialized = true;
729                     }
730
731                     //
732
//Otherwise, we use the Defineable interface to set the definition that
733
//we recieved and otherwise initialize the data object.
734
//
735
if (!initialized) {
736                         String JavaDoc definitionName = getParameter("definition");
737                         if (definitionName == null || definitionName.equals("")) {
738                             throw new ControllerException("Must specify definition for Defineable data objects");
739                         }
740
741                         ((Defineable) myDataObject).setDefinitionName(definitionName);
742                     }
743                 }
744             } catch (Exception JavaDoc eo) {
745                 throw new DBException("Exception loading DataObject", eo);
746             }
747
748             if (myDataObject instanceof Securable) {
749                 ((Securable) myDataObject).setRequestingUid(getUid());
750             } else {
751                 if (getUid() == SecuredDBObject.SYSTEM_ACCOUNT
752                         || User.getUserFromId(getUid(), this.getControllerRequest().getDataContext()).isAdmin()) {
753                     // all access ok
754
} else {
755                     String JavaDoc allowInsecure = Setup.getValue(this.getControllerRequest().getDataContext(),
756                             com.jcorporate.expresso.core.ExpressoSchema.class.getName(),
757                             "insecureDBMaint");
758                     if (!(StringUtil.toBoolean(allowInsecure))) {
759                         throw new SecurityException JavaDoc("Access to unsecured Objects not allowed");
760                     }
761                 }
762             }
763
764             myDataObject.setDataContext(getDBName());
765             myDataObject.setLocale(getControllerRequest().getLocale());
766
767             /* Now see if there is a "page limit" for this object */
768             DBObjLimit dl = new DBObjLimit(SecuredDBObject.SYSTEM_ACCOUNT);
769             dl.setDataContext(getDBName());
770             dl.setField("DBObjectName", myDBObjName);
771
772             int pageLimit = 0;
773
774             try {
775                 dl.retrieve();
776                 try {
777                     pageLimit = new Integer JavaDoc(dl.getField("PageLimit")).intValue();
778                 } catch (NumberFormatException JavaDoc ne) {
779                     throw new DBException("Can't use limit of '" +
780                             dl.getField("PageLimit") + "' for " +
781                             myDBObjName);
782                 }
783
784                 myDataObject.setMaxRecords((getPageNumber() * pageLimit) + 1);
785                 myDataObject.setAttribute("pageLimit", new Integer JavaDoc(pageLimit));
786                 if (log.isDebugEnabled()) {
787                     log.debug("Page limit for '" + myDBObjName + "' is " +
788                             pageLimit);
789                 }
790             } catch (com.jcorporate.expresso.core.db.exception.DBRecordNotFoundException ex) {
791                 //Set it per controller defaults then.
792
dl.setField("DBObjectName",
793                         "com.jcorporate.expresso.services.dbobj.ControllerDefault");
794
795                 try {
796                     dl.retrieve();
797                     try {
798                         pageLimit = new Integer JavaDoc(dl.getField("PageLimit")).intValue();
799                     } catch (NumberFormatException JavaDoc ne) {
800                         throw new DBException("Can't use limit of '" +
801                                 dl.getField("PageLimit") +
802                                 "' for " + myDBObjName);
803                     }
804
805                     myDataObject.setMaxRecords((getPageNumber() * pageLimit) + 1);
806                     myDataObject.setAttribute("pageLimit", new Integer JavaDoc(pageLimit));
807                     if (log.isDebugEnabled()) {
808                         log.debug("Page limit for '" + myDBObjName + "' is " +
809                                 pageLimit);
810                     }
811                 } catch (com.jcorporate.expresso.core.db.exception.DBRecordNotFoundException ex2) {
812                     pageLimit = 0;
813                     if (log.isDebugEnabled()) {
814                         log.debug("No page limit for '" + myDBObjName + "'");
815                     }
816                 }
817             }
818         } catch (DBException de) {
819             throw new ControllerException(de);
820         }
821     } /* getDBObj(HttpServletRequest) */
822
823
824     /**
825      * Return the current database object. It is an error to request this if the
826      * current database object is not initialized
827      *
828      * @return the appropriate DBObject
829      * @throws ControllerException if there is no dbobject associated with the
830      * controller state
831      * @deprecated Since Expresso 5.1 Use getDataObject() for compatibility with AutoDBObject,
832      * JoinedDataObject, etc. Will be removed in Expresso 5.2
833      */

834     protected DBObject getCurrentDBObj()
835             throws ControllerException {
836         if (myDataObject == null) {
837             throw new ControllerException("DBObject is not initialized");
838         }
839
840         return (DBObject) myDataObject;
841     }
842
843     /**
844      * Retrieve the data object
845      *
846      * @return the current DataObject for this state
847      * @throws ControllerException upon exception
848      */

849     protected DataObject getDataObject() throws ControllerException {
850         if (myDataObject == null) {
851             throw new ControllerException("DBObject is not initialized");
852         }
853
854         return myDataObject;
855     }
856
857     /**
858      * Returns the current page number as specified in the 'page' parameter
859      *
860      * @return integer representing the current page number
861      */

862     public int getPageNumber()
863             throws ControllerException {
864         String JavaDoc page = StringUtil.notNull(getParameter("page"));
865         int pageNumber = 1;
866
867         if (!page.equals("")) {
868             try {
869                 pageNumber = new Integer JavaDoc(page).intValue();
870             } catch (NumberFormatException JavaDoc ne) {
871                 throw new ControllerException("Page parameter must be " +
872                         "a number if supplied at all");
873             }
874         } else { /* if page not blank */
875             pageNumber = 1;
876         }
877
878         return pageNumber;
879     }
880
881     /**
882      * Sets the fields in the production environment.
883      *
884      * @param myDBObj the data object to set the fields to
885      * @param fieldPairs the piped field name|field value parameters
886      * @throws DBException upon error
887      */

888     protected void setFields(DataObject myDBObj, String JavaDoc fieldPairs)
889             throws DBException {
890         if (fieldPairs.equals("")) {
891             return;
892         }
893
894         StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(URLUTF8Encoder.decode(fieldPairs), "|");
895         String JavaDoc oneFieldName = null;
896         String JavaDoc oneFieldValue = null;
897
898         while (stk.hasMoreTokens()) {
899             oneFieldName = stk.nextToken();
900
901             if (!stk.hasMoreTokens()) {
902                 throw new DBException("Parameter 'fields' must contain " +
903                         "name/value pairs separated with the '|' symbol - it contained '" +
904                         URLUTF8Encoder.decode(fieldPairs) + "'");
905             }
906
907             oneFieldValue = stk.nextToken();
908             myDBObj.set(oneFieldName, oneFieldValue);
909 // myDBObj.setField(oneFieldName, oneFieldValue);
910
}
911     } /* setFields(DataObject, String) */
912
913     /**
914      * Add the fields, details, search and dbobj parameters to a given transition object
915      *
916      * @param t The Transition to add the appropriate parameters to.
917      * @throws ControllerException upon error
918      */

919     protected void addParams(Transition t)
920             throws ControllerException {
921         try {
922             DataObject myDBObj = this.getDataObject();
923
924             if (myDBObj == null) {
925                 throw new DBException("Database object must be " +
926                         "initialized before calling addParams");
927             }
928
929             t.addParam("dbobj", ((Object JavaDoc) myDBObj).getClass().getName());
930
931             String JavaDoc fieldParam = URLUTF8Encoder.encode(getFieldsParam());
932
933             if (!fieldParam.equals("")) {
934                 t.addParam("fields", fieldParam);
935             }
936
937             String JavaDoc searchParam = URLUTF8Encoder.encode(getSearchParam());
938
939             if (!searchParam.equals("")) {
940                 t.addParam("search", searchParam);
941             }
942             if (StringUtil.notNull(getParameter("details")).equals("y")) {
943                 t.addParam("details", "y");
944             }
945
946             if (myDBObj instanceof Defineable) {
947                 t.addParam("definition", ((Defineable) myDBObj).getDefinitionName());
948             }
949
950         } catch (DBException de) {
951             throw new ControllerException(de);
952         }
953     } /* addParams(Transition) */
954
955
956     /**
957      * Show the edit link as often used by the List state or updateupdate state.
958      *
959      * @param fieldName the name of the field to render as a link
960      * @param oneFieldValue the field's value
961      * @param currentRecord the current data object that the field should be
962      * retrieved from.
963      * @param myElement the output element that is going to be decorated
964      * @throws DBException upon data access error
965      * @throws ControllerException upon controller error
966      */

967     protected synchronized void showEditLink(String JavaDoc fieldName,
968                                              String JavaDoc oneFieldValue,
969                                              DataObject currentRecord,
970                                              Output myElement)
971             throws DBException, ControllerException {
972         showEditLink(fieldName, oneFieldValue, currentRecord, myElement,
973                 this.getController().getClass().getName());
974     }
975
976
977     /**
978      * Create a link that is nested to myElement that is for displaying
979      * a BLOB field.
980      *
981      * @param fieldName The name of the field to render the link for.
982      * @param dbobj The DBobject that the field nests in.
983      * @param myElement The Input object that is getting the nested Transition
984      * @param controller The name of the controller to link to
985      */

986     protected void showBlobViewLink(String JavaDoc fieldName,
987                                     DataObject dbobj,
988                                     Input myElement,
989                                     String JavaDoc controller)
990             throws DBException, ControllerException {
991         DataObject myDBObj = this.getDataObject();
992         if (!myDBObj.getFieldMetaData(fieldName).isLongObjectType()) {
993             throw new ControllerException("Field " + fieldName + " must be a long object type");
994         }
995
996
997         Transition t = new Transition();
998 // Transition t = new Transition("view","View"
999
// ,com.jcorporate.expresso.services.controller.DBMaint.class,
1000
// "ViewBlob");
1001

1002        if (controller == null || controller.equals("")) {
1003            controller = com.jcorporate.expresso.services.controller.DBMaint.class.getName();
1004        }
1005
1006        t.setControllerObject(controller);
1007        t.setState("ViewBlob");
1008        t.setName("view");
1009        t.setLabel("View");
1010        t.addParam("fieldName", fieldName);
1011
1012
1013        addParams(t);
1014        myElement.addNested(t);
1015
1016        FastStringBuffer keyString = FastStringBuffer.getInstance();
1017
1018        try {
1019            keyString.append("'");
1020            String JavaDoc oneKeyFieldName = null;
1021            boolean pipeNeeded = false;
1022
1023            for (Iterator JavaDoc e = dbobj.getMetaData().getKeyFieldListArray().iterator();
1024                 e.hasNext();) {
1025                oneKeyFieldName = (String JavaDoc) e.next();
1026
1027                if (pipeNeeded) {
1028                    keyString.append("|");
1029                }
1030
1031                keyString.append(URLUTF8Encoder.encode(dbobj.getDataField(oneKeyFieldName).asString()));
1032                pipeNeeded = true;
1033            }
1034
1035            keyString.append("'");
1036            t.addParam("key", keyString.toString());
1037
1038
1039        } finally {
1040            keyString.release();
1041        }
1042
1043    }
1044
1045    /**
1046     * Write a hyperlink command that allows edit of the current key
1047     *
1048     * @param fieldName The name of the field to have the hyperlink
1049     * @param oneFieldValue The value of the field
1050     * @param currentRecord A DBObject of the current record
1051     * @param myElement The cell in the table representing the current
1052     * field of the current record
1053     * @param controller the name of the controller to use for the edit link (may
1054     * be null)
1055     * @throws DBException If the information to build the link cannot be
1056     * retrieved from the database object
1057     */

1058    protected synchronized void showEditLink(String JavaDoc fieldName,
1059                                             String JavaDoc oneFieldValue,
1060                                             DataObject currentRecord,
1061                                             Output myElement,
1062                                             String JavaDoc controller)
1063            throws DBException, ControllerException {
1064        DataObject myDBObj = this.getDataObject();
1065        if (controller == null || controller.equals("")) {
1066            controller = "com.jcorporate.expresso.services.controller.DBMaint";
1067        }
1068
1069        Transition editLink = new Transition("edit", controller);
1070        editLink.addParam(Controller.STATE_PARAM_KEY, "Update");
1071        addParams(editLink);
1072
1073        FastStringBuffer keyString = FastStringBuffer.getInstance();
1074        FastStringBuffer fieldsString = FastStringBuffer.getInstance();
1075
1076
1077        try {
1078            keyString.append("'");
1079            String JavaDoc oneKeyFieldName = null;
1080            boolean pipeNeeded = false;
1081
1082            for (Iterator JavaDoc e = currentRecord.getMetaData().getKeyFieldListArray().iterator();
1083                 e.hasNext();) {
1084                oneKeyFieldName = (String JavaDoc) e.next();
1085
1086                if (pipeNeeded) {
1087                    keyString.append("|");
1088                }
1089
1090                String JavaDoc keyRecord = currentRecord.getDataField(oneKeyFieldName).asString();
1091                if (keyRecord != null && keyRecord.length() > 0) {
1092                    keyString.append(URLUTF8Encoder.encode(currentRecord.getDataField(oneKeyFieldName).asString()));
1093                }
1094
1095                pipeNeeded = true;
1096            }
1097
1098            keyString.append("'");
1099            editLink.addParam("key", keyString.toString());
1100
1101
1102            if (myDBObj.getFieldMetaData(fieldName).isMultiValued()) {
1103                java.util.List JavaDoc values = myDBObj.getValidValuesList(fieldName);
1104
1105                if (values == null) {
1106                    throw new DBException("Valid values for field " +
1107                            oneKeyFieldName + " from object " +
1108                            myDBObj.getMetaData().getName() + " were null");
1109                }
1110
1111                String JavaDoc fieldValue = null;
1112                ValidValue oneVV = null;
1113
1114                for (Iterator JavaDoc e = values.iterator(); e.hasNext();) {
1115                    oneVV = (ValidValue) e.next();
1116
1117                    if (oneVV.getValue().equals(oneFieldValue)) {
1118                        fieldValue = oneVV.getDescription();
1119                    }
1120                }
1121                if (fieldValue == null) {
1122                    fieldsString.append(oneFieldValue);
1123                    myElement.setContent(oneFieldValue);
1124                } else {
1125                    fieldsString.append((String JavaDoc) fieldValue);
1126                    myElement.setContent((String JavaDoc) fieldValue);
1127                }
1128            } else { /* if field is multi_valued */
1129                fieldsString.append(oneFieldValue);
1130                myElement.setContent(oneFieldValue);
1131            }
1132        } catch (Throwable JavaDoc t) {
1133            log.error("Error building key string", t);
1134            throw new ControllerException("Error building Key String", t);
1135        } finally {
1136            keyString.release();
1137            fieldsString.release();
1138        }
1139
1140        myElement.addNested(editLink);
1141
1142        //editLink.addParam("fields", fieldsString.toString());
1143
} /* showEditLink(String, String, DataObject, Output) */
1144
1145
1146    /**
1147     * Create a key parameter for locating the DBObject. Used in generating transitions
1148     *
1149     * @param srcDBObj the DBObject to generate the key for.
1150     * @return java.lang.String, the pipe delimited URL encoded keys
1151     * @throws ControllerException upon error getting the keys for the DBObject
1152     */

1153    protected String JavaDoc getKeyParameter(DataObject srcDBObj) throws ControllerException {
1154        FastStringBuffer keyParam = FastStringBuffer.getInstance();
1155
1156        try {
1157            boolean needPipe = false;
1158            String JavaDoc oneKeyName = null;
1159
1160            for (Iterator JavaDoc keys = srcDBObj.getMetaData().getKeyFieldListArray().iterator();
1161                 keys.hasNext();) {
1162                oneKeyName = (String JavaDoc) keys.next();
1163
1164                if (needPipe) {
1165                    keyParam.append("|");
1166                }
1167
1168                needPipe = true;
1169                keyParam.append(getDataObject().getDataField(oneKeyName).asString());
1170            }
1171
1172            return keyParam.toString();
1173        } catch (DBException de) {
1174            throw new ControllerException(de);
1175        } finally {
1176            keyParam.release();
1177            keyParam = null;
1178        }
1179    }
1180
1181
1182    /**
1183     * Retrieves the DBObject as specified in the criteria key fields passed
1184     * to the DBMaint controller.
1185     *
1186     * @return DataObject requested by the request parameters
1187     * @throws DBException if unable to retrieve the object
1188     * @throws ControllerException for non-database related errors
1189     */

1190    protected DataObject retrieveMyDBObject() throws DBException, ControllerException {
1191        String JavaDoc allKeys = URLUTF8Encoder.decode(StringUtil.notNull(getParameter("key")));
1192
1193        DataObject myDBObj = this.getDataObject();
1194
1195        /* peel off the quotes if we get 'em */
1196        if (allKeys.startsWith("\'")) {
1197            allKeys = allKeys.substring(1, allKeys.length() - 1);
1198        }
1199
1200        StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(allKeys, "|");
1201        String JavaDoc oneKeyFieldName = null;
1202
1203        for (Iterator JavaDoc e = myDBObj.getMetaData().getKeyFieldListArray().iterator(); e.hasNext();) {
1204            oneKeyFieldName = (String JavaDoc) e.next();
1205
1206            if (!stk.hasMoreTokens()) {
1207                throw new DBException("Not enough key " +
1208                        "field values for all key fields");
1209            }
1210
1211            myDBObj.set(oneKeyFieldName, decode(stk.nextToken()));
1212        }
1213
1214        if (!myDBObj.find()) {
1215            throw new DBException("Unable to find dataobject specified");
1216        }
1217
1218        return myDBObj;
1219    }
1220
1221    /**
1222     * Set the 'myDBObj' variable which is, in turn, used by the rest of the
1223     * DBMaint controller. Use this in derived classes to directly manipulate
1224     * the dbobject.
1225     *
1226     * @param myDBObj the new dataobject to set.
1227     */

1228    protected void setMyDataObject(DataObject myDBObj) {
1229        this.myDataObject = myDBObj;
1230    }
1231
1232    /**
1233     * Retrieves an instance of my dataobject instance. Use this in derived
1234     * classes to directly access the 'myDataObject' variable.
1235     *
1236     * @return DataObject instance.
1237     */

1238    protected DataObject getMyDataObject() {
1239        return myDataObject;
1240    }
1241
1242
1243    /**
1244     * Retrieve the name of the controller we use. This is much faster than
1245     * getController().getClass().getName() because we precalc things once.
1246     *
1247     * @return java.lang.String
1248     * @throws ControllerException upon error
1249     */

1250    protected String JavaDoc getControllerName() throws ControllerException {
1251        if (controllerName == null) {
1252            //following added by pete in order to share mvc traits
1253
controllerName = (String JavaDoc) this.getMyDataObject().getAttribute("mvcController");
1254
1255            if (controllerName == null) {
1256                controllerName = this.getController().getClass().getName();
1257            }
1258        }
1259
1260        return controllerName;
1261    }
1262}
1263
1264/* DynamicCmd */
Popular Tags