0001: ///////////////////////////////
0002: // Makumba, Makumba tag library
0003: // Copyright (C) 2000-2003 http://www.makumba.org
0004: //
0005: // This library is free software; you can redistribute it and/or
0006: // modify it under the terms of the GNU Lesser General Public
0007: // License as published by the Free Software Foundation; either
0008: // version 2.1 of the License, or (at your option) any later version.
0009: //
0010: // This library is distributed in the hope that it will be useful,
0011: // but WITHOUT ANY WARRANTY; without even the implied warranty of
0012: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013: // Lesser General Public License for more details.
0014: //
0015: // You should have received a copy of the GNU Lesser General Public
0016: // License along with this library; if not, write to the Free Software
0017: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0018: //
0019: // -------------
0020: // $Id: FieldInfo.java 1538 2007-09-14 11:11:39Z manuel_gay $
0021: // $Name$
0022: /////////////////////////////////////
0023:
0024: //TODO extra comments about changes from refactoring
0025:
0026: package org.makumba.providers.datadefinition.makumba;
0027:
0028: import java.util.ArrayList;
0029: import java.util.Calendar;
0030: import java.util.Collection;
0031: import java.util.Collections;
0032: import java.util.Date;
0033: import java.util.Dictionary;
0034: import java.util.Enumeration;
0035: import java.util.GregorianCalendar;
0036: import java.util.Hashtable;
0037: import java.util.Iterator;
0038: import java.util.Vector;
0039:
0040: import org.apache.commons.collections.bidimap.DualHashBidiMap;
0041: import org.makumba.DataDefinition;
0042: import org.makumba.FieldDefinition;
0043: import org.makumba.InvalidValueException;
0044: import org.makumba.Pointer;
0045: import org.makumba.Text;
0046: import org.makumba.ValidationRule;
0047:
0048: /**
0049: * This is a structure containing the elementary data about a field: name, type, attributes, description, and other
0050: * type-specific extra info. All this information is available through the associated <a
0051: * href=org.makumba.abstr.FieldHandler.html#_top_>FieldHandler </a>
0052: */
0053: public class FieldInfo implements java.io.Serializable, FieldDefinition {
0054:
0055: private static final long serialVersionUID = 1L;
0056:
0057: DataDefinition dd;
0058:
0059: static final DualHashBidiMap integerTypeMap = new DualHashBidiMap();
0060:
0061: public DataDefinition getDataDefinition() {
0062: return dd;
0063: }
0064:
0065: // TODO adapt setIntEnum and setCharEnum in FieldDefinition
0066: public static FieldInfo getFieldInfo(String name, Object type,
0067: boolean typeSearch) {
0068: if (type instanceof FieldInfo)
0069: return new FieldInfo(name, (FieldInfo) type);
0070: String t = ((String) type).trim();
0071:
0072: if (!typeSearch || t.indexOf(" ") == -1)
0073: return new FieldInfo(name, t);
0074:
0075: t = name + "=" + t;
0076:
0077: return (FieldInfo) new RecordParser().parse(t)
0078: .getFieldDefinition(name);
0079: }
0080:
0081: public static FieldInfo getFieldInfo(String name, Object type,
0082: boolean typeSearch, String description) {
0083: FieldInfo a = getFieldInfo(name, type, typeSearch);
0084: a.description = description;
0085:
0086: return a;
0087: }
0088:
0089: public FieldInfo(DataDefinition ri, String name) {
0090: this .dd = ri;
0091: this .name = name;
0092: }
0093:
0094: public FieldInfo(FieldInfo fi) {
0095: this (fi.dd, fi.name);
0096: type = fi.type;
0097: fixed = fi.fixed;
0098: notNull = fi.notNull;
0099: unique = fi.unique;
0100: defaultValue = fi.defaultValue;
0101: description = fi.description;
0102: }
0103:
0104: /** for temporary field info */
0105: public FieldInfo(String name, FieldInfo fi) {
0106: this .name = name;
0107: type = fi.type;
0108: fixed = fi.fixed;
0109: notNull = fi.notNull;
0110: unique = fi.unique;
0111: defaultValue = fi.defaultValue;
0112: description = fi.description;
0113: extra1 = fi.extra1;
0114: extra2 = fi.extra2;
0115: extra3 = fi.extra3;
0116: if (type.equals("ptrIndex")) {
0117: type = "ptr";
0118: extra1 = fi.getDataDefinition();
0119: }
0120: validationRules = fi.validationRules;
0121: }
0122:
0123: public FieldInfo(String name, String t) {
0124: try {
0125: this .name = name;
0126: this .type = t;
0127: fixed = false;
0128: notNull = false;
0129: unique = false;
0130: if (type.equals("char"))
0131: extra2 = new Integer(255);
0132: else if (type.startsWith("char")) {
0133: int n = type.indexOf("[");
0134: int m = type.indexOf("]");
0135: if (!type.endsWith("]")
0136: || type.substring(3, n).trim().length() > 1)
0137: throw new InvalidValueException(
0138: "invalid char type " + type);
0139:
0140: extra2 = new Integer(Integer.parseInt(type.substring(
0141: n + 1, m)));
0142: type = "char";
0143: }
0144: } catch (StringIndexOutOfBoundsException e) {
0145: throw new InvalidValueException("bad type " + type);
0146: } catch (NumberFormatException f) {
0147: throw new InvalidValueException("bad char[] size " + type);
0148: }
0149: }
0150:
0151: static {
0152: integerTypeMap.put("ptr", new Integer(FieldDefinition._ptr));
0153: integerTypeMap.put("ptrRel", new Integer(
0154: FieldDefinition._ptrRel));
0155: integerTypeMap.put("ptrOne", new Integer(
0156: FieldDefinition._ptrOne));
0157: integerTypeMap.put("ptrIndex", new Integer(
0158: FieldDefinition._ptrIndex));
0159: integerTypeMap.put("int", new Integer(FieldDefinition._int));
0160: integerTypeMap.put("intEnum", new Integer(
0161: FieldDefinition._intEnum));
0162: integerTypeMap.put("char", new Integer(FieldDefinition._char));
0163: integerTypeMap.put("charEnum", new Integer(
0164: FieldDefinition._charEnum));
0165: integerTypeMap.put("text", new Integer(FieldDefinition._text));
0166: integerTypeMap.put("binary", new Integer(
0167: FieldDefinition._binary));
0168: integerTypeMap.put("date", new Integer(FieldDefinition._date));
0169: integerTypeMap.put("dateCreate", new Integer(
0170: FieldDefinition._dateCreate));
0171: integerTypeMap.put("dateModify", new Integer(
0172: FieldDefinition._dateModify));
0173: integerTypeMap.put("set", new Integer(FieldDefinition._set));
0174: integerTypeMap.put("setComplex", new Integer(
0175: FieldDefinition._setComplex));
0176: integerTypeMap.put("nil", new Integer(FieldDefinition._nil));
0177: integerTypeMap.put("real", new Integer(FieldDefinition._real));
0178: integerTypeMap.put("setcharEnum", new Integer(
0179: FieldDefinition._setCharEnum));
0180: integerTypeMap.put("setintEnum", new Integer(
0181: FieldDefinition._setIntEnum));
0182: }
0183:
0184: public static String getStringType(int integerType) {
0185: return (String) integerTypeMap.getKey(new Integer(integerType));
0186: }
0187:
0188: public boolean isAssignableFrom(FieldDefinition fi) {
0189: switch (getIntegerType()) {
0190: case FieldDefinition._int:
0191: return is_int_AssignableFrom(fi);
0192: case FieldDefinition._intEnum:
0193: return is_intEnum_AssignableFrom(fi);
0194: case FieldDefinition._ptr:
0195: case FieldDefinition._ptrRel:
0196: return is_ptrRel_AssignableFrom(fi);
0197: case FieldDefinition._real:
0198: return is_real_AssignableFrom(fi);
0199: case FieldDefinition._set:
0200: return is_set_AssignableFrom(fi);
0201: default:
0202: return base_isAssignableFrom(fi);
0203: }
0204: }
0205:
0206: // Original from FieldHandler
0207: public boolean base_isAssignableFrom(FieldDefinition fi) {
0208: return fi.getType().equals("nil")
0209: || getType().equals(fi.getType());
0210: }
0211:
0212: // moved from intHandler
0213: public boolean is_int_AssignableFrom(FieldDefinition fi) {
0214: return base_isAssignableFrom(fi)
0215: || fi.getType().equals("intEnum");
0216: }
0217:
0218: // moved from IntEnumHandler
0219: public boolean is_intEnum_AssignableFrom(FieldDefinition fi) {
0220: return is_int_AssignableFrom(fi) || fi.getType().equals("int")
0221: || fi.getType().equals("char");
0222: }
0223:
0224: // moved from ptrRelHandler
0225: public boolean is_ptrRel_AssignableFrom(FieldDefinition fi) {
0226: return "nil".equals(fi.getType())
0227: || getType().equals(fi.getType())
0228: && ((FieldInfo) fi).extra1 instanceof DataDefinition
0229: && ((DataDefinition) ((FieldInfo) fi).extra1).getName()
0230: .equals(getForeignTable().getName());
0231: }
0232:
0233: // moved from realHandler
0234: public boolean is_real_AssignableFrom(FieldDefinition fi) {
0235: return base_isAssignableFrom(fi)
0236: || fi.getType().equals("intEnum")
0237: || fi.getType().equals("int");
0238: }
0239:
0240: // moved from setHandler
0241: public boolean is_set_AssignableFrom(FieldDefinition fi) {
0242: return "nil".equals(fi.getType())
0243: || getType().equals(fi.getType())
0244: && getForeignTable().getName().equals(
0245: fi.getForeignTable().getName());
0246: }
0247:
0248: public String toString() {
0249: return getType();
0250: }
0251:
0252: String name;
0253:
0254: String type;
0255:
0256: boolean fixed;
0257:
0258: boolean notNull;
0259:
0260: boolean unique;
0261:
0262: Object defaultValue;
0263:
0264: String description;
0265:
0266: // those fields are only used by some types
0267: Object extra1, extra2, extra3;
0268:
0269: private Hashtable<String, ValidationRule> validationRules = new Hashtable<String, ValidationRule>();
0270:
0271: /** check if the value can be assigned */
0272: public Object checkValue(Object value) {
0273: switch (getIntegerType()) {
0274: case FieldDefinition._setIntEnum:
0275: return check_setintEnum_Value(value);
0276: default:
0277: return base_checkValue(value);
0278: }
0279: }
0280:
0281: // Original from FieldHandler
0282: /** check if the value can be assigned */
0283: public Object base_checkValue(Object value) {
0284: if (!value.equals(getNull()))
0285: return checkValueImpl(value);
0286: return value;
0287: }
0288:
0289: // moved from setintEnumHandler
0290: public Object check_setintEnum_Value(Object value) {
0291: try {
0292: // may be just an Integer
0293: Object o = getEnum().checkValue(value);
0294: Vector<Object> v = new Vector<Object>();
0295: if (o != null && o instanceof Integer)
0296: v.addElement(o);
0297: return v;
0298: } catch (org.makumba.InvalidValueException ive) {
0299: }
0300:
0301: normalCheck(value);
0302: Vector<Object> v = (Vector) value;
0303:
0304: for (int i = 0; i < v.size(); i++) {
0305: if (v.elementAt(i) == null
0306: || v.elementAt(i).equals(
0307: org.makumba.Pointer.NullInteger))
0308: throw new org.makumba.InvalidValueException(this ,
0309: "set members cannot be null");
0310: v.setElementAt(getEnum().checkValue(v.elementAt(i)), i);
0311: }
0312: return v;
0313: }
0314:
0315: /** check if the value can be assigned */
0316: public void checkInsert(Dictionary d) {
0317: Object o = d.get(getName());
0318: if (isNotNull() && (o == null || o.equals(getNull())))
0319: throw new org.makumba.InvalidValueException(this ,
0320: ERROR_NOT_NULL);
0321: if (o != null)
0322: d.put(getName(), checkValue(o));
0323: }
0324:
0325: /** check if the value can be assigned */
0326: public void checkUpdate(Dictionary d) {
0327: Object o = d.get(getName());
0328: if (o == null)
0329: return;
0330: if (isFixed())
0331: throw new org.makumba.InvalidValueException(this ,
0332: "You cannot update a fixed field");
0333: d.put(getName(), checkValue(o));
0334: }
0335:
0336: /**
0337: * Get deprecated values of the enumerator, works only for intEnum type.
0338: *
0339: * @return <code>Vector</code>, or <code>null</code> if called on other types
0340: */
0341: public Vector getDeprecatedValues() {
0342: switch (getIntegerType()) {
0343: case FieldDefinition._intEnum:
0344: return get_intEnum_DeprecatedValues();
0345: default:
0346: return null;
0347: }
0348: }
0349:
0350: // moved from intEnumHandler
0351: public Vector get_intEnum_DeprecatedValues() {
0352: return (Vector) this .extra3;
0353: }
0354:
0355: /**
0356: * the value returned in case there is no value in the database and no default value is indicated
0357: */
0358: public Object getEmptyValue() {
0359: switch (getIntegerType()) {
0360: case FieldDefinition._char:
0361: case FieldDefinition._charEnum:
0362: case FieldDefinition._text:
0363: case FieldDefinition._binary:
0364: return "";
0365: case FieldDefinition._date:
0366: case FieldDefinition._dateCreate:
0367: case FieldDefinition._dateModify:
0368: return emptyDate;
0369: case FieldDefinition._int:
0370: case FieldDefinition._intEnum:
0371: return emptyInt;
0372: case FieldDefinition._real:
0373: return emptyReal;
0374: default:
0375: return null;
0376: }
0377: }
0378:
0379: public Object getNull() {
0380:
0381: switch (getIntegerType()) {
0382: case FieldDefinition._char:
0383: case FieldDefinition._charEnum:
0384: return Pointer.NullString;
0385: case FieldDefinition._date:
0386: case FieldDefinition._dateCreate:
0387: case FieldDefinition._dateModify:
0388: return Pointer.NullDate;
0389: case FieldDefinition._int:
0390: case FieldDefinition._intEnum:
0391: return Pointer.NullInteger;
0392: case FieldDefinition._ptr:
0393: case FieldDefinition._ptrIndex:
0394: case FieldDefinition._ptrOne:
0395: case FieldDefinition._ptrRel:
0396: case FieldDefinition._setComplex:
0397: return Pointer.Null;
0398: case FieldDefinition._real:
0399: return Pointer.NullReal;
0400: case FieldDefinition._set:
0401: case FieldDefinition._setCharEnum:
0402: case FieldDefinition._setIntEnum:
0403: return Pointer.NullSet;
0404: case FieldDefinition._text:
0405: case FieldDefinition._binary:
0406: return Pointer.NullText;
0407: default:
0408: throw new RuntimeException("Shouldn't be here");
0409: }
0410: }
0411:
0412: // moved from dateHandler
0413: static final Date emptyDate;
0414:
0415: static {
0416: Calendar c = new GregorianCalendar(org.makumba.MakumbaSystem
0417: .getTimeZone());
0418: c.clear();
0419: c.set(1900, 0, 1);
0420: emptyDate = c.getTime();
0421: }
0422:
0423: // moved from intHandler
0424: static final Object emptyInt = new Integer(0);
0425:
0426: // moved from realHandler
0427: static final Object emptyReal = new Double(0d);
0428:
0429: /** the name of this handler, normally the same with the name of the field */
0430: public String getName() {
0431: return getDataName();
0432: }
0433:
0434: /** the data field this handler is associated to */
0435: public final String getDataName() {
0436: return name;
0437: }
0438:
0439: /** tells wether this field has a description originally */
0440: public boolean hasDescription() {
0441: return !description.equals(name);
0442: }
0443:
0444: /**
0445: * returns field's description, if present. If not present (null or "") it returns field name.
0446: */
0447: public String getDescription() {
0448: if (description == null)
0449: return name;
0450: if (description.trim().equals(""))
0451: return name;
0452: return description;
0453: }
0454:
0455: /** returns field's type */
0456: public String getType() {
0457: return type;
0458: }
0459:
0460: /** returns field type's integer value */
0461: public int getIntegerType() {
0462: return ((Integer) integerTypeMap.get(getType())).intValue();
0463: }
0464:
0465: // should be set while parsing
0466: // intEnum has int, set has null, etc
0467: public String getDataType() {
0468: switch (getIntegerType()) {
0469: case FieldDefinition._char:
0470: case FieldDefinition._charEnum:
0471: return "char";
0472: case FieldDefinition._date:
0473: return "datetime";
0474: case FieldDefinition._dateCreate:
0475: case FieldDefinition._dateModify:
0476: return "timestamp";
0477: case FieldDefinition._int:
0478: case FieldDefinition._intEnum:
0479: return "int";
0480: case FieldDefinition._ptr:
0481: case FieldDefinition._ptrIndex:
0482: case FieldDefinition._ptrOne:
0483: case FieldDefinition._ptrRel:
0484: return "pointer";
0485: case FieldDefinition._real:
0486: return "real";
0487: case FieldDefinition._set:
0488: return "set";
0489: case FieldDefinition._setCharEnum:
0490: return "setchar";
0491: case FieldDefinition._setComplex:
0492: return "null";
0493: case FieldDefinition._setIntEnum:
0494: return "setint";
0495: case FieldDefinition._text:
0496: return "text";
0497: case FieldDefinition._binary:
0498: return "binary";
0499: default:
0500: throw new RuntimeException("Shouldn't be here");
0501: }
0502: }
0503:
0504: // intEnum has int, set has null, etc
0505: public Class getJavaType() {
0506: switch (getIntegerType()) {
0507: case FieldDefinition._char:
0508: case FieldDefinition._charEnum:
0509: return java.lang.String.class;
0510: case FieldDefinition._date:
0511: case FieldDefinition._dateCreate:
0512: case FieldDefinition._dateModify:
0513: return java.util.Date.class;
0514: case FieldDefinition._int:
0515: case FieldDefinition._intEnum:
0516: return java.lang.Integer.class;
0517: case FieldDefinition._ptr:
0518: case FieldDefinition._ptrIndex:
0519: case FieldDefinition._ptrOne:
0520: case FieldDefinition._ptrRel:
0521: return Pointer.class;
0522: case FieldDefinition._real:
0523: return java.lang.Double.class;
0524: case FieldDefinition._set:
0525: case FieldDefinition._setCharEnum:
0526: case FieldDefinition._setIntEnum:
0527: return java.util.Vector.class;
0528: case FieldDefinition._setComplex:
0529: return null;
0530: case FieldDefinition._text:
0531: case FieldDefinition._binary:
0532: return org.makumba.Text.class;
0533: default:
0534: throw new RuntimeException("Shouldn't be here");
0535: }
0536: }
0537:
0538: /** tells wether this field is fixed */
0539: public boolean isFixed() {
0540: return fixed;
0541: }
0542:
0543: /** tells wether this field is not null */
0544: public boolean isNotNull() {
0545: return notNull;
0546: }
0547:
0548: /** tells wether this field is unique */
0549: public boolean isUnique() {
0550: return unique;
0551: }
0552:
0553: /** returns the defa()ult value of this field */
0554: public Object getDefaultValue() {
0555: if (defaultValue == null)
0556: return getEmptyValue();
0557: return defaultValue;
0558: }
0559:
0560: /**
0561: * works only for intEnum, charEnum, setintEnum, setcharEnum types
0562: */
0563: public Enumeration getValues() {
0564: switch (getIntegerType()) {
0565: case FieldDefinition._charEnum:
0566: case FieldDefinition._intEnum:
0567: return ((Vector) this .extra1).elements();
0568: case FieldDefinition._setCharEnum:
0569: case FieldDefinition._setIntEnum:
0570: return ((Vector) getEnum().extra1).elements();
0571: default:
0572: throw new RuntimeException("Shouldn't be here");
0573: }
0574: }
0575:
0576: /**
0577: * works only for intEnum, charEnum, setintEnum, setcharEnum types
0578: */
0579: public Enumeration getNames() {
0580: switch (getIntegerType()) {
0581: case FieldDefinition._charEnum:
0582: case FieldDefinition._intEnum:
0583: return ((Vector) this .extra2).elements();
0584: case FieldDefinition._setCharEnum:
0585: case FieldDefinition._setIntEnum:
0586: return ((Vector) getEnum().extra2).elements();
0587: default:
0588: throw new RuntimeException("Shouldn't be here");
0589: }
0590: }
0591:
0592: /**
0593: * works only for intEnum, charEnum, setintEnum, setcharEnum types
0594: */
0595: public int getEnumeratorSize() {
0596: switch (getIntegerType()) {
0597: case FieldDefinition._charEnum:
0598: case FieldDefinition._intEnum:
0599: return ((Vector) this .extra1).size();
0600: case FieldDefinition._setCharEnum:
0601: case FieldDefinition._setIntEnum:
0602: return ((Vector) getEnum().extra1).size();
0603: default:
0604: throw new RuntimeException("Shouldn't be here");
0605: }
0606: }
0607:
0608: /**
0609: * works only for intEnum, charEnum, setintEnum, setcharEnum types
0610: */
0611: public String getStringAt(int i) {
0612: switch (getIntegerType()) {
0613: case FieldDefinition._charEnum:
0614: case FieldDefinition._intEnum:
0615: return ((Vector) this .extra1).elementAt(i).toString();
0616: case FieldDefinition._setCharEnum:
0617: case FieldDefinition._setIntEnum:
0618: return ((Vector) getEnum().extra1).elementAt(i).toString();
0619: default:
0620: throw new RuntimeException("Shouldn't be here");
0621: }
0622: }
0623:
0624: /**
0625: * works only for intEnum type
0626: */
0627: public String getNameFor(int i) {
0628: switch (getIntegerType()) {
0629: case FieldDefinition._intEnum:
0630: return get_intEnum_NameFor(i);
0631: default:
0632: throw new RuntimeException("Shouldn't be here");
0633: }
0634: }
0635:
0636: // moved from intEnumHandler
0637: public String get_intEnum_NameFor(int n) {
0638: Vector names = (Vector) this .extra2;
0639: Vector values = (Vector) this .extra1;
0640: for (int i = 0; i < values.size(); i++)
0641: if (values.elementAt(i).equals(new Integer(n)))
0642: return (String) names.elementAt(i);
0643: throw new org.makumba.InvalidValueException(this ,
0644: "Can't find a name for " + n + " in " + values
0645: + " with names " + names);
0646: }
0647:
0648: /**
0649: * works only for intEnum, charEnum, setintEnum, setcharEnum types
0650: */
0651: public String getNameAt(int i) {
0652: switch (getIntegerType()) {
0653: case FieldDefinition._charEnum:
0654: return (String) ((Vector) this .extra1).elementAt(i);
0655: case FieldDefinition._intEnum:
0656: return (String) ((Vector) this .extra2).elementAt(i);
0657: case FieldDefinition._setCharEnum:
0658: return (String) ((Vector) getEnum().extra1).elementAt(i);
0659: case FieldDefinition._setIntEnum:
0660: return (String) ((Vector) getEnum().extra2).elementAt(i);
0661: default:
0662: throw new RuntimeException("Shouldn't be here");
0663: }
0664: }
0665:
0666: /**
0667: * works only for int, intEnum, setintEnum types
0668: */
0669: public int getDefaultInt() {
0670: switch (getIntegerType()) {
0671: case FieldDefinition._int:
0672: case FieldDefinition._intEnum:
0673: return ((Integer) getDefaultValue()).intValue();
0674: case FieldDefinition._setIntEnum:
0675: return ((Integer) getEnum().defaultValue).intValue();
0676: default:
0677: throw new RuntimeException("Shouldn't be here");
0678: }
0679: }
0680:
0681: /**
0682: * works only for intEnum, setintEnum types
0683: */
0684: public int getIntAt(int i) {
0685: switch (getIntegerType()) {
0686: case FieldDefinition._intEnum:
0687: return ((Integer) ((Vector) this .extra1).elementAt(i))
0688: .intValue();
0689: case FieldDefinition._setIntEnum:
0690: return ((Integer) ((Vector) getEnum().extra1).elementAt(i))
0691: .intValue();
0692: default:
0693: throw new RuntimeException("Shouldn't be here");
0694: }
0695: }
0696:
0697: /**
0698: * works only for char, text, binary, charEnum, setcharEnum types
0699: */
0700: public String getDefaultString() {
0701: switch (getIntegerType()) {
0702: case FieldDefinition._char:
0703: case FieldDefinition._charEnum:
0704: case FieldDefinition._text:
0705: case FieldDefinition._binary:
0706: return (String) getDefaultValue();
0707: case FieldDefinition._setCharEnum:
0708: return (String) getEnum().defaultValue;
0709: default:
0710: throw new RuntimeException("Shouldn't be here");
0711: }
0712: }
0713:
0714: /**
0715: * works only for char, charEnum, setcharEnum types
0716: */
0717: public int getWidth() {
0718: switch (getIntegerType()) {
0719: case FieldDefinition._char:
0720: case FieldDefinition._charEnum:
0721: return ((Integer) this .extra2).intValue();
0722: case FieldDefinition._setCharEnum:
0723: return ((Integer) getEnum().extra2).intValue();
0724: default:
0725: throw new RuntimeException("Shouldn't be here");
0726: }
0727: }
0728:
0729: // inserted 20050418
0730: public Object checkValueImpl(Object value) {
0731: switch (getIntegerType()) {
0732: case FieldDefinition._char:
0733: return check_char_ValueImpl(value);
0734: case FieldDefinition._charEnum:
0735: return check_charEnum_ValueImpl(value);
0736: case FieldDefinition._date:
0737: case FieldDefinition._dateCreate:
0738: case FieldDefinition._dateModify:
0739: return check_date_ValueImpl(value);
0740: case FieldDefinition._int:
0741: return check_int_ValueImpl(value);
0742: case FieldDefinition._intEnum:
0743: return check_intEnum_ValueImpl(value);
0744: case FieldDefinition._ptr:
0745: case FieldDefinition._ptrIndex:
0746: case FieldDefinition._ptrOne:
0747: case FieldDefinition._ptrRel:
0748: case FieldDefinition._setIntEnum:
0749: return check_ptrIndex_ValueImpl(value);
0750: case FieldDefinition._real:
0751: return check_real_ValueImpl(value);
0752: case FieldDefinition._set:
0753: return check_set_ValueImpl(value);
0754: case FieldDefinition._setCharEnum:
0755: return check_setcharEnum_ValueImpl(value);
0756: case FieldDefinition._setComplex:
0757: return check_setComplex_ValueImpl(value);
0758: case FieldDefinition._text:
0759: return check_text_ValueImpl(value);
0760: case FieldDefinition._binary:
0761: return check_binary_ValueImpl(value);
0762: default:
0763: throw new RuntimeException("Shouldn't be here");
0764: }
0765: }
0766:
0767: // moved from charHandler
0768: public Object check_char_ValueImpl(Object value) {
0769: normalCheck(value);
0770: String s = (String) value;
0771: if (s.length() > getWidth())
0772: throw new InvalidValueException(this ,
0773: "String too long for char[] field. Maximum width: "
0774: + getWidth() + " given width " + s.length()
0775: + ".\n\tGiven value <" + s + ">");
0776: return value;
0777: }
0778:
0779: // moved from charEnumHandler
0780: public Object check_charEnum_ValueImpl(Object value) {
0781: check_char_ValueImpl(value);
0782:
0783: Vector names = (Vector) this .extra1;
0784:
0785: for (int i = 0; i < names.size(); i++)
0786: if (names.elementAt(i).equals(value))
0787: return value;
0788: throw new org.makumba.InvalidValueException(this ,
0789: "value set to char enumerator (" + value
0790: + ") is not a member of " + names);
0791: }
0792:
0793: // moved from dateHandler
0794: public Object check_date_ValueImpl(Object value) {
0795: return normalCheck(value);
0796: }
0797:
0798: // moved from intHandler
0799: public Object check_int_ValueImpl(Object value) {
0800: return normalCheck(value);
0801: }
0802:
0803: // moved from intEnumHandler
0804: public Object check_intEnum_ValueImpl(Object value) {
0805: Vector names = (Vector) this .extra2;
0806: Vector values = (Vector) this .extra1;
0807: if (value instanceof Integer) {
0808: for (int i = 0; i < values.size(); i++)
0809: if (values.elementAt(i).equals(value))
0810: return value;
0811: throw new org.makumba.InvalidValueException(this ,
0812: "int value set to int enumerator (" + value
0813: + ") is not a member of " + values);
0814: }
0815: if (!(value instanceof String))
0816: throw new org.makumba.InvalidValueException(
0817: this ,
0818: "int enumerators only accept values of type Integer or String. Value supplied ("
0819: + value
0820: + ") is of type "
0821: + value.getClass().getName());
0822:
0823: for (int i = 0; i < names.size(); i++)
0824: if (names.elementAt(i).equals(value))
0825: return values.elementAt(i);
0826:
0827: throw new org.makumba.InvalidValueException(this ,
0828: "string value set to int enumerator (" + value
0829: + ") is neither a member of " + names
0830: + " nor amember of " + values);
0831: }
0832:
0833: // moved from ptrIndexHandler
0834: public Object check_ptrIndex_ValueImpl(Object value) {
0835: if (value instanceof Pointer) {
0836: if (!((Pointer) value).getType().equals(
0837: getPointedType().getName()))
0838: throw new InvalidValueException(this , getPointedType()
0839: .getName(), (Pointer) value);
0840: return value;
0841: }
0842: if (value instanceof String)
0843: return new Pointer(getPointedType().getName(),
0844: (String) value);
0845: throw new InvalidValueException(
0846: this ,
0847: "Only java.lang.String and org.makumba.Pointer (or a java.util.Vector containing elements of those types) are assignable to makumba pointers, given value <"
0848: + value
0849: + "> is of type "
0850: + value.getClass().getName());
0851: }
0852:
0853: // moved from realHandler
0854: public Object check_real_ValueImpl(Object value) {
0855: if (value instanceof Integer)
0856: return value;
0857: return normalCheck(value);
0858: }
0859:
0860: // moved from setHandler
0861: public Object check_set_ValueImpl(Object value) {
0862: try {
0863: // may be just a pointer
0864: Object o = check_ptrIndex_ValueImpl(value);
0865: Vector<Object> v = new Vector<Object>();
0866: if (o != null && o instanceof Pointer)
0867: v.addElement(o);
0868: return v;
0869: } catch (org.makumba.InvalidValueException ive) {
0870: }
0871:
0872: normalCheck(value);
0873:
0874: Vector<Object> v = (Vector) value;
0875:
0876: FieldDefinition ptr = getForeignTable().getFieldDefinition(
0877: getForeignTable().getIndexPointerFieldName());
0878:
0879: for (int i = 0; i < v.size(); i++) {
0880: if (v.elementAt(i) == null
0881: || v.elementAt(i).equals(org.makumba.Pointer.Null))
0882: throw new org.makumba.InvalidValueException(this ,
0883: "set members cannot be null");
0884: try {
0885: v.setElementAt(ptr.checkValue(v.elementAt(i)), i);
0886: } catch (org.makumba.InvalidValueException e) {
0887: throw new org.makumba.InvalidValueException(
0888: this ,
0889: "the set member <"
0890: + v.elementAt(i)
0891: + "> is not assignable to pointers of type "
0892: + getForeignTable().getName());
0893: }
0894: }
0895: return v;
0896: }
0897:
0898: // moved from setcharEnumHandler
0899: public Object check_setcharEnum_ValueImpl(Object value) {
0900: try {
0901: Object o = getEnum().checkValue(value);
0902: Vector<Object> v = new Vector<Object>();
0903: if (o != null && o instanceof String)
0904: v.addElement(o);
0905: return v;
0906: } catch (org.makumba.InvalidValueException ive) {
0907: }
0908:
0909: normalCheck(value);
0910:
0911: Vector<Object> v = (Vector) value;
0912:
0913: for (int i = 0; i < v.size(); i++) {
0914: if (v.elementAt(i) == null
0915: || v.elementAt(i).equals(
0916: org.makumba.Pointer.NullString))
0917: throw new org.makumba.InvalidValueException(this ,
0918: "set members cannot be null");
0919: v.setElementAt(getEnum().checkValue(v.elementAt(i)), i);
0920: }
0921: return v;
0922: }
0923:
0924: // moved from setComplexHandler
0925: public Object check_setComplex_ValueImpl(Object value) {
0926: throw new org.makumba.InvalidValueException(this ,
0927: "subsets cannot be assigned directly");
0928: }
0929:
0930: // moved from textHandler
0931: public Object check_text_ValueImpl(Object value) {
0932: try {
0933: return Text.getText(value);
0934: } catch (InvalidValueException e) {
0935: throw new InvalidValueException(this , e.getMessage());
0936: }
0937: }
0938:
0939: // moved from textHandler
0940: public Object check_binary_ValueImpl(Object value) {
0941: try {
0942: return Text.getText(value);
0943: } catch (InvalidValueException e) {
0944: throw new InvalidValueException(this , e.getMessage());
0945: }
0946: }
0947:
0948: // moved from setcharEnumHandler and setintEnumHandler
0949: FieldInfo getEnum() {
0950: return (FieldInfo) ((DataDefinition) this .extra1)
0951: .getFieldDefinition("enum");
0952: }
0953:
0954: // moved from ptrOneHandler
0955: public DataDefinition get_ptrOne_Subtable() {
0956: return (DataDefinition) this .extra1;
0957: }
0958:
0959: /**
0960: * works only for date type
0961: */
0962: public Date getDefaultDate() {
0963: switch (getIntegerType()) {
0964: case FieldDefinition._date:
0965: case FieldDefinition._dateCreate:
0966: case FieldDefinition._dateModify:
0967: return (Date) getDefaultValue();
0968: default:
0969: throw new RuntimeException("Shouldn't be here");
0970: }
0971: }
0972:
0973: /**
0974: * works only for ptr, ptrRel and set types
0975: */
0976: public DataDefinition getForeignTable() {
0977: switch (getIntegerType()) {
0978: case FieldDefinition._ptr:
0979: case FieldDefinition._ptrRel:
0980: return get_ptrRel_ForeignTable();
0981: case FieldDefinition._set:
0982: return get_set_ForeignTable();
0983: default:
0984: throw new RuntimeException("Shouldn't be here");
0985: }
0986: }
0987:
0988: // moved from prtRelHandler
0989: public DataDefinition get_ptrRel_ForeignTable() {
0990: return (DataDefinition) this .extra1;
0991: }
0992:
0993: // moved from setHandler
0994: public DataDefinition get_set_ForeignTable() {
0995: if (this .extra3 == null) // automatic set
0996: return pointerToForeign().getForeignTable();
0997: else
0998: return (DataDefinition) this .extra3; // manually made
0999: }
1000:
1001: // moved from setHandler
1002: FieldDefinition pointerToForeign() {
1003: return getSubtable().getFieldDefinition(
1004: (String) getSubtable().getFieldNames().elementAt(4));
1005: }
1006:
1007: /**
1008: * works only for ptrOne, set, setComplex, setcharEnum and setintEnum types
1009: *
1010: * @return the subtable indicated in set or ptr definition
1011: */
1012: public DataDefinition getSubtable() {
1013: switch (getIntegerType()) {
1014: case FieldDefinition._ptrOne:
1015: case FieldDefinition._setCharEnum:
1016: case FieldDefinition._setComplex:
1017: case FieldDefinition._setIntEnum:
1018: return get_ptrOne_Subtable();
1019: case FieldDefinition._set:
1020: return get_set_Subtable();
1021: default:
1022: throw new RuntimeException("Shouldn't be here");
1023: }
1024: }
1025:
1026: // moved from setHandler
1027: public DataDefinition get_set_Subtable() {
1028: return (DataDefinition) this .extra1;
1029: }
1030:
1031: /**
1032: * works only for all pointer and set types
1033: */
1034: public DataDefinition getPointedType() {
1035: switch (getIntegerType()) {
1036: case FieldDefinition._ptrIndex:
1037: return get_ptrIndex_PointedType();
1038: case FieldDefinition._ptrOne:
1039: case FieldDefinition._setCharEnum:
1040: case FieldDefinition._setComplex:
1041: case FieldDefinition._setIntEnum:
1042: return get_ptrOne_PointedType();
1043: case FieldDefinition._ptrRel:
1044: case FieldDefinition._ptr:
1045: case FieldDefinition._set:
1046: return get_ptrRel_PointedType();
1047: default:
1048: throw new RuntimeException("Shouldn't be here");
1049: }
1050: }
1051:
1052: // moved from ptrIndexHandler
1053: public DataDefinition get_ptrIndex_PointedType() {
1054: return getDataDefinition();
1055: }
1056:
1057: // moved from ptrOneHandler
1058: public DataDefinition get_ptrOne_PointedType() {
1059: return getSubtable();
1060: }
1061:
1062: // moved from ptrRelHandler
1063: public DataDefinition get_ptrRel_PointedType() {
1064: return getForeignTable();
1065: }
1066:
1067: /**
1068: * works only for ptr and set types
1069: *
1070: * @return title field of the record in the foreign table, as indicated in this field definition or in the
1071: * respective foreign table record definition
1072: * @see #hasTitleFieldIndicated()
1073: */
1074: public String getTitleField() {
1075: switch (getIntegerType()) {
1076: case FieldDefinition._ptr:
1077: case FieldDefinition._set:
1078: return get_ptr_TitleField();
1079: default:
1080: throw new RuntimeException("Shouldn't be here");
1081: }
1082: }
1083:
1084: // moved from ptrHandler
1085: public String get_ptr_TitleField() {
1086: if (hasTitleFieldIndicated())
1087: return (String) this .extra2;
1088: return getForeignTable().getTitleFieldName();
1089: }
1090:
1091: /**
1092: * works only for ptr and set types
1093: *
1094: * @return wether the definition indicates a title field
1095: * @exception ClassCastException
1096: * for other types
1097: */
1098: public boolean hasTitleFieldIndicated() {
1099: switch (getIntegerType()) {
1100: case FieldDefinition._ptr:
1101: case FieldDefinition._set:
1102: return has_ptr_TitleFieldIndicated();
1103: default:
1104: throw new RuntimeException("Shouldn't be here");
1105: }
1106: }
1107:
1108: // moved from ptrHandler
1109: public boolean has_ptr_TitleFieldIndicated() {
1110: return this .extra2 != null;
1111: }
1112:
1113: // moved from FieldHandler
1114: protected Object normalCheck(Object value) {
1115: if (!getJavaType().isInstance(value))
1116: throw new org.makumba.InvalidValueException(this ,
1117: getJavaType(), value);
1118: return value;
1119: }
1120:
1121: public boolean isDefaultField() {
1122: return getIntegerType() == _ptrIndex
1123: || getIntegerType() == _dateCreate
1124: || getIntegerType() == _dateModify;
1125: }
1126:
1127: public boolean shouldEditBySingleInput() {
1128: return !(getIntegerType() == _ptrOne || getIntegerType() == _setComplex);
1129: }
1130:
1131: public boolean isDateType() {
1132: return getIntegerType() == _date
1133: || getIntegerType() == _dateCreate
1134: || getIntegerType() == _dateModify;
1135: }
1136:
1137: public boolean isIntegerType() {
1138: return getIntegerType() == _int;
1139: }
1140:
1141: public boolean isRealType() {
1142: return getIntegerType() == _real;
1143: }
1144:
1145: public boolean isNumberType() {
1146: return isIntegerType() || isRealType();
1147: }
1148:
1149: public boolean isSetType() {
1150: return getIntegerType() == _set || isInternalSet();
1151: }
1152:
1153: public boolean isEnumType() {
1154: return getIntegerType() == _intEnum
1155: || getIntegerType() == _charEnum;
1156: }
1157:
1158: public boolean isSetEnumType() {
1159: return getIntegerType() == _setIntEnum
1160: || getIntegerType() == _setCharEnum;
1161: }
1162:
1163: public boolean isStringType() {
1164: return getIntegerType() == _char
1165: || getIntegerType() == _intEnum;
1166: }
1167:
1168: public boolean isInternalSet() {
1169: return getIntegerType() == _setComplex
1170: || getIntegerType() == _setIntEnum
1171: || getIntegerType() == _setCharEnum;
1172: }
1173:
1174: public boolean isPointer() {
1175: return getIntegerType() == _ptr;
1176: }
1177:
1178: public boolean isExternalSet() {
1179: return getIntegerType() == _set;
1180: }
1181:
1182: public boolean isComplexSet() {
1183: return getIntegerType() == _setComplex;
1184: }
1185:
1186: public void addValidationRule(Collection rules) {
1187: if (rules != null) {
1188: for (Iterator iter = rules.iterator(); iter.hasNext();) {
1189: addValidationRule((ValidationRule) iter.next());
1190: }
1191: }
1192: }
1193:
1194: public void addValidationRule(ValidationRule rule) {
1195: validationRules.put(rule.getRuleName(), rule);
1196: }
1197:
1198: public Collection getValidationRules() {
1199: // we sort the rules, so that comparison rules come in the end
1200: ArrayList<ValidationRule> arrayList = new ArrayList<ValidationRule>(
1201: validationRules.values());
1202: Collections.sort(arrayList);
1203: return arrayList;
1204: }
1205: }
|