KickJava   Java API By Example, From Geeks To Geeks.

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


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.Output;
72 import com.jcorporate.expresso.core.controller.Transition;
73 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData;
74 import com.jcorporate.expresso.core.dataobjects.DataObject;
75 import com.jcorporate.expresso.core.dataobjects.DataObjectMetaData;
76 import com.jcorporate.expresso.core.db.DBException;
77 import com.jcorporate.expresso.core.dbobj.ValidValue;
78 import com.jcorporate.expresso.core.misc.Format;
79 import com.jcorporate.expresso.core.misc.RecordPaginator;
80 import com.jcorporate.expresso.core.security.User;
81
82 import java.text.DateFormat JavaDoc;
83 import java.text.SimpleDateFormat JavaDoc;
84 import java.util.ArrayList JavaDoc;
85 import java.util.Date JavaDoc;
86 import java.util.Iterator JavaDoc;
87 import java.util.Locale JavaDoc;
88 import java.util.StringTokenizer JavaDoc;
89
90
91 /**
92  * Base class for the DBMaint commands that display lists of records, such
93  * as Search and List.
94  *
95  * @author Michael Nash
96  */

97 public abstract class ListBase
98         extends DynamicCmd {
99     private long totalRecordCount = 0;
100
101     private RecordPaginator paginator;
102
103     public ListBase() {
104         super();
105     }
106
107     /**
108      * Constructor
109      *
110      * @param code The name of the state.
111      * @param descrip The friendly name of the state
112      */

113     public ListBase(String JavaDoc code, String JavaDoc descrip) {
114         super(code, descrip);
115     } /* ListBase(String, String) */
116
117     /**
118      * Base class
119      * Search the database for a list of records that match the given criteria
120      * and display them in a table. Key fields are made clickable for the user
121      * to edit/delete the current record (security permitting).
122      *
123      * @throws DBException If the search fails with a database problem
124      */

125     private synchronized void autoList()
126             throws DBException, ControllerException {
127         DataObject myDBObj = this.getDataObject();
128         String JavaDoc oneFieldName = null;
129         long recordCount = 0;
130
131         if (myDBObj == null) {
132             throw new DBException("Database object not initialized - cannot list");
133         }
134
135         DataObjectMetaData metadata = myDBObj.getMetaData();
136
137         showUserName(metadata.getDescription(this.getControllerRequest().getLocale()));
138
139         Block myTable = new Block("recordList");
140         myTable.setDescription(metadata.getDescription(this.getControllerRequest().getLocale()) + " (" +
141                 User.getLoginFromId(this.getUid(), this.getDataContext()) + ")");
142         myTable.setAttribute("table", "Y");
143         addBlock(myTable);
144
145         /* Now the heading row for the table */
146         StringBuffer JavaDoc headerString = new StringBuffer JavaDoc();
147         boolean pipeNeeded = false;
148
149         //following changes by Pete allow viewing a select group of fields, if specified
150
ArrayList JavaDoc browseArrayList = (ArrayList JavaDoc) myDBObj.getAttribute("browseArrayList");
151         boolean hasBrowseArrayList = false;
152
153         if (browseArrayList != null) {
154             hasBrowseArrayList = true;
155         }
156         for (Iterator JavaDoc e = (hasBrowseArrayList)
157                 ? browseArrayList.iterator()
158                 : myDBObj.getMetaData().getFieldListArray().iterator(); e.hasNext();) {
159             oneFieldName = (String JavaDoc) e.next();
160             DataFieldMetaData fieldMetadata = myDBObj.getFieldMetaData(oneFieldName);
161             if (!fieldMetadata.isSecret()) {
162                 if (pipeNeeded) {
163                     headerString.append("|");
164                 }
165
166                 headerString.append(metadata.getDescription(this.getControllerRequest().getLocale(),
167                         oneFieldName));
168                 pipeNeeded = true;
169             }
170         } /* for each field */
171
172
173         myTable.setAttribute("header-row", headerString.toString());
174
175         String JavaDoc sortKey = getSortKey();
176         recordCount = listRecords(sortKey, myTable);
177
178         if (recordCount == 0) {
179             addOutput(new Output("recordCount", "No records found"));
180         } else {
181             addOutput(new Output("recordCount",
182                     "" + totalRecordCount + " records found"));
183
184             addBlock(this.generatePageTransitions(getControllerRequest(),
185                     this.getRecordPaginator(), 10));
186         }
187     } /* autoList() */
188
189     /**
190      * Gleaned from {@link http://www.jguru.com/faq/view.jsp?EID=429821} to
191      * make the SimpleDateFormat give us 4 year dates instead.
192      *
193      * @param df the DateFormat class
194      * @return DateFormat instance
195      */

196     private DateFormat JavaDoc modifyDateFormat(DateFormat JavaDoc df) {
197         SimpleDateFormat JavaDoc sdf = null;
198         try {
199             sdf = (SimpleDateFormat JavaDoc) df;
200         } catch (ClassCastException JavaDoc cce) {
201             return df;
202         }
203         String JavaDoc sTemp = sdf.toPattern();
204         int iLen = sTemp.length();
205         int i = sTemp.lastIndexOf('y') + 1;
206         sTemp = sTemp.substring(0, i) +
207                 "yy" +
208                 (i < iLen
209                 ? sTemp.substring(i, iLen)
210                 : "");
211         sdf.applyPattern(sTemp);
212
213         return sdf;
214     } // end do4
215

216     /**
217      * Same as display value but for Date/DateTime types. Formats things appropriate
218      * to the user's locale
219      *
220      * @param metaData the Data Field's metadata
221      * @param dt The date value to format
222      * @param l the User's Locale gathered from the ControllerResponse object
223      * @return a properly formatted date
224      */

225     private String JavaDoc displayDateValue(DataFieldMetaData metaData, Date JavaDoc dt, Locale JavaDoc l) {
226         if (dt == null) {
227             return "";
228         }
229         if (metaData.isDateOnlyType()) {
230             DateFormat JavaDoc df = DateFormat.getDateInstance(DateFormat.SHORT, l);
231             df = this.modifyDateFormat(df);
232             return df.format(dt);
233         } else if (metaData.isTimeType()) {
234             DateFormat JavaDoc df = DateFormat.getTimeInstance(DateFormat.SHORT, l);
235             df = this.modifyDateFormat(df);
236             return df.format(dt);
237         } else {
238             DateFormat JavaDoc df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
239                     DateFormat.SHORT,
240                     l);
241             df = this.modifyDateFormat(df);
242             return df.format(dt);
243
244         }
245
246     }
247
248     /**
249      * Gets the currently used paginator
250      *
251      * @return RecordPaginator instance
252      */

