KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > dbobj > DBObjectDef


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.dbobj;
66
67 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
68 import com.jcorporate.expresso.core.ExpressoSchema;
69 import com.jcorporate.expresso.core.controller.Transition;
70 import com.jcorporate.expresso.core.dataobjects.DataException;
71 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData;
72 import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCObjectMetaData;
73 import com.jcorporate.expresso.core.db.DBException;
74 import com.jcorporate.expresso.core.db.config.JDBCConfig;
75 import com.jcorporate.expresso.core.i18n.Messages;
76 import com.jcorporate.expresso.core.misc.ConfigManager;
77 import com.jcorporate.expresso.core.misc.ConfigurationException;
78 import com.jcorporate.expresso.core.misc.StringUtil;
79 import com.jcorporate.expresso.core.security.filters.FilterManager;
80 import org.apache.log4j.Logger;
81 import org.apache.oro.text.regex.MalformedPatternException;
82 import org.apache.oro.text.regex.Pattern;
83 import org.apache.oro.text.regex.PatternCompiler;
84 import org.apache.oro.text.regex.Perl5Compiler;
85
86 import java.util.ArrayList JavaDoc;
87 import java.util.Enumeration JavaDoc;
88 import java.util.HashMap JavaDoc;
89 import java.util.Hashtable JavaDoc;
90 import java.util.Iterator JavaDoc;
91 import java.util.Locale JavaDoc;
92 import java.util.Map JavaDoc;
93 import java.util.Set JavaDoc;
94 import java.util.StringTokenizer JavaDoc;
95 import java.util.Vector JavaDoc;
96
97
98 /**
99  * This object contains the "definition" of the DBObject, while the DBObject
100  * itself contains only the data itself.
101  * One DBObjectDef object is stored in a static HashMap in the DBObject class,
102  * and is looked up and referenced for all definitions of the structure of the given object.
103  * <p/>
104  * since this class is not threadsafe for adding information, it is imperitive
105  * that all information addition, typically done when the first instance
106  * of a DBObject is instantiated, is done in a synchronized context.
107  *
108  * @author Michael Nash
109  */

