0001: /* ====================================================================
0002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
0003: *
0004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * 1. Redistributions of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * 2. Redistributions in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * 3. The end-user documentation included with the redistribution,
0019: * if any, must include the following acknowledgment:
0020: * "This product includes software developed by Jcorporate Ltd.
0021: * (http://www.jcorporate.com/)."
0022: * Alternately, this acknowledgment may appear in the software itself,
0023: * if and wherever such third-party acknowledgments normally appear.
0024: *
0025: * 4. "Jcorporate" and product names such as "Expresso" must
0026: * not be used to endorse or promote products derived from this
0027: * software without prior written permission. For written permission,
0028: * please contact info@jcorporate.com.
0029: *
0030: * 5. Products derived from this software may not be called "Expresso",
0031: * or other Jcorporate product names; nor may "Expresso" or other
0032: * Jcorporate product names appear in their name, without prior
0033: * written permission of Jcorporate Ltd.
0034: *
0035: * 6. No product derived from this software may compete in the same
0036: * market space, i.e. framework, without prior written permission
0037: * of Jcorporate Ltd. For written permission, please contact
0038: * partners@jcorporate.com.
0039: *
0040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
0044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
0046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0051: * SUCH DAMAGE.
0052: * ====================================================================
0053: *
0054: * This software consists of voluntary contributions made by many
0055: * individuals on behalf of the Jcorporate Ltd. Contributions back
0056: * to the project(s) are encouraged when you make modifications.
0057: * Please send them to support@jcorporate.com. For more information
0058: * on Jcorporate Ltd. and its products, please see
0059: * <http://www.jcorporate.com/>.
0060: *
0061: * Portions of this software are based upon other open source
0062: * products and are subject to their respective licenses.
0063: */
0064:
0065: package com.jcorporate.expresso.core.dbobj;
0066:
0067: import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData;
0068: import com.jcorporate.expresso.core.db.DBException;
0069: import org.apache.log4j.Logger;
0070: import org.apache.oro.text.regex.MalformedPatternException;
0071: import org.apache.oro.text.regex.Pattern;
0072: import org.apache.oro.text.regex.PatternCompiler;
0073: import org.apache.oro.text.regex.Perl5Compiler;
0074:
0075: import java.io.IOException;
0076: import java.io.ObjectInputStream;
0077: import java.io.Serializable;
0078: import java.util.HashMap;
0079: import java.util.HashSet;
0080: import java.util.Hashtable;
0081: import java.util.Iterator;
0082: import java.util.Set;
0083:
0084: /**
0085: * A DBField object represents a single field definition in a DBObjectDef. It does
0086: * not store any actual data, only the meta-data associated with a field.
0087: *
0088: * @author Michael Nash
0089: */
0090: public class DBField implements Serializable, DataFieldMetaData {
0091:
0092: /**
0093: * AUTOINC_TYPE is a special expresso type code for auto-increment field,
0094: * a synonym for integer.
0095: */
0096: transient public static final String AUTOINC_TYPE = "auto-inc";
0097:
0098: transient public static final String ARRAY_TYPE = "array";
0099: transient public static final String BIGINT_TYPE = "bigint";
0100: transient public static final String BINARY_TYPE = "binary";
0101: transient public static final String BIT_TYPE = "bit";
0102: /**
0103: * boolean is synonym for bit
0104: */
0105: transient public static final String BOOLEAN_TYPE = "boolean";
0106: transient public static final String BLOB_TYPE = "blob";
0107: transient public static final String CHAR_TYPE = "char";
0108: transient public static final String CLOB_TYPE = "clob";
0109:
0110: transient public static final String DATE_TYPE = "date";
0111: /**
0112: * datetime is a synonym for timestamp
0113: */
0114: transient public static final String DATETIME_TYPE = "datetime";
0115: transient public static final String DOUBLE_TYPE = "double";
0116: transient public static final String DECIMAL_TYPE = "decimal";
0117:
0118: transient public static final String FLOAT_TYPE = "float";
0119: transient public static final String INTEGER_TYPE = "int";
0120: /**
0121: * int is synonym for integer
0122: */
0123: transient public static final String INT_TYPE = "integer";
0124: transient public static final String JAVA_OBJECT = "java_object";
0125:
0126: /**
0127: * long is a synonym for BIGINT
0128: */
0129: transient public static final String LONG_TYPE = "long";
0130: transient public static final String LONGVARCHAR_TYPE = "longvarchar";
0131: transient public static final String LONGVARBINARY = "longvarbinary";
0132: /**
0133: * null isn't supported in expresso as of 5/02
0134: */
0135: transient public static final String NULL_TYPE = "null";
0136: transient public static final String NUMERIC_TYPE = "numeric";
0137: transient public static final String OTHER_TYPE = "other";
0138:
0139: transient public static final String REAL_TYPE = "real";
0140: transient public static final String REF_TYPE = "ref";
0141: transient public static final String SMALLINT_TYPE = "smallint";
0142: transient public static final String STRUCT_TYPE = "struct";
0143:
0144: transient public static final String TIME_TYPE = "time";
0145: transient public static final String TIMESTAMP_TYPE = "timestamp";
0146: /**
0147: * text is a synonym for longvarchar
0148: */
0149: transient public static final String TEXT_TYPE = "text";
0150: transient public static final String TINYINT_TYPE = "tinyint";
0151: transient public static final String VARBINARY_TYPE = "varbinary";
0152: transient public static final String VARCHAR_TYPE = "varchar";
0153:
0154: /**
0155: * Boolean regular expression syntax for easy reference.
0156: */
0157: public static final String BOOLEAN_MASK = "^([01]|true|TRUE|false|FALSE|y|Y|n|N)$";
0158:
0159: /**
0160: * Date regular expression syntax for easy reference.
0161: */
0162: public static final String DATE_MASK = "^[\\d\\s-:/.+]+$";
0163:
0164: /**
0165: * Integer Regular Expression for easy reference
0166: */
0167: public static final String INT_MASK = "^[+-]?[0-9]+";
0168:
0169: /**
0170: * Floating point regular expression syntax for easy reference.
0171: */
0172: public static final String FLOAT_MASK = "^([+-]?)(?=\\d|\\.\\d)\\d*(\\.\\d*)?([Ee]([+-]?\\d+))?$";
0173:
0174: /**
0175: * Perl5 Regular Expression Compiler. The patterns generated by this compiler
0176: * are mainly stored in the field mask table.
0177: */
0178: transient private static PatternCompiler patternCompiler = new Perl5Compiler();
0179:
0180: /**
0181: * Attribute String for if there's an error with the field.
0182: */
0183: public static final String ATTRIBUTE_ERROR = "error";
0184:
0185: /**
0186: * Attribute String for what message to display if there's an error
0187: * with thie field.
0188: */
0189: public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message";
0190:
0191: protected String fieldName;
0192:
0193: /**
0194: * The string "type" used to specify this type of field in Expresso
0195: */
0196: protected String expressoFieldTypeString;
0197:
0198: //protected String fieldValue;
0199:
0200: /**
0201: * Is a null value allowed for this field.
0202: */
0203: protected boolean allowNull;
0204:
0205: /**
0206: * The user friendly description of this field.
0207: */
0208: protected String description;
0209:
0210: /**
0211: * The size of this field. ex: 80 for VARCHAR(80)
0212: */
0213: protected int fieldSize;
0214:
0215: /**
0216: * Is this a virtual field: Ie, does the system provide all values
0217: * for this field.
0218: */
0219: protected boolean isVirtual = false;
0220:
0221: /* regular expression "mask" for this field, if any */
0222: protected Pattern mask = null;
0223:
0224: /**
0225: * User Defined Attributes for each field.
0226: */
0227: protected Hashtable attributes = null;
0228:
0229: /**
0230: * Is this field selected as a unique or distinct field?
0231: */
0232: /* protected boolean isDistinct = false; */
0233: /**
0234: * Is this a multivalued field
0235: */
0236: protected boolean isMultiValued = false;
0237:
0238: /**
0239: * Does this field not appear in standard DBMaint listings?
0240: */
0241: protected boolean isSecret = false;
0242:
0243: /**
0244: * Is this field readonly?
0245: */
0246: protected boolean isReadOnly = false;
0247:
0248: /**
0249: * is the field boolean?
0250: */
0251: private boolean isBoolean;
0252:
0253: /**
0254: * is the field numeric?
0255: */
0256: private boolean isNumeric;
0257: /**
0258: * is the field a date type?
0259: */
0260: private boolean isDate;
0261:
0262: /**
0263: * is the field a datetime or timestamp type?
0264: * This necessary for handling correctly the Database datatime format
0265: * when retrieve data from resultSet
0266: * author Yves Henri AMAIZO
0267: */
0268: private boolean isDateTime;
0269: /**
0270: * is the field a time type?
0271: * This necessary for handling correctly the Database datatime format
0272: * when retrieve data from resultSet
0273: * author Yves Henri AMAIZO
0274: */
0275: private boolean isTime;
0276:
0277: /**
0278: * is the field a date type?
0279: * This necessary for handling correctly the Database datatime format
0280: * when retrieve data from resultSet
0281: * author Yves Henri AMAIZO
0282: */
0283: private boolean isDateOnly;
0284:
0285: /**
0286: * The default value for when a data object is first initialized.
0287: */
0288: private String defaultValue;
0289:
0290: /**
0291: * is the field a time type?
0292: * This necessary for handling correctly the Database string format data
0293: * when retrieve data from resultSet
0294: * Oracle does not handlin correctly string more longer than 4000 chars
0295: * author Yves Henri AMAIZO
0296: */
0297: private boolean isLongBinary;
0298:
0299: private boolean isLongCharacter;
0300:
0301: /**
0302: * is the field a text type?
0303: */
0304: private boolean isText;
0305:
0306: /**
0307: * String for lookup object classname
0308: */
0309: protected String lookupObject;
0310:
0311: /**
0312: * String for the lookup field in the lookup object that maps to this
0313: * field.
0314: */
0315: protected String lookupField;
0316:
0317: /**
0318: * Optional parameter that defines the definition of the lookup object if
0319: * the lookup object implements the Defineable interface.
0320: */
0321: protected String lookupDefinition;
0322:
0323: /**
0324: * Is this a key field?
0325: */
0326: protected boolean isKey = false;
0327:
0328: /**
0329: * Is this object a LOB?
0330: */
0331: protected boolean isLongObject = false;
0332:
0333: /**
0334: * Is this object a CLOB?
0335: */
0336: protected boolean isCharacterLongObject = false;
0337:
0338: /**
0339: * What is the string filtering method applied with this filter
0340: */
0341: protected String filterMethod = "standardFilter";
0342:
0343: /**
0344: * The Log Category associated with DBFields
0345: */
0346: private transient static Logger logCat = Logger
0347: .getLogger(DBField.class);
0348:
0349: /**
0350: * set if the field is autoincremented
0351: */
0352: private boolean isAutoInc = false;
0353:
0354: /**
0355: * Set this value to true if you want a particular string field encrypted
0356: * (Not implemented yet)
0357: */
0358: protected boolean encrypted = false;
0359:
0360: /**
0361: * Set this value to true if you want a particular string field hashed
0362: * instead of stored in plaintext.
0363: * (Not implamented yet)
0364: */
0365: protected boolean hashed = false;
0366:
0367: /**
0368: * Field precision, if applicable to this field
0369: */
0370: protected int precision;
0371:
0372: protected boolean isFloatingPointType = false;
0373:
0374: /**
0375: * the preferred filtering class; null indicates default
0376: */
0377: private Class mFilterClass;
0378:
0379: /**
0380: * contains a list of all data types that should be quoted when building
0381: * SQL strings.
0382: */
0383: transient private static Set quotedDataTypes = new HashSet(5);
0384: transient private static Set numericDataTypes = new HashSet(10);
0385: transient private static Set dateTypes = new HashSet(4);
0386:
0387: /**
0388: * Contains a list of all recognized expresso data types.
0389: */
0390: transient public static Set allDataTypes = new HashSet(40);
0391:
0392: static {
0393: quotedDataTypes.add(CHAR_TYPE);
0394: quotedDataTypes.add(VARCHAR_TYPE);
0395: quotedDataTypes.add(TEXT_TYPE);
0396: quotedDataTypes.add(LONGVARCHAR_TYPE);
0397:
0398: numericDataTypes.add(NUMERIC_TYPE);
0399: numericDataTypes.add(INT_TYPE);
0400: numericDataTypes.add(INTEGER_TYPE);
0401: numericDataTypes.add(DOUBLE_TYPE);
0402: numericDataTypes.add(FLOAT_TYPE);
0403: numericDataTypes.add(REAL_TYPE);
0404: numericDataTypes.add(DECIMAL_TYPE);
0405: numericDataTypes.add(AUTOINC_TYPE);
0406: numericDataTypes.add(BIGINT_TYPE);
0407: numericDataTypes.add(LONG_TYPE);
0408: numericDataTypes.add(SMALLINT_TYPE);
0409: numericDataTypes.add(TINYINT_TYPE);
0410:
0411: dateTypes.add(DATE_TYPE);
0412: dateTypes.add(DATETIME_TYPE);
0413: dateTypes.add(TIME_TYPE);
0414: dateTypes.add(TIMESTAMP_TYPE);
0415:
0416: allDataTypes.add(DBField.ARRAY_TYPE);
0417: allDataTypes.add(DBField.BIGINT_TYPE);
0418: allDataTypes.add(DBField.LONG_TYPE);
0419: allDataTypes.add(DBField.BINARY_TYPE);
0420: allDataTypes.add(DBField.BIT_TYPE);
0421: allDataTypes.add(DBField.BOOLEAN_TYPE);
0422: allDataTypes.add(DBField.BLOB_TYPE);
0423: allDataTypes.add(DBField.CHAR_TYPE);
0424: allDataTypes.add(DBField.CLOB_TYPE);
0425: allDataTypes.add(DBField.DATE_TYPE);
0426: allDataTypes.add(DBField.DECIMAL_TYPE);
0427: allDataTypes.add(DBField.DOUBLE_TYPE);
0428: allDataTypes.add(DBField.FLOAT_TYPE);
0429: allDataTypes.add(DBField.INTEGER_TYPE);
0430: allDataTypes.add(DBField.INT_TYPE);
0431: allDataTypes.add(DBField.JAVA_OBJECT);
0432: allDataTypes.add(DBField.LONGVARBINARY);
0433: allDataTypes.add(DBField.LONGVARCHAR_TYPE);
0434: allDataTypes.add(DBField.NUMERIC_TYPE);
0435: allDataTypes.add(DBField.OTHER_TYPE);
0436: allDataTypes.add(DBField.REAL_TYPE);
0437: allDataTypes.add(DBField.REF_TYPE);
0438: allDataTypes.add(DBField.SMALLINT_TYPE);
0439: allDataTypes.add(DBField.STRUCT_TYPE);
0440: allDataTypes.add(DBField.TIME_TYPE);
0441: allDataTypes.add(DBField.TIMESTAMP_TYPE);
0442: allDataTypes.add(DBField.DATETIME_TYPE);
0443: allDataTypes.add(DBField.TINYINT_TYPE);
0444: allDataTypes.add(DBField.VARBINARY_TYPE);
0445: allDataTypes.add(DBField.VARCHAR_TYPE);
0446:
0447: // TEXT_TYPE synonym for longvarchar
0448: allDataTypes.add(DBField.TEXT_TYPE);
0449:
0450: // auto-inc is unique to expresso
0451: allDataTypes.add(DBField.AUTOINC_TYPE);
0452:
0453: }
0454:
0455: /**
0456: * Constructor: A DBField is initialized knowing it's name, type, size,
0457: * description and whether or not it can accept null or empty values
0458: *
0459: * @param myName Field name of this field
0460: * @param myType Database type of the field - use string constant from DBField
0461: * @param mySize Size of the field in characters
0462: * @param newPrecision precision for this field
0463: * @param myAllowNull True if null is allowed, false if not
0464: * @param myDescrip Description (title) of the field
0465: */
0466: public DBField(String myName, String myType, int mySize,
0467: int newPrecision, boolean myAllowNull, String myDescrip)
0468: throws DBException {
0469: if (myName.length() > 18) {
0470: logCat.warn("Field name '" + myName
0471: + "' is over 18 characters - may not be portable");
0472: }
0473:
0474: fieldName = myName;
0475: expressoFieldTypeString = myType;
0476: allowNull = myAllowNull;
0477: description = myDescrip;
0478: fieldSize = mySize;
0479: precision = newPrecision;
0480:
0481: isNumeric = numericDataTypes.contains(myType);
0482: isBoolean = myType.equalsIgnoreCase(BOOLEAN_TYPE);
0483: isDate = dateTypes.contains(myType);
0484: isDateOnly = myType.equalsIgnoreCase(DATE_TYPE);
0485: isTime = myType.equalsIgnoreCase(TIME_TYPE);
0486: isDateTime = myType.equalsIgnoreCase(TIMESTAMP_TYPE)
0487: || myType.equalsIgnoreCase(DATETIME_TYPE);
0488: isText = quotedDataTypes.contains(myType);
0489: isAutoInc = myType.equalsIgnoreCase(AUTOINC_TYPE);
0490: isFloatingPointType = myType.equalsIgnoreCase(FLOAT_TYPE);
0491:
0492: isCharacterLongObject = (myType.equalsIgnoreCase(TEXT_TYPE)
0493: || myType.equalsIgnoreCase(LONGVARCHAR_TYPE) || myType
0494: .equalsIgnoreCase(CLOB_TYPE));
0495:
0496: isLongObject = (isCharacterLongObject
0497: || myType.equalsIgnoreCase(BINARY_TYPE)
0498: || myType.equalsIgnoreCase(BLOB_TYPE)
0499: || myType.equalsIgnoreCase(JAVA_OBJECT)
0500: || myType.equalsIgnoreCase(LONGVARBINARY) || myType
0501: .equalsIgnoreCase(VARBINARY_TYPE));
0502:
0503: setDefaultMask();
0504:
0505: } /* DBField(String, String, int, boolean, String) */
0506:
0507: /**
0508: * constructor for types with no size
0509: *
0510: * @param myName Field name of this field
0511: * @param myType Database type of the field - use string constant from DBField
0512: * @param newPrecision precision for this field
0513: * @param myAllowNull True if null is allowed, false if not
0514: * @param myDescrip Description (title) of the field
0515: */
0516: public DBField(String myName, String myType, int newPrecision,
0517: boolean myAllowNull, String myDescrip) throws DBException {
0518: this (myName, myType, 0, newPrecision, myAllowNull, myDescrip);
0519: }
0520:
0521: /**
0522: * Does this field allow nulls?
0523: *
0524: * @return boolean True if the field allows null, else false if it does not
0525: */
0526: public boolean allowsNull() {
0527: return allowNull;
0528: } /* allowsNull() */
0529:
0530: /**
0531: * Return the description of this field
0532: *
0533: * @return String Description of the field
0534: */
0535: public String getDescription() {
0536: return description;
0537: } /* getDescription() */
0538:
0539: /**
0540: * Retrieve the default value for the field.
0541: *
0542: * @return String
0543: */
0544: public String getDefaultValue() {
0545: return defaultValue;
0546: }
0547:
0548: /**
0549: * Sets the default value of the field.
0550: *
0551: * @param newValue String
0552: */
0553: public void setDefaultValue(String newValue) {
0554: this .defaultValue = newValue;
0555: }
0556:
0557: /**
0558: * Return the filter method currently used for this field.
0559: *
0560: * @return The name of the filter method
0561: */
0562: public String getFilterMethod() {
0563: return filterMethod;
0564: } /* getFilterMethod() */
0565:
0566: /**
0567: * Return the length of the field in characters
0568: *
0569: * @return String A String containing the number of characters of
0570: * this fields length
0571: */
0572: public String getLength() {
0573: return String.valueOf(fieldSize);
0574: } /* getLength() */
0575:
0576: /**
0577: * Return the length of this field as an integer
0578: *
0579: * @return int The length of this field in characters
0580: */
0581: public int getLengthInt() {
0582: return fieldSize;
0583: } /* getLengthInt() */
0584:
0585: /**
0586: * Return the value for the lookupObject for this field
0587: *
0588: * @return String for the lookup object for this field
0589: */
0590: public String getLookupObject() {
0591: return lookupObject;
0592: } /* getLookupObject() */
0593:
0594: /**
0595: * Future versions of Expresso will rely more on objects that are shown as
0596: * unique by a combination of their classname and their definition names. All
0597: * instances of Defineable must have a corresponding definition name.
0598: *
0599: * @return java.lang.String
0600: */
0601: public String getLookupDefinition() {
0602: return lookupDefinition;
0603: }
0604:
0605: /**
0606: * When you get a lookup object, to perform a complete mapping between the
0607: * two, you need to know what field name in the remote object maps to this
0608: * field.
0609: *
0610: * @return java.lang.String or null if there is no lookup field
0611: * @throws IllegalArgumentException if the field name does not exist
0612: */
0613: public String getLookupField() {
0614: return this .lookupField;
0615: }
0616:
0617: /**
0618: * Return the name of the field
0619: *
0620: * @return String The name of this field
0621: */
0622: public String getName() {
0623: return fieldName;
0624: } /* getName() */
0625:
0626: /**
0627: * Return the precision of this field as an integer
0628: *
0629: * @return int The precision of this field
0630: */
0631: public int getPrecision() {
0632: return precision;
0633: } /* getPrecision() */
0634:
0635: /**
0636: * Return the database type of the field as specified with a
0637: * string in the DBObject itself
0638: *
0639: * @return The type of this field
0640: */
0641: public String getTypeString() {
0642: return expressoFieldTypeString;
0643: } /* getTypeString() */
0644:
0645: /**
0646: * Is this field a key field?
0647: *
0648: * @return true if this field is a key field
0649: */
0650: public boolean isKey() {
0651: return isKey;
0652: } /* isKey() */
0653:
0654: /**
0655: * Is this field multi-valued?
0656: *
0657: * @return boolean True if the field is multi-valued, else false
0658: */
0659: public boolean isMultiValued() {
0660: return isMultiValued;
0661: } /* isMultiValued() */
0662:
0663: /**
0664: * Return the field's read-only
0665: *
0666: * @return True if the field is readonly, else false if it is not
0667: */
0668: public boolean isReadOnly() {
0669: return isReadOnly || isAutoIncremented();
0670: } /* isReadOnly() */
0671:
0672: /**
0673: * is the field a boolean?
0674: * cache answer for efficiency, since field type is immutable
0675: *
0676: * @return True if the field is boolean
0677: */
0678: public boolean isBooleanType() {
0679: return this .isBoolean;
0680: }
0681:
0682: /**
0683: * Is this field fall into the classification of a long character
0684: * object?
0685: *
0686: * @return boolean true if it does
0687: */
0688: public boolean isCharacterLongObjectType() {
0689: return this .isCharacterLongObject;
0690: }
0691:
0692: /**
0693: * Does this field fall into a class of BLOB object data types?
0694: *
0695: * @return boolean true if it does
0696: */
0697: public boolean isLongObjectType() {
0698: return this .isLongObject;
0699: }
0700:
0701: /**
0702: * Is it a LONGVARBINARY? This is calculated by if it is a long object
0703: * and is NOT a character long object.
0704: *
0705: * @return boolean True if it is
0706: */
0707: public boolean isLongBinaryType() {
0708: return this .isLongBinary;
0709: }
0710:
0711: /**
0712: * Is it a LONGVARCHAR? This is calculated by if it is a long object
0713: * and is NOT a character long object.
0714: *
0715: * @return boolean True if it is
0716: */
0717: public boolean isLongCharacterType() {
0718: return this .isLongCharacter;
0719: }
0720:
0721: /**
0722: * Is it a BLOB? This is calculated by if it is a long object
0723: * and is NOT a character long object.
0724: *
0725: * @return boolean True if it is
0726: */
0727: public boolean isBinaryObjectType() {
0728: return (isLongObject & !isCharacterLongObject & !isLongBinary);
0729: }
0730:
0731: /**
0732: * is the field a quoted text field?
0733: * cache answer for efficiency, since field type is immutable
0734: *
0735: * @return True if the field is text field
0736: */
0737: public boolean isQuotedTextType() {
0738: return isText;
0739: }
0740:
0741: /**
0742: * is the field a numeric field?
0743: * cache answer for efficiency, since field type is immutable
0744: *
0745: * @return true if the field is numberic field
0746: */
0747: public boolean isNumericType() {
0748: return isNumeric;
0749: }
0750:
0751: /**
0752: * is the field a date or time field?
0753: * cache answer for efficiency, since field type is immutable
0754: *
0755: * @return true if the field is date or time field
0756: */
0757: public boolean isDateType() {
0758: return isDate;
0759: }
0760:
0761: /**
0762: * is the field a date or time field?
0763: * cache answer for efficiency, since field type is immutable
0764: *
0765: * @return true if the field is date field
0766: * author Yves Henri AMAIZO
0767: */
0768: public boolean isDateOnlyType() {
0769: return isDateOnly;
0770: }
0771:
0772: public boolean isFloatingPointType() {
0773: return isFloatingPointType;
0774: }
0775:
0776: /**
0777: * is the field a date or time field?
0778: * cache answer for efficiency, since field type is immutable
0779: *
0780: * @return true if the field is time field
0781: * author Yves Henri AMAIZO
0782: */
0783: public boolean isTimeType() {
0784: return isTime;
0785: }
0786:
0787: /**
0788: * is the field a date or time field?
0789: * cache answer for efficiency, since field type is immutable
0790: *
0791: * @return true if the field is dateTime or Timestamp field
0792: * author Yves Henri AMAIZO
0793: */
0794: public boolean isDateTimeType() {
0795: return isDateTime;
0796: }
0797:
0798: /**
0799: * Return the field's secret status
0800: *
0801: * @return True if the field is secret, else false if it is not
0802: */
0803: public boolean isSecret() {
0804: return isSecret;
0805: } /* isSecret() */
0806:
0807: /**
0808: * Return the field's hashed status
0809: *
0810: * @return True if the field is secret, else false if it is not
0811: * @todo This is not completely implemented yet.
0812: */
0813: public boolean isHashed() {
0814: return hashed;
0815: } /* isHashed() */
0816:
0817: /**
0818: * Return the field's hashed status
0819: *
0820: * @return True if the field is secret, else false if it is not
0821: * @todo This is not completely implemented yet.
0822: */
0823: public boolean isEncrypted() {
0824: return encrypted;
0825: } /* isEncrypted() */
0826:
0827: /**
0828: * Is this field a virtual field? E.g. not stored in the database
0829: *
0830: * @return boolean True if the field is virtual, else false
0831: */
0832: public boolean isVirtual() {
0833: return isVirtual;
0834: } /* isVirtual() */
0835:
0836: /**
0837: * Set's the name of the filter method to be used
0838: *
0839: * @param newMethod The name of the filter method to use.
0840: * @return old filter just replaced
0841: * @see com.jcorporate.expresso.core.security.filters.FilterManager
0842: */
0843: public String setFilterMethod(String newMethod) throws DBException {
0844:
0845: //Check for validity of new method
0846: if (!(newMethod.equals("standardFilter")
0847: || newMethod.equals("rawFilter") || newMethod
0848: .equals("stripFilter"))) {
0849: throw new DBException("Unknown Filter Method Name: "
0850: + newMethod);
0851: }
0852:
0853: String oldmethod = filterMethod;
0854: filterMethod = newMethod;
0855: return oldmethod;
0856: } /* setFilterMethod(String) */
0857:
0858: /**
0859: * Set this field as a key field (or not)
0860: *
0861: * @param newKey Is this field a key?
0862: */
0863: public void setKey(boolean newKey) {
0864: isKey = newKey;
0865: } /* setKey(boolean) */
0866:
0867: /**
0868: * Set the value for the "lookup object" for this field. This is
0869: * a database object name which can be used to look up valid
0870: * values for this field by the user. This is used by the standard
0871: * maintenance forms to create a "Lookup" link alongside the
0872: * field if this value is set
0873: *
0874: * @param objectName the classname of the lookup object
0875: */
0876: public synchronized void setLookupObject(String objectName) {
0877: lookupObject = objectName;
0878: } /* setLookupObject(String) */
0879:
0880: /**
0881: * Sets the value for the "lookup field". This is the field name in the
0882: * lookup object that maps to this particular field.
0883: *
0884: * @param lookupFieldName the name of the field to retrieve.
0885: */
0886: public synchronized void setLookupField(String lookupFieldName) {
0887: lookupField = lookupFieldName;
0888: }
0889:
0890: /**
0891: * Sets the value for the "lookup definition" this is the name of the definition
0892: * for objects implementing the defineable interface.
0893: *
0894: * @param definitionName java.lang.String. Depends on the class implementation
0895: * of the Defineable implementation.
0896: */
0897: public synchronized void setLookupDefinition(String definitionName) {
0898: lookupDefinition = definitionName;
0899: }
0900:
0901: /**
0902: * Set this field to be "multi-valued". A multi-valued field has
0903: * a specific set of valid values, often from another database
0904: * object. Any multi-valued field may be used in a call to the
0905: * getValues method, which will return a hashtable of the valid
0906: * values for the field and descriptions for those values.
0907: *
0908: * @param newMulti True if the field is multi-valued, false if it is not
0909: * @see com.jcorporate.expresso.core.dbobj.DBObject#isMultiValued
0910: */
0911: public synchronized void setMultiValued(boolean newMulti) {
0912: isMultiValued = newMulti;
0913: } /* setMultiValued(boolean) */
0914:
0915: /**
0916: * Set the field's hashed status. Only works if the field is a string
0917: * data type (in the future CLOB should be ok too) [This is currently not
0918: * yet implemented and tested]
0919: *
0920: * @param newValue true if you want this field hashed.
0921: */
0922: public synchronized void setHashed(boolean newValue) {
0923: if (this .isQuotedTextType()) {
0924: if (logCat.isDebugEnabled()) {
0925: logCat.debug("Setting field " + fieldName
0926: + " to hashed status");
0927: }
0928:
0929: hashed = newValue;
0930: } else {
0931: throw new java.lang.IllegalArgumentException(fieldName
0932: + " Field needs to be a string data type field");
0933: }
0934: } /* setHashed(boolean) */
0935:
0936: /**
0937: * Set the field's encrypted status
0938: *
0939: * @param newValue new value if you want an encrypted field
0940: * @todo This is not completely implemented yet.
0941: */
0942: public synchronized void setEncrypted(boolean newValue) {
0943: if (this .isQuotedTextType()) {
0944: if (logCat.isDebugEnabled()) {
0945: logCat.debug("Setting field " + fieldName
0946: + " to encrypted status");
0947: }
0948:
0949: encrypted = newValue;
0950: } else {
0951: throw new IllegalArgumentException(
0952: "Field needs to be a string data type field");
0953: }
0954: } /* setEncrypted(boolean) */
0955:
0956: /**
0957: * Set the field as a read-only field. Read only fields are still used
0958: * against the database, but are not offered for updating when the
0959: * automatic database maintenance servlet creates a form on the screen. Note
0960: * this is different from the setAutoIncremented method below, which
0961: * means this field will not participate in any add or update statement
0962: * to the database.
0963: */
0964: public synchronized void setReadOnly() {
0965: isReadOnly = true;
0966: } /* setReadOnly() */
0967:
0968: /**
0969: * Is this field an auto-incremented field?
0970: *
0971: * @return true if this field is autoincremented
0972: */
0973: public boolean isAutoIncremented() {
0974: return isAutoInc;
0975: } /* isAutoIncremented() */
0976:
0977: /**
0978: * Set the field as a 'secret' field. Secret fields are not shown
0979: * in listings of data from this database object, and are only available
0980: * to users with update, add or delete permissions
0981: */
0982: public synchronized void setSecret() {
0983: isSecret = true;
0984: } /* setSecret() */
0985:
0986: /**
0987: * Set this field as a virtual field. A virtual field is part of the object
0988: * but not stored in the database table.
0989: *
0990: * @param newVirtual True to make this object virtual, false if it is not
0991: */
0992: public synchronized void setVirtual(boolean newVirtual) {
0993: isVirtual = newVirtual;
0994: } /* setVirtual(boolean) */
0995:
0996: /**
0997: * Set a regular expression "mask" for this field that specifies it's
0998: * valid values. The mask should already be compiled by the regular
0999: * expression compiler
1000: *
1001: * @param newMask The compiled regular expression mask
1002: */
1003: public void setMask(Pattern newMask) {
1004: mask = newMask;
1005: }
1006:
1007: /**
1008: * Set the field's default mask according to it's type
1009: *
1010: * @throws DBException on error
1011: */
1012: public void setDefaultMask() throws DBException {
1013: /* Still have not defined default masks for the following types. Either they are text types, which will be quoted
1014: and do not need default masks, or do not fit into the mold (like BLOB)
1015: DBField.ARRAY_TYPE
1016: DBField.AUTOINC_TYPE
1017: DBField.BINARY_TYPE
1018: DBField.BLOB_TYPE
1019: DBField.CHAR_TYPE
1020: DBField.CLOB_TYPE
1021: DBField.JAVA_OBJECT
1022: DBField.LONGVARBINARY
1023: DBField.LONGVARCHAR_TYPE
1024: DBField.NULL_TYPE
1025: DBField.OTHER_TYPE
1026: DBField.REF_TYPE
1027: DBField.STRUCT_TYPE
1028: DBField.TEXT_TYPE
1029: DBField.VARBINARY_TYPE
1030: DBField.VARCHAR_TYPE
1031: */
1032:
1033: // integer types
1034: if (expressoFieldTypeString
1035: .equalsIgnoreCase(DBField.BIGINT_TYPE)
1036: || expressoFieldTypeString
1037: .equalsIgnoreCase(DBField.INTEGER_TYPE)
1038: || expressoFieldTypeString
1039: .equalsIgnoreCase(DBField.INT_TYPE)
1040: || expressoFieldTypeString
1041: .equalsIgnoreCase(DBField.LONG_TYPE)
1042: || expressoFieldTypeString
1043: .equalsIgnoreCase(DBField.SMALLINT_TYPE)
1044: || expressoFieldTypeString
1045: .equalsIgnoreCase(DBField.TINYINT_TYPE)) {
1046: Pattern p;
1047: try {
1048: p = patternCompiler.compile(INT_MASK,
1049: Perl5Compiler.READ_ONLY_MASK);
1050: } catch (MalformedPatternException mpe) {
1051: throw new DBException(mpe);
1052: }
1053: setMask(p);
1054: // TODO not i18n
1055: setAttribute(ATTRIBUTE_ERROR_MESSAGE,
1056: "You must enter a valid integer for field '"
1057: + description + "'");
1058: }
1059: // decimal types
1060: else if (expressoFieldTypeString
1061: .equalsIgnoreCase(DBField.DECIMAL_TYPE)
1062: || expressoFieldTypeString
1063: .equalsIgnoreCase(DBField.DOUBLE_TYPE)
1064: || expressoFieldTypeString
1065: .equalsIgnoreCase(DBField.FLOAT_TYPE)
1066: || expressoFieldTypeString
1067: .equalsIgnoreCase(DBField.NUMERIC_TYPE)
1068: || expressoFieldTypeString
1069: .equalsIgnoreCase(DBField.REAL_TYPE)) {
1070:
1071: Pattern p;
1072: try {
1073: p = patternCompiler.compile(FLOAT_MASK,
1074: Perl5Compiler.READ_ONLY_MASK);
1075: } catch (MalformedPatternException mpe) {
1076: throw new DBException(mpe);
1077: }
1078: setMask(p);
1079: //TODO not i18n
1080: setAttribute(ATTRIBUTE_ERROR_MESSAGE,
1081: "You must enter a valid decimal for field '"
1082: + description + "'");
1083: }
1084: // boolean types
1085: else if (expressoFieldTypeString
1086: .equalsIgnoreCase(DBField.BIT_TYPE)
1087: || expressoFieldTypeString
1088: .equalsIgnoreCase(DBField.BOOLEAN_TYPE)) {
1089:
1090: Pattern p;
1091: try {
1092: p = patternCompiler.compile(BOOLEAN_MASK,
1093: Perl5Compiler.READ_ONLY_MASK);
1094: } catch (MalformedPatternException mpe) {
1095: throw new DBException(mpe);
1096: }
1097: setMask(p);
1098: // TODO not i18n
1099: setAttribute(ATTRIBUTE_ERROR_MESSAGE,
1100: "You must enter a valid boolean for field '"
1101: + description + "'");
1102: }
1103: // date types
1104: else if (expressoFieldTypeString
1105: .equalsIgnoreCase(DBField.DATETIME_TYPE)
1106: || expressoFieldTypeString
1107: .equalsIgnoreCase(DBField.DATE_TYPE)
1108: || expressoFieldTypeString
1109: .equalsIgnoreCase(DBField.TIMESTAMP_TYPE)
1110: || expressoFieldTypeString
1111: .equalsIgnoreCase(DBField.TIME_TYPE)) {
1112:
1113: Pattern p;
1114: try {
1115: p = patternCompiler.compile(DATE_MASK,
1116: Perl5Compiler.READ_ONLY_MASK);
1117: } catch (MalformedPatternException mpe) {
1118: throw new DBException(mpe);
1119: }
1120: setMask(p);
1121: // TODO not i18n
1122: setAttribute(ATTRIBUTE_ERROR_MESSAGE,
1123: "You must enter a valid date for field '"
1124: + description + "'");
1125: }
1126: }
1127:
1128: /**
1129: * Get the compiled regular expression for this field.
1130: *
1131: * @return the precompiled regular expression mask
1132: */
1133: public Pattern getMask() {
1134: return mask;
1135: }
1136:
1137: /**
1138: * Removes an attribute from this Field object.
1139: *
1140: * @param attribName The name of the attribute to remove from this field.
1141: */
1142: public synchronized void removeAttribute(String attribName) {
1143: if (attributes == null) {
1144: return;
1145: }
1146:
1147: attributes.remove(attribName);
1148: }
1149:
1150: /**
1151: * Sets an attribute for this particular field.
1152: *
1153: * @param attribName the name of the attribute
1154: * @param attribValue the value of the attribute by this name
1155: */
1156: public synchronized void setAttribute(String attribName,
1157: Object attribValue) {
1158: if (attributes == null) {
1159: attributes = new Hashtable();
1160: }
1161:
1162: attributes.put(attribName, attribValue);
1163: }
1164:
1165: /**
1166: * Returns an attribute keyed by name. An attribute is an arbitrary object
1167: * you can associate with a particular db field.
1168: *
1169: * @param attribName the name of the attribute to get
1170: * @return java.lang.Object the object associated with this attribute name
1171: */
1172: public Object getAttribute(String attribName) {
1173: if (attributes == null) {
1174: return null;
1175: }
1176:
1177: return attributes.get(attribName);
1178: }
1179:
1180: /**
1181: * Returns a copy of all attributes associated with this field.
1182: *
1183: * @return a valid Iterator to a HashMap OR null if no attributes exist for
1184: * this field
1185: */
1186: public Iterator getAttributesIterator() {
1187: if (attributes == null) {
1188: return null;
1189: }
1190:
1191: return new HashMap(attributes).keySet().iterator();
1192: }
1193:
1194: /**
1195: * Retrieves all attribute names for this particular data field's metadata
1196: *
1197: * @return java.util.Set
1198: */
1199: public java.util.Set getAllAttributes() {
1200: if (attributes == null) {
1201: return null;
1202: }
1203:
1204: return new HashMap(attributes).keySet();
1205: }
1206:
1207: /**
1208: * Reads the Field object from a serialization stream.
1209: *
1210: * @param stream The object input stream from which to create this object
1211: */
1212: private void readObject(ObjectInputStream stream)
1213: throws IOException, ClassNotFoundException {
1214: if (logCat == null) {
1215: logCat = Logger.getLogger(DBField.class);
1216: }
1217:
1218: stream.defaultReadObject();
1219: }
1220:
1221: /**
1222: * getter for Filter Class
1223: * used in conjuction with get/setFilterMethod
1224: *
1225: * @return class for current filter; NULL if not explicitly set; NULL implies using standard filter
1226: * @see #getFilterMethod
1227: */
1228: public Class getFilterClass() {
1229: return mFilterClass;
1230: }
1231:
1232: /**
1233: * Set's the name of the filter class to be used
1234: * used in conjuction with get/setFilterMethod
1235: *
1236: * @param filterClass The class of the filter method to use.
1237: * @see #setFilterMethod
1238: * @see com.jcorporate.expresso.core.security.filters.FilterManager
1239: */
1240: public void setFilterClass(Class filterClass) throws DBException {
1241:
1242: mFilterClass = filterClass;
1243: }
1244:
1245: /**
1246: * Return boolean if the field has a mask set
1247: *
1248: * @return True if the field mask is set, else false if it is not
1249: */
1250: public boolean isMasked() {
1251: return mask != null;
1252: } /* isMasked() */
1253:
1254: } /* DBField */
|