253     protected RecordPaginator getRecordPaginator() throws ControllerException {
254         if (paginator == null) {
255             paginator = new RecordPaginator();
256         }
257         paginator.setCountRecords(true);
258         paginator.setPageNumber(getPageNumber());
259
260         return paginator;
261     }
262
263     /**
264      * Lists the records for display
265      *
266      * @param sortKey The key to sort against
267      * @param myTable The <code>Block</code> to insert the table into.
268      * @return the total number of records listed
269      * @throws DBException Upon error communicating with the DBObject
270      * @throws ControllerException upon other errors
271      */

272     protected long listRecords(String JavaDoc sortKey, Block myTable)
273             throws DBException, ControllerException {
274         DataObject myDBObj = this.getDataObject();
275
276         int startShowingRecord = 0;
277         int endShowingRecord = 0;
278         paginator = getRecordPaginator();
279         setupListSearchCriteria();
280
281         ArrayList JavaDoc allRecords = paginator.searchAndRetrieve(myDBObj, sortKey);
282         totalRecordCount = paginator.getTotalRecordCount();
283
284         startShowingRecord = paginator.getStartRecordNumber();
285         endShowingRecord = paginator.getEndRecordNumber();
286         if (allRecords.size() > 0) {
287             addRecordsToBlock(allRecords, myTable);
288         }
289
290
291
292
293         //xun li add for record count
294
showNext = paginator.isMoreRecords();
295         addOutput(new Output("recordRange",
296                 "Records " + startShowingRecord + " to " +
297                 endShowingRecord));
298
299         return totalRecordCount;
300     } /* listRecords(String, Output) */
301
302
303     /**
304      * This method determines how the list is sorted. The default sort order
305      * is by the key fields of the underlying DBObject. To change the
306      * default just override this method in a derived class.
307      *
308      * @return String the sort key coded with pipes.
309      * @throws DBException upon error communicating with the DBObject
310      * @throws ControllerException upon other errors
311      */