110 public class DBObjectDef
111         implements JDBCObjectMetaData {
112
113     private static final String JavaDoc OBJECT_NAME_NOT_ASSIGNED = "NOT ASSIGNED";
114
115     /* the log */
116     transient private static Logger log = Logger.getLogger(DBObjectDef.class);
117
118     /**
119      * Perl5 Regular Expression Compiler. The patterns generated by this compiler
120      * are mainly stored in the field mask table.
121      */

122     transient private static PatternCompiler patternCompiler =
123             new Perl5Compiler();
124
125     /**
126      * An instance of the singleton FilterManager class.
127      */

128     transient private static FilterManager filterManager = FilterManager.getInstance();
129
130 ////////////////////////////////////////////////////////////////////
131
// instance members
132
/////////////////////////////////////////////////////////////////////
133

134     /**
135      * A hashtable of all of the DBField objects in this DBObject
136      */

137     private Map allFields = new ConcurrentReaderHashMap();
138
139
140     /**
141      * Vector containing the field names in the order they were added
142      */

143     private ArrayList JavaDoc fieldNamesInOrder = new ArrayList JavaDoc();
144     private Map allKeys = new ConcurrentReaderHashMap();
145     private ArrayList JavaDoc keyList = new ArrayList JavaDoc();
146     private String JavaDoc objectDescription = "";
147
148     /**
149      * Vector containing the field names in the order they were added for
150      * INPUT and OUTPUT parameters for store procedure
151      * author Yves Henri AMAIZO
152      */

153     private Map allInParameters = new ConcurrentReaderHashMap();
154     private ArrayList JavaDoc inParamList = new ArrayList JavaDoc();
155     private Map allOutParameters = new ConcurrentReaderHashMap();
156     private ArrayList JavaDoc outParamList = new ArrayList JavaDoc();
157
158
159     /**
160      * The detailObjsLocal local and detailObjsForeign hashtables holds one or more references to other
161      * dbobject classes (the class name is the key), with the value
162      * stored being the names of the field(s) in this class (pipe-delimited)
163      * that relate to the primary key in the other object
164      */

165     private Hashtable JavaDoc detailObjsLocal = new Hashtable JavaDoc();
166     private Hashtable JavaDoc detailObjsForeign = new Hashtable JavaDoc();
167
168     /**
169      * A vector of "transition" objects that can be displayed as tabs
170      * available when DBMaint displays a DBObject of this type
171      */

172     private ArrayList JavaDoc transitionTabs = new ArrayList JavaDoc();
173
174     /**
175      * The list of all indicies used by this DBObject.<br>
176      * <i>Please Note:</i> If there is no index associated with a dbobject
177      * then indexList WILL be null.
178      */

179     private ArrayList JavaDoc indexList = null;
180
181     /**
182      * Table name of the "primary" table that this DB object refers to
183      */

184     private String JavaDoc tableName = "";
185
186     /**
187      * Store Procedure name of the "primary" table that this DB object refers to
188      */

189     private String JavaDoc storeProcedureName = ("");
190
191     private boolean returningValue = false;
192
193
194     /**
195      * Database schema name of the "primary" table that this DB object refers to
196      */

197     private String JavaDoc dbSchemaName = ("");
198
199     /**
200      * Database catalogue name of the "primary" table that this DB object refers to
201      */

202     private String JavaDoc dbCatalogName = ("");
203
204
205     /**
206      * A default characterset to filter on.
207      */

208     private String JavaDoc charSet = "ISO-8859-1";
209     private String JavaDoc mObjectName = OBJECT_NAME_NOT_ASSIGNED;
210
211     /**
212      * Do we log changes to this object
213      */

214     private boolean loggingEnabled = false;
215
216     /**
217      * What schema does this DB object belong to?
218      */

219     private String JavaDoc mySchema = ExpressoSchema.class.getName();
220
221     /**
222      * When we do an update, do we check if any records
223      * were updated & throw if there were none?
224      */

225     private boolean checkZeroUpdate = true;
226
227     transient private int cacheSize = -2;
228
229     /**
230      * Default Constructor. This allows a DB object to be dynamically
231      * instantiated (e.g. loaded
232      * with Class.forName()) and does all of the required initializations.
233      */

234     public DBObjectDef() {
235     } /* DBObjectDef() */
236
237     /**
238      * Add a field with more details: This version allows the user to specify a
239      * precision, for fields that use both a size and precision.
240      *
241      * @param fieldName Name of the field
242      * @param fieldType Type of the field - this is the internal Expresso type,
243      * mapping in DBField to a specific database data type.
244      * @param fieldSize Size of the field
245      * @param fieldPrecision The precision of the field
246      * @param allowNull Does this field allow nulls?
247      * @param fieldDescription A longer description of this field
248      * (user-understandable hopefully!)
249      */

250     synchronized public void addField(String JavaDoc fieldName, String JavaDoc fieldType,
251                                       int fieldSize, int fieldPrecision,
252                                       boolean allowNull, String JavaDoc fieldDescription)
253             throws DBException {
254         if (ConfigManager.isReservedWord(fieldName)) {
255             throw new DBException("You cannot have a field name of " +
256                     fieldName +
257                     ". It is a reserved word. Check " +
258                     "com.jcorporate.expresso.core.misc.ReservedWords for a full list" +
259                     " of reservered words");
260         }
261
262         if (!DBField.allDataTypes.contains(fieldType)) {
263             throw new DBException("You cannot have a field type of : " + fieldType +
264                     ". It is not a recognized Expresso datatype." +
265                     " See: com.jcorporate.expresso.core.dbobj.DBField for a list of all recognized datatypes");
266         }
267
268         allFields.put(fieldName,
269                 new DBField(fieldName, fieldType, fieldSize,
270                         fieldPrecision, allowNull, fieldDescription));
271
272         /**
273          * If we're dealing with integer datatypes, lets be helpful and make sure
274          * that the field is a valid integer format. Add the mask automatically
275          */

276         if (fieldType.equalsIgnoreCase(DBField.INTEGER_TYPE) ||
277                 fieldType.equalsIgnoreCase(DBField.INT_TYPE)) {
278
279             setMask(fieldName, DBObject.INT_MASK);
280             setAttribute(fieldName, DBObject.ATTRIBUTE_ERROR_MESSAGE,
281                     "You must enter a valid integer for field: "
282                     + fieldDescription);
283         }
284
285
286         fieldNamesInOrder.add(fieldName);
287     } /* addField(String, String, int, int, boolean, String) */
288
289
290     /**
291      * Sets the default value for a particular field
292      *
293      * @param fieldName The name of the field to set
294      * @param fieldValue the default value to use
295      * @throws DBException upon error
296      */

297     synchronized public void setDefaultValue(String JavaDoc fieldName, String JavaDoc fieldValue)
298             throws DBException {
299         if (!isField(fieldName)) {
300             throw new DBException("No such field as '" + fieldName +
301                     "' in db object '" + getName() + "'");
302         }
303
304         getFieldMetadata(fieldName).setDefaultValue(fieldValue);
305     }
306
307     /**
308      * @return default value if found, or null
309      */

310     public String JavaDoc getDefaultValue(String JavaDoc fieldName) {
311         return getFieldMetadata(fieldName).getDefaultValue();
312     }
313
314     /**
315      * Specify a new "detail" db object, and the fields in this object
316      * they specify the fields in the related object
317      *
318      * @param objName The class name of the related object. There is assumed to be
319      * a one to one or one to many relationship from this object to the specified object
320      * @param keyFieldsLocal A pipe-delimited list of field names in this object
321      * @param keyFieldsForeign A pipe-delimieted list of field names in the other object
322      */

323     synchronized public void addDetail(String JavaDoc objName, String JavaDoc keyFieldsLocal,
324                                        String JavaDoc keyFieldsForeign)
325             throws DBException {
326         detailObjsLocal.put(objName, keyFieldsLocal);
327         detailObjsForeign.put(objName, keyFieldsForeign);
328     }
329
330     public Enumeration JavaDoc getDetails() {
331         return detailObjsLocal.keys();
332     }
333
334     public String JavaDoc getDetailFieldsLocal(String JavaDoc detailName) {
335         return (String JavaDoc) detailObjsLocal.get(detailName);
336     }
337
338     public String JavaDoc getDetailFieldsForeign(String JavaDoc detailName) {
339         return (String JavaDoc) detailObjsForeign.get(detailName);
340     }
341
342     /**
343      * Add a field with more details: This version of addfield supplies
344      * the allowNull flags and a description of the field to be used
345      * when reporting errors to the user. This method is only used by the class that
346      * extends DB object, and typically only in the setupFields() method.
347      *
348      * @param fieldName Name of the field
349      * @param fieldType Type of the field - this is the "internal" Expresso type,
350      * and is mapped to a specific type for the database depending on the
351      * mappings in the properties file (if any). The DBField object contains
352      * the default mappings.
353      * @param fieldSize Size of this field, if specified for this type of field. For
354      * fields that do not use a size (such as "date"), specify 0 for the size.
355      * @param allowNull Does this field allow nulls?
356      * @param fieldDescription A longer description of this field
357      * (user-understandable hopefully!)
358      */

359     synchronized public void addField(String JavaDoc fieldName, String JavaDoc fieldType,
360                                       int fieldSize, boolean allowNull,
361                                       String JavaDoc fieldDescription)
362             throws DBException {
363
364 // try {
365
// fieldDescription = Messages.getString(this.getDefaulfieldDescription);
366
// } catch (IllegalArgumentException e) {
367
// //Do nothing here.
368
// }
369

370         addField(fieldName, fieldType, fieldSize, allowNull, null,
371                 fieldDescription);
372     }
373
374     /**
375      * Add a field with more details: This version of addfield supplies
376      * the allowNull flags and a description of the field to be used
377      * when reporting errors to the user. This method is only used by the class that
378      * extends DB object, and typically only in the setupFields() method.
379      *
380      * @param fieldName Name of the field
381      * @param fieldType Type of the field - this is the "internal" Expresso type,
382      * and is mapped to a specific type for the database depending on the
383      * mappings in the properties file (if any). The DBField object contains
384      * the default mappings.
385      * @param fieldSize Size of this field, if specified for this type of field. For
386      * fields that do not use a size (such as "date"), specify 0 for the size.
387      * @param allowNull Does this field allow nulls?
388      * @param descriptionKey Key into the local language files for this
389      * field's description
390      * @param fieldDescription A longer description of this field
391      * (user-understandable hopefully!)
392      */

393     synchronized public void addField(String JavaDoc fieldName, String JavaDoc fieldType,
394                                       int fieldSize, boolean allowNull,
395                                       String JavaDoc descriptionKey, String JavaDoc fieldDescription)
396             throws DBException {
397         if (ConfigManager.isReservedWord(fieldName)) {
398             throw new DBException("You cannot have a field name of " +
399                     fieldName +
400                     ". It is a reserved word. Check " +
401                     "com.jcorporate.expresso.core.misc.ConfigManager for a full list" +
402                     " of reservered words");
403         }
404
405         allFields.put(fieldName,
406                 new DBField(fieldName, fieldType, fieldSize, 0,
407                         allowNull, fieldDescription));
408         fieldNamesInOrder.add(fieldName);
409
410
411
412         /**
413          * If we're dealing with integer datatypes, lets be helpful and make sure
414          * that the field is a valid integer format. Add the mask automatically
415          */

416         if (fieldType.equalsIgnoreCase(DBField.INTEGER_TYPE) ||
417                 fieldType.equalsIgnoreCase(DBField.INT_TYPE)) {
418
419             setMask(fieldName, DBObject.INT_MASK);
420             setAttribute(fieldName, DBObject.ATTRIBUTE_ERROR_MESSAGE,
421                     "You must enter a valid integer for field: "
422                     + fieldDescription);
423         }
424
425     } /* addField(String, String, int, boolean, String) */
426
427
428     /**
429      * Returns whether the field allows null values or not.
430      *
431      * @param fieldName name of the field
432      * @return true if the field allows null
433      */

434     public boolean allowsNull(String JavaDoc fieldName)
435             throws DBException {
436         DBField oneField = (DBField) allFields.get(fieldName);
437
438         if (oneField == null) {
439             throw new DBException("(" + mObjectName + ") Field " + fieldName +
440                     " is not defined as a field in this DBObject");
441         }
442         if (oneField.allowsNull()) {
443             return true;
444         }
445
446         return false;
447     } /* allowsNull(String) */
448
449
450     /**
451      * Sets the field's regular expression validation mask. It also precompiles
452      * the regular expression when it is called.
453      *
454      * @param fieldName The field name to associate with this regular expression
455      * @param newMask The actual regular expression.
456      */

457     synchronized public void setMask(String JavaDoc fieldName, String JavaDoc newMask)
458             throws DBException {
459         DBField oneField = (DBField) allFields.get(fieldName);
460
461         if (oneField == null) {
462             throw new DBException("(" + mObjectName + ") Field " + fieldName +
463                     " is not defined as a field in this DBObject");
464         }
465
466         StringUtil.assertNotBlank(newMask,
467                 "DBObject.setMask: newMask parameter was null for field: " +
468                 fieldName);
469
470         try {
471             Pattern p = patternCompiler.compile(newMask, Perl5Compiler.READ_ONLY_MASK);
472             oneField.setMask(p);
473         } catch (MalformedPatternException mpe) {
474             throw new DBException("Error compiling mask for field: " +
475                     fieldName, mpe);
476         }
477     } /* allowsNull(String) */
478
479
480     /**
481      * Removes an attribute from the field.
482      *
483      * @param fieldName the name of the field to remove the attribute
484      * @param attribName the attribute name to remove
485      */

486     public void removeAttribute(String JavaDoc fieldName, String JavaDoc attribName) {
487         DBField oneField = (DBField) allFields.get(fieldName);
488
489         if (oneField == null) {
490             return;
491         }
492
493         oneField.removeAttribute(attribName);
494     }
495
496     /**
497      * @param fieldName the name of the field to set the attribute for
498      * @param attribName the name of the attribute to set
499      * @param attribValue the attribute to set
500      */

501     synchronized public void setAttribute(String JavaDoc fieldName, String JavaDoc attribName, Object JavaDoc attribValue)
502             throws DBException {
503         DBField oneField = (DBField) allFields.get(fieldName);
504
505         if (oneField == null) {
506             throw new DBException("(" + getName() + ") Field " + fieldName +
507                     " is not defined as a field in this DBObject");
508         }
509
510         oneField.setAttribute(attribName, attribValue);
511     } /* allowsNull(String) */
512
513
514     /**
515      * Gets an <code>Object</code> attribute from the field's metatdata
516      *
517      * @param fieldName the name of the field for the attribute
518      * @param attribName the name of the attribute
519      * @return java.lang.Object
520      */

521     public Object JavaDoc getAttribute(String JavaDoc fieldName, String JavaDoc attribName)
522             throws DBException {
523         DBField oneField = (DBField) allFields.get(fieldName);
524
525         if (oneField == null) {
526             throw new DBException("(" + getName() + ") Field " + fieldName +
527                     " is not defined as a field in this DBObject");
528         }
529
530         return oneField.getAttribute(attribName);
531     } /* allowsNull(String) */
532
533
534     public Iterator JavaDoc getAttributesIterator(String JavaDoc fieldName)
535             throws DBException {
536         DBField oneField = (DBField) allFields.get(fieldName);
537
538         if (oneField == null) {
539             throw new DBException("(" + getName() + ") Field " + fieldName +
540                     " is not defined as a field in this DBObject");
541         }
542
543         return oneField.getAttributesIterator();
544     }
545
546     /**
547      * Add an index to the table.
548      *
549      * @param indexName the name to give the index in the table
550      * @param fieldNames A comma delimited list of all fields in the index.
551      * @param isUnique - True if this field is a unique index.
552      * @throws IllegalArgumentException of fieldName is null or doesn't exist
553      * or if indexName is null
554      */

555     synchronized public void addIndex(String JavaDoc indexName, String JavaDoc fieldNames, boolean isUnique)
556             throws IllegalArgumentException JavaDoc {
557
558         //
559
// Begin Argument Validation
560
//
561
if (indexName == null) {
562             throw new IllegalArgumentException JavaDoc(Messages.getString(getSchema(),
563                     "DBOBJ_Add_Index_IllegalArgument1"));
564         }
565         if (fieldNames == null) {
566             throw new IllegalArgumentException JavaDoc(Messages.getString(getSchema(),
567                     "DBOBJ_Add_Index_IllegalArgument2"));
568         }
569
570         //
571
//Iterate through all the field names and make sure that they exist
572
//
573
String JavaDoc tempString = null;
574
575         //Check to make sure that these fields really do exist
576
//in the table they're being called for.
577
StringTokenizer JavaDoc stk = new StringTokenizer JavaDoc(fieldNames, ",");
578
579         while (stk.hasMoreTokens()) {
580             tempString = stk.nextToken();
581
582             //
583
//Will throw a DBException if the field doesn't exist.
584
//
585
this.getDBField(tempString);
586         }
587         //
588
// End Argument Validation
589
//
590
if (indexList == null) {
591             indexList = new ArrayList JavaDoc();
592         }
593         try {
594             indexList.add(new DBIndex(indexName, getTargetTable(), fieldNames,
595                     isUnique));
596         } catch (DBException e) {
597             throw new IllegalArgumentException JavaDoc(e.getMessage());
598         }
599     } /* addIndex(String, String, boolean) */
600
601
602     /**
603      * Add a new field to the list of fields that are part of this
604      * object's key. Called after all of the "addField" calls in the setupFields()
605      * method to specify which fields make up the primary key of this object.
606      *
607      * @param keyFieldName The name of the field to add as part of the key
608      * @throws DBException if the field name is not valid or the field
609      * allows nulls
610      */

611     synchronized public void addKey(String JavaDoc keyFieldName)
612             throws DBException {
613         DBField oneField = (DBField) allFields.get(keyFieldName);
614
615         if (oneField == null) {
616             throw new DBException("(" + getName() + ") Field " + keyFieldName +
617                     " is not defined as a field in this DBObject - cannot add " +
618                     "to key");
619         }
620         if (oneField.allowsNull()) {
621             throw new DBException("(" + getName() + ") Field " + keyFieldName +
622                     " allows null - not suitable for inclusion " +
623                     "in key");
624         }
625         if (oneField.isVirtual()) {
626             throw new DBException("(" + getName() + ") Field " + keyFieldName +
627                     " is a virtual field - not suitable for " +
628                     "inclusion in key");
629         }
630
631         if (oneField.isLongObjectType()) {
632             throw new DBException("(" + getName() + ") Field " + keyFieldName +
633                     " allows arbitrarily long length, either text or binary - not suitable for inclusion " +
634                     "in key");
635         }
636
637         oneField.setKey(true);
638         allKeys.put(keyFieldName, oneField);
639
640         /* We must keep keys in order, so we add to keyList as well */
641         keyList.add(keyFieldName);
642     } /* addKey(String) */
643
644
645     /**
646      * Add a new virtual field to the definition of this object.
647      * A virtual field is just like a regular one, except it's
648      * not stored in the target table
649      * A normal call to getField or setField on a virtual field will throw
650      * an exception - getField and setField should be extended to handle the virtual
651      * fields for a particular object correctly.
652      *
653      * @param fieldName Name of the field
654      * @param fieldType Database type of the field
655      * @param fieldSize Size of the field in characters
656      * @param fieldDescription A longer description of this field
657      * (user-understandable hopefully!)
658      */

659     synchronized public void addVirtualField(String JavaDoc fieldName, String JavaDoc fieldType,
660                                              int fieldSize, String JavaDoc fieldDescription)
661             throws DBException {
662         addVirtualField(fieldName, fieldType, fieldSize, null,
663                 fieldDescription);
664     }
665
666     /**
667      * Add a new virtual field to the definition of this object.
668      * A virtual field is just like a regular one, except it's
669      * not stored in the target table
670      * A normal call to getField or setField on a virtual field will throw
671      * an exception - getField and setField should be extended to handle the virtual
672      * fields for a particular object correctly.
673      *
674      * @param fieldName Name of the field
675      * @param fieldType Database type of the field
676      * @param fieldSize Size of the field in characters
677      * @param descriptionKey Key into the local language files
678      * for the description of this field.
679      * @param fieldDescription A longer description of this field
680      * (user-understandable hopefully!)
681      */

682     synchronized public void addVirtualField(String JavaDoc fieldName, String JavaDoc fieldType,
683                                              int fieldSize, String JavaDoc descriptionKey,
684                                              String JavaDoc fieldDescription)
685             throws DBException {
686         DBField newField = new DBField(fieldName, fieldType, fieldSize, 0,
687                 true, fieldDescription);
688         newField.setVirtual(true);
689         allFields.put(fieldName, newField);
690         fieldNamesInOrder.add(fieldName);
691     } /* addVirtualField(String, String, int, String) */
692
693
694     /**
695      * Add a field with more details: This version allows the user to specify a
696      * precision, for fields that use both a size and precision.
697      *
698      * @param fieldName Name of the field
699      * @param fieldType Type of the field - this is the internal Expresso type,
700      * mapping in DBField to a specific database data type.
701      * @param fieldSize Size of the field
702      * @param fieldPrecision The precision of the field
703      * @param allowNull Does this field allow nulls?
704      * @param fieldDescription A longer description of this field
705      * (user-understandable hopefully!)
706      */

707     synchronized public void addVirtualField(String JavaDoc fieldName, String JavaDoc fieldType,
708                                              int fieldSize, int fieldPrecision,
709                                              boolean allowNull,
710                                              String JavaDoc fieldDescription)
711             throws DBException {
712         addVirtualField(fieldName, fieldType, fieldSize, fieldPrecision,
713                 allowNull, null, fieldDescription);
714     } /* addVirtualField */
715
716
717     /**
718      * Add a field with more details: This version allows the user to specify a
719      * precision, for fields that use both a size and precision.
720      *
721      * @param fieldName Name of the field
722      * @param fieldType Type of the field - this is the internal Expresso type,
723      * mapping in DBField to a specific database data type.
724      * @param fieldSize Size of the field
725      * @param fieldPrecision The precision of the field
726      * @param allowNull Does this field allow nulls?
727      * @param descriptionKey Key into the local langauge files
728      * with a description of this field
729      * @param fieldDescription A longer description of this field
730      * (user-understandable hopefully!)
731      */

732     synchronized public void addVirtualField(String JavaDoc fieldName, String JavaDoc fieldType,
733                                              int fieldSize, int fieldPrecision,
734                                              boolean allowNull, String JavaDoc descriptionKey,
735                                              String JavaDoc fieldDescription)
736             throws DBException {
737         DBField newField = new DBField(fieldName, fieldType, fieldSize,
738                 fieldPrecision, allowNull,
739                 fieldDescription);
740         newField.setVirtual(true);
741         allFields.put(fieldName, newField);
742         fieldNamesInOrder.add(fieldName);
743     } /* addField(String, String, int, int, boolean, String) */
744
745
746     /**
747      * Disable change logging of this object
748      */

749     public synchronized void disableLogging() {
750         loggingEnabled = false;
751     } /* disableLogging() */
752
753     /**
754      * Enable logging of changes to this object. Change logging writes an entry to
755      * the ChangeLog object every time an add, update, or delete is made to this
756      * object. It is used to track important tables, such as user information,
757      * account information, etc.
758      */

759     public synchronized void enableLogging() {
760         loggingEnabled = true;
761     } /* enableLogging() */
762
763
764     public boolean isLoggingEnabled() {
765         return loggingEnabled;
766     }
767
768     /**
769      * Return the "allFields" Hashtable, which contains all of the DBField objects
770      * that make up this DB object.
771      *
772      * @return Hashtable
773      * @deprecated use getAllFieldsMap instead
774      */

775     synchronized public Hashtable JavaDoc getAllFields() {
776         return new Hashtable JavaDoc(allFields);
777     } /* getAllFields() */
778
779     /**
780      * Check if a certain name is a field (of any kind) in this DBOBject
781      * since SQL is case insensitive, ignore case of field name for match,
782      * this method takes longer, so use isField if the field name is known precisely
783      *
784      * @param fieldName the name of the field to check
785      * @return internal format for field name if matched, or null if no match
786      */

787     public String JavaDoc isFieldIgnoreCase(String JavaDoc fieldName) {
788         // try efficient test first
789
if (isField(fieldName)) {
790             return fieldName;
791         }
792
793         // now iterate to ignore case
794
String JavaDoc internalFieldName = null;
795         for (Iterator JavaDoc i = getFieldListIterator(); i.hasNext();) {
796             String JavaDoc oneFieldName = (String JavaDoc) i.next();
797
798             if (oneFieldName.equalsIgnoreCase(fieldName)) {
799                 internalFieldName = oneFieldName;
800                 break;
801             }
802         } /* for each field */
803
804         return internalFieldName;
805     }
806
807     /**
808      * Check if a certain name is a field (of any kind) in this DBOBject
809      *
810      * @param fieldName the name of the field to check
811      * @return true if the field name exists
812      */

813     public boolean isField(String JavaDoc fieldName) {
814         return allFields.get(fieldName) != null;
815     }
816
817     /**
818      * Return the "allFields" Hashtable, which contains all of the DBField objects
819      * that make up this DB object.
820      *
821      * @return java.util.HashMap
822      */

823     public HashMap getAllFieldsMap() {
824         return new HashMap(allFields);
825     }
826
827     public HashMap getAllDBFields() {
828         return new HashMap(allFields);
829     }
830
831     /**
832      * Way to get an interator into the allFields objects
833      *
834      * @return an Iterator into the allFields HashMap
835      */

836     public Iterator JavaDoc getAllFieldsIterator() {
837         return allFields.values().iterator();
838     }
839
840     /**
841      * Retrieve an interator of key fields
842      *
843      * @return Iterator of key fields. [MetaData]
844      */

845     public Iterator JavaDoc getKeyFieldListIterator() {
846         return keyList.iterator();
847     }
848
849     /**
850      * Return the "allKeys" hash, containing the DBField objects that make up
851      * the primary key for this db object.
852      *
853      * @return java.util.Hashtable
854      * @deprecated Use getAllKeysMap or getAllKeysIterator instead
855      */

856     public Hashtable JavaDoc getAllKeys() {
857         return new Hashtable JavaDoc(allKeys);
858     } /* getAllKeys() */
859
860     /**
861      * Return the "allKeys" hash, containing the DBField objects that make up
862      * the primary key for this db object.
863      *
864      * @return java.util.HashMap
865      */

866     public HashMap getAllKeysMap() {
867         return new HashMap(allKeys);
868     } /* getAllKeysMap() */
869
870     /**
871      * <b> Non-threadsafe </b> way to get an interator into the allKeys data
872      * structure
873      *
874      * @return java.util.Iterator of key fields (DBField)
875      */

876     public Iterator JavaDoc getAllKeysIterator() {
877         return allKeys.values().iterator();
878     } /* getAllKeysIterator() */
879
880     /**
881      * return the current object's character set
882      *
883      * @return java.lang.String
884      */

885     public String JavaDoc getCharset() {
886         return charSet;
887     } /* getCharset() */
888
889     /**
890      * Get the current Cache size of this object. or -2 if it hasn't been
891      * defined yet.
892      *
893      * @return current cache size value.
894      */

895     public int getCacheSize() {
896         return cacheSize;
897     }
898
899     /**
900      * Sets the cache size for this DBObject
901      *
902      * @param newValue the new value. Must be >= -2
903      * @throws IllegalArgumentException if newValue < -2
904      */

905     public void setCacheSize(int newValue) {
906         if (newValue < -2) {
907             throw new java.lang.IllegalArgumentException JavaDoc(this.getClass().getName() +
908                     ".setCacheSize(int). newValue must be greater than or equal to -2");
909         }
910
911         cacheSize = newValue;
912     }
913
914     /**
915      * Set a characterset for a particular field.
916      *
917      * @param newCharSet The name of the characterset that you will filter against.
918      * For Western-Latin character sets use &quot;ISO-8859-1&quot; as the parameter.
919      * Currently, no other charactersets are implemented. <br>
920      * @throws DBException upon error
921      * @see com.jcorporate.expresso.core.security.filters.FilterManager
922      * for more information on Filters and implementing Filters for your own
923      * characterset.
924      * <p/>
925      * Sets the characterset expected for a this DB object. A Table's default
926      * is &quot;ISO-8859-1&quot;
927      * @see com.jcorporate.expresso.core.security.filters.Filter
928      * @see com.jcorporate.expresso.core.security.filters.ISO_8859_1
929      */

930     synchronized public void setCharset(String JavaDoc newCharSet)
931             throws DBException {
932         charSet = newCharSet;
933     } /* setCharset(String) */
934
935
936     /**
937      * Return a description of this database object. If no explicit description has
938      * been set, return the class name.
939      *
940      * @return A string describing this database object
941      */

942     public String JavaDoc getDescription() {
943         if (StringUtil.notNull(objectDescription).equals("")) {
944             return getName();
945         } else {
946             return objectDescription;
947         }
948     } /* getDescription() */
949
950
951     /**
952      * Retrieve the table description in a localized way. If l == null, the
953      * function uses the system locale to generate the value. If unable to
954      * locate the key in the message bundle, the key becomes the return value.
955      *
956      * @param l the Locale to use for rendering the table description
957      * @return java.lang.String
958      */

959     public String JavaDoc getDescription(Locale JavaDoc l) {
960         String JavaDoc key = this.getDescription();
961
962         if (key == null || key.length() == 0) {
963             return "Unknown Table";
964         }
965
966         if (l == null) {
967             l = Locale.getDefault();
968         }
969
970         String JavaDoc schema = this.getSchema();
971         if (schema == null || schema.length() == 0) {
972             schema = com.jcorporate.expresso.core.ExpressoSchema.class.getName();
973         }
974
975         String JavaDoc returnValue;
976         try {
977             returnValue = Messages.getString(schema, l, key);
978         } catch (IllegalArgumentException JavaDoc ex) {
979             returnValue = key;
980         }
981
982         return returnValue;
983
984     }
985
986
987     /**
988      * Return the long description of a field, if available
989      *
990      * @param fieldName The name of the field
991      * @return String: The long description of the field (user-readable)
992      * @throws DBException If there is no such field
993      */

994     public String JavaDoc getDescription(String JavaDoc fieldName)
995             throws DBException {
996         DBField oneField = (DBField) allFields.get(fieldName);
997
998         if (oneField == null) {
999             throw new DBException("No such field '" + fieldName + "'" +
1000                    " in object '" + mObjectName + "'");
1001        }
1002
1003        return oneField.getDescription();
1004    } /* getDescription(String) */
1005
1006
1007    /**
1008     * Retrieve an i18n'ized description as per the locale defined for the
1009     * 'client'
1010     *
1011     * @param l the Locale to use. If null, will use the System default Locale
1012     * @param fieldName the name of the field to retrieve the i18n'ized description
1013     * for.
1014     * @return an i18n'ized string. K
1015     */

1016    public String JavaDoc getDescription(java.util.Locale JavaDoc l, String JavaDoc fieldName) {
1017        String JavaDoc key = null;
1018        try {
1019            key = this.getDescription(fieldName);
1020        } catch (DBException ex) {
1021            log.error("Error getting field: " + fieldName, ex);
1022        }
1023
1024        if (key == null) {
1025            return "Unknown Field";
1026        }
1027
1028        if (l == null) {
1029            l = Locale.getDefault();
1030        }
1031
1032        String JavaDoc schema = this.getSchema();
1033        if (schema == null || schema.length() == 0) {
1034            schema = com.jcorporate.expresso.core.ExpressoSchema.class.getName();
1035        }
1036
1037        String JavaDoc returnValue;
1038        try {
1039            returnValue = Messages.getString(schema, l, key);
1040        } catch (IllegalArgumentException JavaDoc ex) {
1041            returnValue = key;
1042        }
1043
1044        return returnValue;
1045    }
1046
1047    /**
1048     * Get the DBField object specified by the fieldname
1049     *
1050     * @param fieldName the name of the field to retrieve
1051     * @return <code>DBField</code> object
1052     */

1053    public DBField getDBField(String JavaDoc fieldName) {
1054        DBField oneField = (DBField) allFields.get(fieldName);
1055
1056        if (oneField == null) {
1057            throw new IllegalArgumentException JavaDoc("No such field as '" + fieldName +
1058                    "' in object '" + mObjectName + "'");
1059        }
1060
1061        return oneField;
1062    } /* getDBField(String) */
1063
1064
1065    /**
1066     * Get a list of all of the fields in this object
1067     *
1068     * @return A Vector of all of the fieldNames in this object
1069     * @deprecated Use getFieldListArray or getFieldListIterator instead
1070     */

1071    synchronized public Enumeration JavaDoc getFieldList() {
1072        return new Vector JavaDoc(fieldNamesInOrder).elements();
1073    } /* getFieldList() */
1074
1075
1076    /**
1077     * Get a list of all of the fields in this object This is threadsafe in that
1078     * it makes a new copy of the fieldNamesInOrder ArrayList
1079     *
1080     * @return A Vector of all of the fieldNames in this object
1081     */

1082    synchronized public ArrayList JavaDoc getFieldListArray() {
1083        return (ArrayList JavaDoc) fieldNamesInOrder.clone();
1084    }
1085
1086    /**
1087     * Get a list of all of the fields in this object This iterator is not thread
1088     * safe.
1089     *
1090     * @return An iterator of the fieldNamesInOrder array list
1091     */

1092    public Iterator JavaDoc getFieldListIterator() {
1093        return fieldNamesInOrder.iterator();
1094    }
1095
1096    /**
1097     * Get a list of all of the names of the key fields in this object
1098     *
1099     * @return A Vector of all of the names of the key fields
1100     * @deprecated Use getKeyFieldArray instead
1101     */

1102    public Enumeration JavaDoc getKeyFieldList() {
1103        Vector JavaDoc newKeys = new Vector JavaDoc(keyList);
1104
1105        return newKeys.elements();
1106    } /* getKeyFieldList() */
1107
1108    /**
1109     * Get a list of all of the names of the key fields in this object
1110     *
1111     * @return An ArrayList of all of the names of the key fields
1112     */

1113    public ArrayList JavaDoc getKeyFieldListArray() {
1114        return keyList;
1115    }
1116
1117    /**
1118     * Return the length of a field
1119     *
1120     * @param fieldName The name of the field
1121     * @return String: The length of the field
1122     * @throws DBException If there is no such field in this object
1123     */

1124    public String JavaDoc getLength(String JavaDoc fieldName) throws DBException {
1125        DBField oneField = getDBField(fieldName);
1126
1127        return oneField.getLength();
1128    } /* getLength(String) */
1129
1130
1131    public int getLengthInt(String JavaDoc fieldName) throws DBException {
1132        return new Integer JavaDoc(getLength(fieldName)).intValue();
1133    }
1134
1135    /**
1136     * @param fieldName The name of the field
1137     * @return integer for demcimal precision of the field
1138     */

1139    public int getPrecision(String JavaDoc fieldName)
1140            throws DBException {
1141        DBField oneField = getDBField(fieldName);
1142
1143        return oneField.getPrecision();
1144    } /* getPrecision(String) */
1145
1146
1147    /**
1148     * Get a field's lookup object - this is the name of another database
1149     * object that can be used to look up valid values for this object. The lookup
1150     * object for a field is set in the db objects setupFields method, and is used
1151     * by the DBMaint servlet to provide automatic lookup links for fields.
1152     *
1153     * @param fieldName Field name to check
1154     * @return String specifying the className of the lookup object
1155     * @throws DBException If the specified field does not exist.
1156     */

1157    public String JavaDoc getLookupObject(String JavaDoc fieldName)
1158            throws DBException {
1159        DBField oneField = getDBField(fieldName);
1160
1161        return oneField.getLookupObject();
1162    } /* getLookupObject(String) */
1163
1164
1165    /**
1166     * When you get a lookup object, to perform a complete mapping between the
1167     * two, you need to know what field name in the remote object maps to this
1168     * field.
1169     *
1170     * @param fieldName the name of the field to look up.
1171     * @return java.lang.String or null if there is no lookup field
1172     * @throws IllegalArgumentException if the field name does not exist
1173     */

1174    public String JavaDoc getLookupField(String JavaDoc fieldName) {
1175        DBField oneField = getDBField(fieldName);
1176        if (oneField == null) {
1177            throw new IllegalArgumentException JavaDoc("No field metadata found for field name: "
1178                    + fieldName);
1179        }
1180
1181        return oneField.getLookupField();
1182    }
1183
1184    /**
1185     * Get the name of this object
1186     *
1187     * @return String The database object name, or the table name if none
1188     * has been assigned
1189     */

1190    public String JavaDoc getName() {
1191        if (mObjectName.equals(OBJECT_NAME_NOT_ASSIGNED) ||
1192                "".equals(mObjectName) || mObjectName == null) {
1193            return tableName;
1194        } else {
1195            return mObjectName;
1196        }
1197    } /* getName() */
1198
1199    /**
1200     * Return the Table Name of the current database object. Keep in mind
1201     * that a database object could update or affect other tables as well.
1202     *
1203     * @return String: Table name of the target table of this database object
1204     * @throws DataException upon error
1205     */

1206    public String JavaDoc getTargetTable()
1207            throws DataException {
1208        if (tableName == null) {
1209            throw new DataException("No table name supplied");
1210        }
1211
1212        return tableName;
1213    } /* getTargetTable() */
1214
1215    /**
1216     * Return the Schema Name of the current database object.
1217     *
1218     * @return String: Schema name of the target table of this database object
1219     * <p/>
1220     * author Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1221     */

1222    public String JavaDoc getTargetDbSchema() {
1223        return dbSchemaName;
1224    } /* getTargetDbSchema() */
1225
1226    /**
1227     * Return the Schema Name of the current database object.
1228     *
1229     * @return String: Schema name of the target table of this database object
1230     * <p/>
1231     * author Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1232     */

1233    public String JavaDoc getTargetDbCatalog() {
1234        return dbCatalogName;
1235    }
1236
1237    /**
1238     * Return the type of a field - this method returns the internal Expresso type
1239     *
1240     * @param fieldName The name of the field
1241     * @return String: The type of the field
1242     * @throws DBException If there is no such field in this object
1243     */

1244    public String JavaDoc getType(String JavaDoc fieldName)
1245            throws DBException {
1246        DBField oneField = getDBField(fieldName);
1247
1248        return oneField.getTypeString();
1249    } /* getType(String) */
1250
1251
1252    /**
1253     * Get an array of DBIndex objects for purpose of
1254     * creating them through the schema. Return type
1255     * should actually be DBIndex. <i>Please Note</i> This may cause an
1256     * exception to be thrown if indexList is null. Call hasIndex() first
1257     * before calling getIndexArray
1258     *
1259     * @return Object[]
1260     */

1261    synchronized public Object JavaDoc[] getIndexArray() {
1262        return this.indexList.toArray();
1263    }
1264
1265    /**
1266     * Returns true if an Index exists for this array.
1267     *
1268     * @return true if it has an index
1269     */

1270    public boolean hasIndex() {
1271        if (this.indexList == null) {
1272            return false;
1273        } else {
1274            return true;
1275        }
1276    }
1277
1278    /**
1279     * This method will return a boolean true if the field is defined in the DBOBject,
1280     * false otherwise.
1281     * Creation date: (8/8/00 11:04:32 AM)
1282     *
1283     * @param fieldName java.lang.String
1284     * @return boolean
1285     */

1286    public boolean hasField(String JavaDoc fieldName) {
1287        if (allFields.containsKey(fieldName)) {
1288            return true;
1289        }
1290
1291        return false;
1292    } /* hasField(String) */
1293
1294
1295    public FilterManager getFilterManager() {
1296        return filterManager;
1297    }
1298
1299    /**
1300     * Method called to determine if a particular field is multi-valued,
1301     * that is does it have a set of specific values and descriptions
1302     *
1303     * @param fieldName Name of the field
1304     * @return boolean True if the field is multi-valued, false if not
1305     * @throws DBException If there is no such field
1306     */

1307    synchronized public boolean isMultiValued(String JavaDoc fieldName)
1308            throws DBException {
1309        DBField oneField = getDBField(fieldName);
1310
1311        return oneField.isMultiValued();
1312    } /* isMultiValued(String) */
1313
1314
1315    /**
1316     * Is a given field readOnly - these fields are not offered for entry
1317     * when a form is produced by the generic database maintenance servlet
1318     *
1319     * @param fieldName name of the field to check
1320     * @return true of the field is "read only", false if it is not
1321     * @throws DBException Ff there is no such field
1322     */

1323    public boolean isReadOnly(String JavaDoc fieldName)
1324            throws DBException {
1325        DBField oneField = getDBField(fieldName);
1326
1327        if (oneField == null) {
1328            throw new DBException("No such field '" + fieldName + "'" +
1329                    "' in object '" + mObjectName + "'");
1330        }
1331
1332        return oneField.isReadOnly();
1333    } /* isReadOnly(String) */
1334
1335
1336    /**
1337     * Is a given field 'secret' - these fields are not shown
1338     * when a list is produced by the generic database maintenance servlet (DBMaint).
1339     * This means that only users with update permission to the record can see the
1340     * value of the specified field.
1341     *
1342     * @param fieldName The name of the field to check
1343     * @return True if the field is 'secret', false if it is not
1344     * @throws DBException If there is no such field.
1345     * @see #setSecret(String)
1346     */

1347    public boolean isSecret(String JavaDoc fieldName)
1348            throws DBException {
1349        DBField oneField = getDBField(fieldName);
1350
1351        return oneField.isSecret();
1352    } /* isSecret(String) */
1353
1354
1355    /**
1356     * Is a given field virtual? A virtual field is not stored in the target table
1357     * for this object - it may be computed, or stored in another table.
1358     *
1359     * @param fieldName The name of the field to check
1360     * @return True of the field is virtual, false if it is not
1361     * @throws DBException If there is no such field
1362     * @see #addVirtualField(String, String, int, String)
1363     */

1364    public boolean isVirtual(String JavaDoc fieldName)
1365            throws DBException {
1366        DBField oneField = getDBField(fieldName);
1367
1368        return oneField.isVirtual();
1369    } /* isVirtual(String) */
1370
1371
1372    /**
1373     * Turn on or off the facility to verify that when an update is made that at
1374     * least one record got updated. If this flag is on, and no records get updated,
1375     * the update() method throws an Exception. Note that for some databases, if the
1376     * existing record is not changed (e.g. it was already identical to what
1377     * was being updated) this counts "no update" (notably, mySQL does this).
1378     *
1379     * @param newFlag True to turn on checking, false to turn it off
1380     */

1381    synchronized public void setCheckZeroUpdate(boolean newFlag) {
1382        checkZeroUpdate = newFlag;
1383    } /* setCheckZeroUpdate(boolean) */
1384
1385
1386    public boolean checkZeroUpdate() {
1387        return checkZeroUpdate;
1388    }
1389
1390    /**
1391     * Set the description of this object
1392     *
1393     * @param newDescription A description of this database object
1394     */

1395    synchronized public void setDescription(String JavaDoc newDescription) {
1396        objectDescription = newDescription;
1397    } /* setDescription(String) */
1398
1399    /**
1400     * Set a field's lookup object - this is the name of another database
1401     * object that can be used to look up valid values for this object. This value
1402     * is used by the DBMaint servlet to provide automatic lookup ability for
1403     * related fields.
1404     *
1405     * @param fieldName The field name that this lookup is associated with
1406     * @param objectName The db object used to look up valid values for this field.
1407     */

1408    synchronized public void setLookupObject(String JavaDoc fieldName, String JavaDoc objectName)
1409            throws DBException {
1410        DBField oneField = getDBField(fieldName);
1411        oneField.setLookupObject(objectName);
1412    } /* setLookupObject(String, String) */
1413
1414
1415    /**
1416     * Set this field to be multi-valued - e.g. there is a specific list of
1417     * values that are valid for this field. There should be code in the
1418     * getValidValues method that returns the valid values for the specified
1419     * multi-valued field.
1420     *
1421     * @param fieldName The name of the field to specify as multi-valued
1422     * @throws DBException If the field name given is not valid, or is a virtual field
1423     */

1424    synchronized public void setMultiValued(String JavaDoc fieldName)
1425            throws DBException {
1426        DBField oneField = getDBField(fieldName);
1427
1428        if (oneField.isVirtual()) {
1429            throw new DBException("(" + mObjectName + ") Field '" + fieldName +
1430                    "' is a virtual field - not suitable for " +
1431                    "setting as multi-valued");
1432        }
1433
1434        oneField.setMultiValued(true);
1435    } /* setMultiValued(String) */
1436
1437
1438    /**
1439     * Set the name of this object - this name is used to identify the db object
1440     * with a more human-readable description
1441     *
1442     * @param theName New name for this object
1443     */

1444    synchronized public void setName(String JavaDoc theName) {
1445        mObjectName = theName;
1446    } /* setName(String) */
1447
1448    /**
1449     * Set a field as read-only - these fields are not offered for update
1450     * when a form is produced by the generic database maintenance servlet
1451     * (DBMaint). It does not otherwise affect the use of the field.
1452     * <p>Typical uses are for serial-numbered fields and timestamps</p>
1453     *
1454     * @param fieldName The name of the field to be reserved as normally read-only.
1455     * @throws DBException If there is no such field.
1456     */

1457    synchronized public void setReadOnly(String JavaDoc fieldName)
1458            throws DBException {
1459        DBField oneField = getDBField(fieldName);
1460        oneField.setReadOnly();
1461    } /* setReadOnly(String) */
1462
1463
1464    /**
1465     * Set a field as 'secret' - these fields are not shown
1466     * when a list is produced by the generic database maintenance servlet. In
1467     * this way, only users with update permission to the object can view the
1468     * values of "secret" fields.
1469     *
1470     * @param fieldName The name of the field to set as 'secret'
1471     * @throws DBException if the field does not exist
1472     */

1473    synchronized public void setSecret(String JavaDoc fieldName)
1474            throws DBException {
1475        DBField oneField = getDBField(fieldName);
1476        oneField.setSecret();
1477    } /* setSecret(String) */
1478
1479
1480    /**
1481     * Set a filter for a particular field. Check the documentation at
1482     *
1483     * @param fieldName The name of the field to set a particular filter for.
1484     * @param filterMethod The name of the filter method to use when calling a filter.
1485     * Can be one of three values:<br> See @see
1486     * com.jcorporate.expresso.core.security.filters.FilterManager.filterString for
1487     * more information on this parameter.
1488     * @throws DBException if: fieldName doesn't exist, or filterType String
1489     * isn't a valid value.
1490     * @see com.jcorporate.expresso.core.security.filters.FilterManager
1491     * for more information on Filters and implementing Filters for your own
1492     * characterset.
1493     */

1494    synchronized public void setStringFilter(String JavaDoc fieldName, String JavaDoc filterMethod)
1495            throws DBException {
1496
1497        //
1498
//Parameter Check
1499
//
1500
if (!(filterMethod.equalsIgnoreCase("standardFilter") || filterMethod.equalsIgnoreCase("stripFilter") ||
1501                filterMethod.equalsIgnoreCase("rawFilter"))) {
1502            throw new DBException("Undefined Filter Method: " + filterMethod);
1503        }
1504
1505        DBField oneField = getDBField(fieldName);
1506        oneField.setFilterMethod(filterMethod);
1507    } /* setStringFilter(String, String) */
1508
1509
1510    /**
1511     * Set the target table for this DBObject. Note that an object
1512     * can span tables by the use of virtual fields, but that this table
1513     * is the default table for the object.
1514     *
1515     * @param theTable Table for this object
1516     */

1517    synchronized public void setTargetTable(String JavaDoc theTable)
1518            throws DBException {
1519        if (theTable.length() > 18) {
1520            log.warn("Table name is over 18 characters");
1521        }
1522        if (ConfigManager.isReservedWord(theTable)) {
1523            throw new DBException("You cannot have a table name of " +
1524                    theTable +
1525                    ". It is a database reserved word. Check " +
1526                    "com.jcorporate.expresso.core.misc.ReservedWords for a full list" +
1527                    " of reservered words");
1528        }
1529
1530        tableName = theTable;
1531    } /* setTargetTable(String) */
1532
1533
1534    /**
1535     * Set the target database schema for this DBObject.
1536     *
1537     * @param theSchema database schema for this object
1538     * @throws DBException author Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1539     */

1540    synchronized public void setTargetDbSchema(String JavaDoc theSchema)
1541            throws DBException {
1542        if (theSchema.length() > 18) {
1543            log.warn("Schema name is over 18 characters");
1544        }
1545        if (ConfigManager.isReservedWord(theSchema)) {
1546            throw new DBException("You cannot have a Schema name of " +
1547                    theSchema +
1548                    ". It is a database reserved word. Check " +
1549                    "com.jcorporate.expresso.core.misc.ReservedWords for a full list" +
1550                    " of reservered words");
1551        }
1552
1553        dbSchemaName = theSchema;
1554    } /* setTargetSchema(String) */
1555
1556    /**
1557     * Set the target database schema for this DBObject.
1558     *
1559     * @param theCatalog database schema for this object
1560     * @throws DBException author Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1561     */

1562    synchronized public void setTargetDbCatalog(String JavaDoc theCatalog)
1563            throws DBException {
1564        if (theCatalog.length() > 18) {
1565            log.warn("Schema name is over 18 characters");
1566        }
1567        if (ConfigManager.isReservedWord(theCatalog)) {
1568            throw new DBException("You cannot have a Catalog name of " +
1569                    theCatalog +
1570                    ". It is a database reserved word. Check " +
1571                    "com.jcorporate.expresso.core.misc.ReservedWords for a full list" +
1572                    " of reservered words");
1573        }
1574
1575        dbCatalogName = theCatalog;
1576    } /* setTargetDbCatalog(String) */
1577
1578
1579    /**
1580     * @param schemaName the name of the schema
1581     */

1582    synchronized public void setSchema(String JavaDoc schemaName) {
1583        StringUtil.assertNotBlank(mySchema,
1584                "Schema name may not be null or blank");
1585        mySchema = schemaName;
1586    } /* setSchema(String) */
1587
1588    /**
1589     * @return the className of the schema associated with this DBObject
1590     */

1591    public String JavaDoc getSchema() {
1592        return mySchema;
1593    } /* getSchema() */
1594
1595    /**
1596     * <p>This convenience method iterates through all the
1597     * fields belonging to this <code>DBObject</code>
1598     * returns an array of field names ( <code>String</code> ).</p>
1599     *
1600     * @return String array of all field names in this object.
1601     * <p/>
1602     * author Peter Pilgrim <peter.pilgrim@db.com>
1603     * @see #getFieldList()
1604     */

1605    public String JavaDoc[] getFields() {
1606        int N = fieldNamesInOrder.size();
1607        String JavaDoc[] arr = new String JavaDoc[N];
1608
1609        for (int j = 0; j < N; ++j) {
1610            arr[j] = (String JavaDoc) fieldNamesInOrder.get(j);
1611        }
1612
1613        return arr;
1614    } /* getFields() */
1615
1616
1617    /**
1618     * ??????
1619     *
1620     * @param t ???
1621     */

1622    synchronized public void addTransition(Transition t)
1623            throws DBException {
1624        transitionTabs.add(t);
1625    }
1626
1627    /**
1628     * ????????????
1629     *
1630     * @return Iterator to the TransitionTabs
1631     */

1632    public Iterator JavaDoc getTransitionsIterator()
1633            throws DBException {
1634        return transitionTabs.iterator();
1635    }
1636
1637    /**
1638     * Retrieve a set of detail objects.
1639     *
1640     * @return java.util.Set
1641     */

1642    public Set JavaDoc getDetailSet() {
1643        return detailObjsLocal.keySet();
1644    }
1645
1646    /**
1647     * Returns whether the field allows null values or not.
1648     *
1649     * @param fieldName name of the field
1650     * @return true if the field allows null
1651     */

1652    public boolean isAllowsNull(String JavaDoc fieldName) throws DBException {
1653        return allowsNull(fieldName);
1654    }
1655
1656
1657    /**
1658     * Retrieve the metadata for the field.
1659     *
1660     * @param fieldName the name of the field to retrieve the metadata for.
1661     * @return DataFieldMetaData instance for the specified field name.
1662     */

1663    public DataFieldMetaData getFieldMetadata(String JavaDoc fieldName) {
1664        return (DataFieldMetaData) allFields.get(fieldName);
1665    }
1666
1667    /**
1668     * Retrieve all the attributes so you can iterate through them.
1669     *
1670     * @param fieldName the name of the field to retrieve.
1671     * @return java.util.Set of all the attribute names for the given field.
1672     */

1673    public java.util.Set JavaDoc getAllAttributes(String JavaDoc fieldName) {
1674        DBField oneField = (DBField) allFields.get(fieldName);
1675
1676        if (oneField == null) {
1677            throw new IllegalArgumentException JavaDoc("(" + getName() + ") Field " + fieldName +
1678                    " is not defined as a field in this DBObject");
1679        }
1680
1681        return oneField.getAllAttributes();
1682    }
1683
1684
1685    /**
1686     * Return the Store procedure Name of the current database object. Keep in mind
1687     * that a database object could update or affect other tables as well.
1688     *
1689     * @return String: Store procedure name of the target table of this database object
1690     * @throws DataException upon error
1691     * <p/>
1692     * author Yves Henri AMAIZO
1693     */

1694    public String JavaDoc getTargetStoreProcedure()
1695            throws DataException {
1696        if (storeProcedureName == null) {
1697            throw new DataException("No store procedure name supplied");
1698        }
1699
1700        return storeProcedureName;
1701    } /* getTargetTable() */
1702
1703
1704    /**
1705     * Set the target store procedure for this DBObject.
1706     *
1707     * @param theStoreProcedure Store procedure for this object
1708     */

1709    synchronized public void setTargetStoreProcedure(String JavaDoc theStoreProcedure)
1710            throws DBException {
1711        if (theStoreProcedure.length() > 18) {
1712            log.warn("Strore procedure name is over 18 characters");
1713        }
1714        if (ConfigManager.isReservedWord(theStoreProcedure)) {
1715            throw new DBException("You cannot have a store procedure name of " +
1716                    theStoreProcedure +
1717                    ". It is a database reserved word. Check " +
1718                    "com.jcorporate.expresso.core.misc.ReservedWords for a full list" +
1719                    " of reservered words");
1720        }
1721
1722        storeProcedureName = theStoreProcedure;
1723        tableName = theStoreProcedure;
1724    } /* setTargetStoreProcedure(String) */
1725
1726
1727    /**
1728     * Add a new field to the list of fields that are part of this
1729     * object's list of input parameters. Called after all of the "addField" calls in the setupFields()
1730     * method to specify which fields make up the parameter fields of this object.
1731     *
1732     * @param inFieldName The name of the field to add as part of the input parameter
1733     * @throws DBException if the field name is not valid or the field
1734     * allows nulls
1735     */

1736    synchronized public void addInParam(String JavaDoc inFieldName)
1737            throws DBException {
1738        DBField oneField = (DBField) allFields.get(inFieldName);
1739
1740        if (oneField == null) {
1741            throw new DBException("(" + getName() + ") Field " + inFieldName +
1742                    " is not defined as a field in this DBObject - cannot add " +
1743                    "to input list parameter");
1744        }
1745        if (oneField.allowsNull()) {
1746            throw new DBException("(" + getName() + ") Field " + inFieldName +
1747                    " allows null - not suitable for inclusion " +
1748                    "in key");
1749        }
1750        if (oneField.isVirtual()) {
1751            throw new DBException("(" + getName() + ") Field " + inFieldName +
1752                    " is a virtual field - not suitable for " +
1753                    "inclusion in input list parameter");
1754        }
1755
1756        if (oneField.isLongObjectType()) {
1757            throw new DBException("(" + getName() + ") Field " + inFieldName +
1758                    " allows arbitrarily long length, either text or binary - not suitable for inclusion " +
1759                    "in the input list parameter");
1760        }
1761
1762        allInParameters.put(inFieldName, oneField);
1763
1764        /* We must keep keys in order, so we add to keyList as well */
1765        inParamList.add(inFieldName);
1766    } /* addInParam(String) */
1767
1768
1769    /**
1770     * Add a new field to the list of fields that are part of this
1771     * object's list of output parameter. Called after all of the "addField" calls in the setupFields()
1772     * method to specify which fields make up the parameter fields of this object.
1773     *
1774     * @param outFieldName The name of the field to add as part of the output parameter
1775     * @throws DBException if the field name is not valid or the field
1776     * allows nulls
1777     */

1778    synchronized public void addOutParam(String JavaDoc outFieldName)
1779            throws DBException {
1780        DBField oneField = (DBField) allFields.get(outFieldName);
1781
1782        if (oneField == null) {
1783            throw new DBException("(" + getName() + ") Field " + outFieldName +
1784                    " is not defined as a field in this DBObject - cannot add " +
1785                    "to the output list parameter");
1786        }
1787        if (oneField.allowsNull()) {
1788            throw new DBException("(" + getName() + ") Field " + outFieldName +
1789                    " allows null - not suitable for inclusion " +
1790                    "in the output list parameter");
1791        }
1792        if (oneField.isVirtual()) {
1793            throw new DBException("(" + getName() + ") Field " + outFieldName +
1794                    " is a virtual field - not suitable for " +
1795                    "inclusion in the output list parameter");
1796        }
1797
1798        if (oneField.isLongObjectType()) {
1799            throw new DBException("(" + getName() + ") Field " + outFieldName +
1800                    " allows arbitrarily long length, either text or binary - not suitable for inclusion " +
1801                    "in the output list parameter");
1802        }
1803
1804        allOutParameters.put(outFieldName, oneField);
1805
1806        /* We must keep keys in order, so we add to keyList as well */
1807        outParamList.add(outFieldName);
1808    } /* addOutParam(String) */
1809
1810
1811    public boolean isReturningValue() {
1812        return returningValue;
1813    }
1814
1815    /**
1816     * @param value returning value to be set
1817     */

1818    public void setReturningValue(boolean value) {
1819        returningValue = value;
1820    }
1821
1822    /**
1823     * Check if a certain name is a INPUT field parameter(of any kind) in this DBOBject
1824     *
1825     * @param fieldName the name of the field to check
1826     * @return true if the field name exists
1827     */

1828    public boolean isOutField(String JavaDoc fieldName) {
1829        return allOutParameters.get(fieldName) != null;
1830    }
1831
1832    /**
1833     * Check if a certain name is a OUTPUT field parameter(of any kind) in this DBOBject
1834     *
1835     * @param fieldName the name of the field to check
1836     * @return true if the field name exists
1837     */

1838    public boolean isInField(String JavaDoc fieldName) {
1839        return allInParameters.get(fieldName) != null;
1840    }
1841
1842    /**
1843     * Return the Table Name of the current database object. Keep in mind
1844     * that a database object could update or affect other tables as well.
1845     *
1846     * @return String: Table name of the target table of this database object
1847     * @throws DataException upon error
1848     * <p/>
1849     * author Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1850     */

1851    public String JavaDoc getTargetSQLTable(String JavaDoc dataContext)
1852            throws DataException {
1853        String JavaDoc sqlTableName = getTargetTable();
1854        try {
1855            if (getTargetDbSchema() != null && !"".equals(getTargetDbSchema())) {
1856                sqlTableName = getTargetDbSchema() + "." + getTargetTable();
1857            } else {
1858                JDBCConfig myConfig = ConfigManager.getJdbcRequired(dataContext);
1859                if (myConfig.getDbSchema() != null && !"".equals(myConfig.getDbSchema())) {
1860                    sqlTableName = myConfig.getDbSchema() + "." + getTargetTable();
1861                }
1862            }
1863        } catch (ConfigurationException ce) {
1864            throw new DataException(ce);
1865        }
1866        return sqlTableName;
1867    } /* getTargetSQLTable() */
1868
1869
1870    /**
1871     * Get a list of all of the names of the IN param fields in this object
1872     *
1873     * @return An ArrayList of all of the names of the IN param fields
1874     */

1875    public ArrayList JavaDoc getInParamListArray() {
1876        return inParamList;
1877    }
1878
1879    /**
1880     * Get a list of all of the names of the OUT param fields in this object
1881     *
1882     * @return An ArrayList of all of the names of the OUT param fields
1883     */

1884    public ArrayList JavaDoc getOutParamListArray() {
1885        return outParamList;
1886    }
1887
1888
1889    /**
1890     * Retrieve an interator of IN param fields
1891     *
1892     * @return Iterator of IN param fields. [MetaData]
1893     */

1894    public Iterator JavaDoc getInParamFieldListIterator() {
1895        return inParamList.iterator();
1896    }
1897
1898
1899    /**
1900     * Retrieve an interator of IN param fields
1901     *
1902     * @return Iterator of IN param fields. [MetaData]
1903     */

1904    public Iterator JavaDoc getOutParamFieldListIterator() {
1905        return outParamList.iterator();
1906    }
1907
1908    /**
1909     * This convenience method counts
1910     * <code>DBFields</code> belonging to this
1911     * <code>DBObject</code> that are set to <b>retrieve</b>.
1912     * author Yves Henri Amaizo <amy_amaizo@compuserve.com>
1913     *
1914     * @return int number of retrieve fields.
1915     */

1916    public synchronized int getOutParamFieldsCount()
1917            throws DBException {
1918        if (outParamList == null) {
1919            return 0;
1920        } else {
1921            return outParamList.size();
1922        }
1923    } /* getFieldsToRetrieveCount() */
1924
1925
1926}
1927
Popular Tags