312     protected String JavaDoc getSortKey()
313             throws DBException, ControllerException {
314
315         DataObject dataobj = this.getDataObject();
316
317         String JavaDoc sortKey = ("");
318         boolean needPipe = false;
319
320         for (Iterator JavaDoc k = dataobj.getMetaData().getKeyFieldListArray().iterator(); k.hasNext();) {
321             if (needPipe) {
322                 sortKey = sortKey + "|";
323             }
324
325             sortKey = sortKey + (String JavaDoc) k.next();
326             needPipe = true;
327         }
328
329         return sortKey;
330     }
331
332     /**
333      * This method sets the search conditions on the current DBObject.
334      * The implementation at this level uses the searchParam if it has
335      * been set, you can override this method to use other criteria,
336      * like a custom where clause.
337      *
338      * @throws DBException upon error communicating with the DBObject
339      * @throws ControllerException upon other errors
340      */

341     protected void setupListSearchCriteria()
342             throws DBException, ControllerException {
343         String JavaDoc searchLimits = getSearchParam();
344
345         if (!searchLimits.equals("")) {
346             DataObject myDBObj = getDataObject();
347             StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(searchLimits, "|");
348             String JavaDoc oneSearchFieldName = null;
349             String JavaDoc oneSearchFieldValue = null;
350
351             while (stk.hasMoreTokens()) {
352                 oneSearchFieldName = stk.nextToken();
353
354                 if (!stk.hasMoreTokens()) {
355                     throw new DBException("Parameter 'search' must " +
356                             "contain name/value pairs seperated with " +
357                             "the '|' symbol. It contained '" +
358                             searchLimits + "'");
359                 }
360
361                 oneSearchFieldValue = stk.nextToken();
362                 myDBObj.set(oneSearchFieldName, oneSearchFieldValue);
363             }
364         } /* if any search limits */
365
366     }
367
368     /**
369      * Generates an arrayList of transitions to allow direct jumping to a page.
370      *
371      * @param request The controllerRequest object so we can set the appropriate
372      * parameters from the previous page.
373      * @param rp a queried and instantiated RecordPaginator object
374      * @param pageLimit the maximum number of records per screen.
375      * @return Block of <code>Transition</code> objects.
376      * @throws IllegalArgumentException if isCountRecords() == false or
377      * if no search has been run yet.
378      * @throws ControllerException upon all other errors
379      */

380     protected Block generatePageTransitions(ControllerRequest request, RecordPaginator rp, int pageLimit)
381             throws ControllerException {
382         if (rp.isCountRecords() == false) {
383             throw new java.lang.IllegalArgumentException JavaDoc("You must have countRecords set " +
384                     "to true for pagination to work");
385         }
386         Block returnBlock = new Block();
387         returnBlock.setName("PageJumpBlock");
388
389
390         int curPage = rp.getPageNumber();
391         int endPage = rp.getPageCount();
392
393         int startPage;
394         int index = 1;
395         if (curPage >= 10) {
396             startPage = curPage - (curPage % 10);
397         } else {
398             startPage = curPage - (curPage % 10) + 1;
399         }
400         if (endPage >= (startPage + 10)) {
401             endPage = curPage + (10 - (curPage % 10));
402         }
403
404         Class JavaDoc controllerClass = this.getController().getClass();
405         java.util.Hashtable JavaDoc allParameters = request.getParameters();
406         allParameters.remove(Controller.CONTROLLER_PARAM_KEY);
407         String JavaDoc state = (String JavaDoc) allParameters.get(Controller.STATE_PARAM_KEY);
408         allParameters.remove(Controller.STATE_PARAM_KEY);
409
410         if (curPage != 1) {
411             Transition t = new Transition();
412             t.setParams(allParameters);
413             t.setState(state);
414             t.setControllerObject(controllerClass);
415             t.addParam("page", Integer.toString(curPage - 1));
416             t.setLabel("< Previous");
417             t.setName(Integer.toString(index));
418             index++;
419             returnBlock.add(t);
420         }
421
422
423         for (int i = startPage; i <= endPage; i++) {
424             Transition t = new Transition();
425             t.setParams(allParameters);
426             t.setControllerObject(controllerClass);
427             t.addParam("page", Integer.toString(i));
428             t.setLabel(Integer.toString(i));
429             t.setState(state);
430             if (curPage == i) {
431                 t.setAttribute("currentPage", "true");
432                 Output o = new Output();
433                 o.setName("CurrentPage");
434                 o.setContent(Integer.toString(curPage));
435                 returnBlock.add(o);
436             }
437             t.setName(Integer.toString(index));
438             index++;
439
440             returnBlock.add(t);
441         }
442
443         if (curPage < endPage) {
444             Transition t = new Transition();
445             t.setParams(allParameters);
446             t.setControllerObject(controllerClass);
447             t.addParam("page", Integer.toString(curPage + 1));
448             t.setState(state);
449             t.setLabel("Next >");
450             t.setName(Integer.toString(index));
451             index++;
452             returnBlock.add(t);
453         }
454
455         addOutput(new Output("pageCount",
456                 Integer.toString(this.getRecordPaginator().getPageCount()) + " Pages"));
457         return returnBlock;
458     }
459
460
461     /**
462      * Given an interator containing database objects add all of those
463      * objects to the given output block as rows. All non-secret
464      * fields of each object should be added to the row.
465      *
466      * @param i_AllRecords an arrayList of DBObjects to add to the specified block
467      * @param myTable the <code>Block</code> obejct to add the records to.
468      * @throws DBException upon error communicating with the DBObjects
469      * @throws ControllerException upon other error.
470      */

471     protected void addRecordsToBlock(ArrayList JavaDoc i_AllRecords, Block myTable)
472             throws DBException, ControllerException {
473         DataObject myDBObj = this.getDataObject();
474
475         int recordCount = 0;
476         String JavaDoc oneFieldName = null;
477         String JavaDoc oneFieldValue = null;
478         DataObject oneRecord = null;
479         String JavaDoc controller = getControllerName();
480         Iterator JavaDoc i = i_AllRecords.iterator();
481
482         //added by Pete to allow showing of only specified fields
483
ArrayList JavaDoc browseArrayList = (ArrayList JavaDoc) myDBObj.getAttribute("browseArrayList");
484         boolean hasBrowseArrayList = false;
485
486         if (browseArrayList != null) {
487             hasBrowseArrayList = true;
488         }
489         while (i.hasNext()) {
490             oneRecord = (DataObject) i.next();
491             recordCount++;
492
493             Block oneRow = new Block("" + recordCount);
494             oneRow.setAttribute("row", "Y");
495             myTable.add(oneRow);
496
497             /* for each field in this kind of obect */
498             for (Iterator JavaDoc e2 = (hasBrowseArrayList)
499                     ? browseArrayList.iterator()
500                     : myDBObj.getMetaData().getFieldListArray().iterator();
501                  e2.hasNext();) {
502                 oneFieldName = (String JavaDoc) e2.next();
503                 DataFieldMetaData metaData = myDBObj.getFieldMetaData(oneFieldName);
504
505                 if (!metaData.isSecret()) {
506                     oneFieldValue = oneRecord.getField(oneFieldName);
507
508                     if (oneFieldValue == null) {
509                         oneFieldValue = "";
510                     }
511
512                     Output oneCell = new Output();
513                     oneCell.setName(oneFieldName);
514                     oneRow.addNested(oneCell);
515
516                     if (metaData.isKey()) {
517                         showEditLink(oneFieldName, oneFieldValue, oneRecord,
518                                 oneCell, controller);
519                     } else {
520                         if (oneFieldValue.equalsIgnoreCase("")) {
521                             oneCell.setContent(oneFieldValue);
522                         } else if (myDBObj.getFieldMetaData(oneFieldName).getTypeString().equalsIgnoreCase("money")) {
523                             try {
524                                 oneCell.setContent(new Format("%-10.2f").form(new Double JavaDoc(oneFieldValue).doubleValue()));
525                             } catch (NumberFormatException JavaDoc ne) {
526                                 throw new DBException("Number for " +
527                                         "field '" +
528                                         oneFieldName +
529                                         "' not in a valid numeric format:" +
530                                         oneFieldValue + ":" +
531                                         ne.getMessage());
532                             }
533                         } else { /* else not blank */
534                             if (metaData.isMultiValued()) {
535                                 java.util.List JavaDoc values = myDBObj.getValidValuesList(oneFieldName);
536
537                                 if (values == null) {
538                                     throw new DBException("Valid values for field '" +
539                                             oneFieldName + "' from object " +
540                                             ((Object JavaDoc) myDBObj).getClass().getName() +
541                                             " were null");
542                                 }
543
544                                 String JavaDoc fieldValue = null;
545                                 ValidValue oneVV = null;
546
547                                 for (Iterator JavaDoc ve = values.iterator();
548                                      ve.hasNext();) {
549                                     oneVV = (ValidValue) ve.next();
550
551                                     if (oneVV.getValue().equals(oneFieldValue)) {
552                                         fieldValue = oneVV.getDescription();
553                                     }
554                                 }
555                                 if (fieldValue == null) {
556                                     oneCell.setContent(oneFieldValue);
557                                 } else {
558                                     oneCell.setContent(fieldValue);
559                                 }
560                             } else { /* if field is multi_valued */
561                                 if (metaData.isDateType()) {
562                                     java.util.Date JavaDoc dt = oneRecord.getDataField(oneFieldName).asDate();
563                                     Locale JavaDoc l = this.getResponse().getLocale();
564                                     oneCell.setContent(displayDateValue(metaData, dt, l));
565                                 } else if (metaData.isCharacterLongObjectType()) {
566                                     oneCell.setContent(oneFieldValue + "");
567                                 } else {
568                                     oneCell.setContent(oneFieldValue);
569                                 }
570                             }
571                         }
572                     } /* else key field */
573
574                 } else { /* if not a secret field */
575
576                     //xun li add below code for ref link
577
if (isKeyField(oneFieldName)) {
578                         oneFieldName = (String JavaDoc) e2.next();
579                         oneFieldValue = oneRecord.getField(oneFieldName);
580
581                         if (oneFieldValue == null) {
582                             oneFieldValue = "";
583                         }
584
585                         Output oneCell = new Output();
586                         oneCell.setName(oneFieldName);
587                         oneRow.addNested(oneCell);
588                         showEditLink(oneFieldName, oneFieldValue, oneRecord,
589                                 oneCell, controller);
590                     }
591                 }
592             } /* each field */
593
594         } /* for each record */
595
596     }
597
598     /**
599      * Base class
600      * Show a list of database records to the user, allowing the key
601      * to be clicked on to request an edit of the object
602      *
603      * @throws DBException If a problem occurs retrieving the list
604      */

605     protected void showList()
606             throws DBException, ControllerException {
607         autoList();
608         showOptions();
609     } /* showList() */
610
611
612 } /* ListBase */
613
614
Popular Tags