0001: package org.apache.ojb.broker.metadata;
0002:
0003: /* Copyright 2002-2005 The Apache Software Foundation
0004: *
0005: * Licensed under the Apache License, Version 2.0 (the "License");
0006: * you may not use this file except in compliance with the License.
0007: * You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: import java.io.Serializable;
0019: import java.lang.reflect.Constructor;
0020: import java.lang.reflect.Method;
0021: import java.lang.reflect.Modifier;
0022: import java.sql.Timestamp;
0023: import java.util.ArrayList;
0024: import java.util.Arrays;
0025: import java.util.Collection;
0026: import java.util.Collections;
0027: import java.util.HashMap;
0028: import java.util.Iterator;
0029: import java.util.List;
0030: import java.util.Map;
0031: import java.util.Vector;
0032:
0033: import org.apache.commons.lang.builder.ToStringBuilder;
0034: import org.apache.commons.lang.builder.ToStringStyle;
0035: import org.apache.ojb.broker.PersistenceBrokerException;
0036: import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
0037: import org.apache.ojb.broker.accesslayer.RowReader;
0038: import org.apache.ojb.broker.accesslayer.RowReaderDefaultImpl;
0039: import org.apache.ojb.broker.accesslayer.StatementsForClassFactory;
0040: import org.apache.ojb.broker.accesslayer.StatementsForClassIF;
0041: import org.apache.ojb.broker.core.ValueContainer;
0042: import org.apache.ojb.broker.locking.IsolationLevels;
0043: import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
0044: import org.apache.ojb.broker.util.ClassHelper;
0045: import org.apache.ojb.broker.util.SqlHelper;
0046: import org.apache.ojb.broker.util.configuration.Configuration;
0047: import org.apache.ojb.broker.util.configuration.Configurator;
0048: import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
0049: import org.apache.ojb.broker.util.logging.LoggerFactory;
0050:
0051: /**
0052: * A ClassDescriptor contains all information for mapping objects of a
0053: * given class to database tables.
0054: * <br>
0055: * Note: Be careful when use ClassDescriptor variables or caching
0056: * ClassDescriptor instances, because instances could become invalid
0057: * during runtime (see {@link MetadataManager}).
0058: *
0059: * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
0060: * @version $Id: ClassDescriptor.java,v 1.88.2.21 2005/12/21 22:26:10 tomdz Exp $
0061: */
0062: public final class ClassDescriptor extends DescriptorBase implements
0063: Serializable, XmlCapable, IsolationLevels {
0064: private String persistentFieldClassName;
0065:
0066: private static final long serialVersionUID = -5212253607374173965L;
0067:
0068: public static final String DYNAMIC_STR = "dynamic";
0069: public static final String OJB_CONCRETE_CLASS = "ojbConcreteClass";
0070: private static final Class[] NO_PARAMS = {};
0071:
0072: //---------------------------------------------------------------
0073: /**
0074: * The descriptor for the insert procedure/function.
0075: */
0076: private InsertProcedureDescriptor insertProcedure;
0077:
0078: //---------------------------------------------------------------
0079: /**
0080: * The descriptor for the update procedure/function.
0081: */
0082: private UpdateProcedureDescriptor updateProcedure;
0083:
0084: //---------------------------------------------------------------
0085: /**
0086: * The descriptor for the delete procedure/function.
0087: */
0088: private DeleteProcedureDescriptor deleteProcedure;
0089:
0090: //---------------------------------------------------------------
0091: // transient fields, to make this class serializable we have to declare
0092: // some transient fields and some associated string fields to reinitialze
0093: // transient fields after serialization
0094: //---------------------------------------------------------------
0095: /**
0096: * optional method to be invoked after instance fields are initialized
0097: */
0098: private transient Method initializationMethod;
0099: private String initializationMethodName;
0100:
0101: private transient Method factoryMethod;
0102: private String factoryMethodName;
0103: /**
0104: * whether we have already tried to look up the zero
0105: * argument constructor. Transient declared, because
0106: * {@link Constructor} is transient and we need to
0107: * reinitialize constructor after serialization.
0108: */
0109: private transient boolean alreadyLookedupZeroArguments = false;
0110: /**
0111: * the zero argument constructor for this class
0112: */
0113: private transient Constructor zeroArgumentConstructor = null;
0114:
0115: /**
0116: * used to signal use of ojbConcreteClass field
0117: */
0118: private transient boolean ojbConcreteFieldCheckDone = false;
0119: private transient FieldDescriptor ojbConcreteClassField;
0120: /**
0121: * We have to bound {@link org.apache.ojb.broker.accesslayer.StatementsForClassIF}
0122: * instance to this class, because metadata may change.
0123: */
0124: private transient StatementsForClassIF statementsForClass;
0125: //---------------------------------------------------------------
0126: // end transient fields
0127: //---------------------------------------------------------------
0128:
0129: private DescriptorRepository m_repository;
0130: /**
0131: * optional class.method to be invoked to create object instance. Both
0132: * of these must be present for this function to be successful.
0133: */
0134: private Class factoryClass;
0135: private int useIdentityColumn = 0;
0136:
0137: private String baseClass = null;
0138: /**
0139: * transaction isolation level specified for this class, used in the ODMG server
0140: */
0141: private int m_IsolationLevel;
0142: /**
0143: * the SQL SCHEMA of the underlying table of this class
0144: */
0145: private String schema = null;
0146: /**
0147: * the described class
0148: */
0149: private Class m_Class = null;
0150: /**
0151: * whether the described class is abstract
0152: */
0153: private boolean isAbstract = false;
0154: /**
0155: * the table name used to store the scalar attributes of this class
0156: */
0157: private String m_TableName = null;
0158: // private Vector superPersistentFieldDescriptors = null;
0159: /**
0160: * the RowReader for this class
0161: */
0162: private RowReader m_rowReader = null;
0163: /*
0164: arminw:
0165: TODO: this feature doesn't work, so remove/reuse this in future
0166: */
0167: /**
0168: * the class that this class extends
0169: */
0170: private String super Class;
0171: /**
0172: * reference column for the superclass
0173: */
0174: private int super ClassFieldRef;
0175: /**
0176: * does the described class represent an interface?
0177: */
0178: private boolean m_isInterface = false;
0179: /**
0180: * the proxy class for the described class, may be null
0181: */
0182: private Class proxyClass = null;
0183: /**
0184: * the proxy class name for the described class, may be null
0185: */
0186: private String proxyClassName = null;
0187: /**
0188: * if false do not accept implicit locks on this class
0189: */
0190: private boolean acceptLocks = true;
0191: /**
0192: * if true instances of this class are always refreshed
0193: * even if they are already in the cache.
0194: * false by default.
0195: */
0196: private boolean alwaysRefresh = false;
0197: private int m_ProxyPrefetchingLimit = 50;
0198: /**
0199: * optional, ObjectCacheDescriptor for representing class
0200: */
0201: private ObjectCacheDescriptor objectCacheDescriptor;
0202: /**
0203: * the vector of indices used in DDL generation.
0204: */
0205: private Vector indexes = new Vector();
0206:
0207: //-----------------------------------------------------------------
0208: //-----------------------------------------------------------------
0209: // !!! the following arrays and maps have take care of metadata changes!!!
0210: //-----------------------------------------------------------------
0211: //-----------------------------------------------------------------
0212: private FieldDescriptor m_autoIncrementField = null;
0213: /**
0214: * the FieldDescriptors for the primitive attributes
0215: */
0216: private FieldDescriptor[] m_FieldDescriptions = null;
0217: /**
0218: * the descriptors for collection attributes
0219: */
0220: private Vector m_CollectionDescriptors = new Vector();
0221: /**
0222: * the descriptor for 1-1 reference attributes
0223: */
0224: private Vector m_ObjectReferenceDescriptors = new Vector();
0225: /**
0226: * the non-primary key FieldDescriptors
0227: */
0228: private FieldDescriptor[] m_nonPkFieldDescriptors = null;
0229: /**
0230: * the primary key FieldDescriptors
0231: */
0232: private FieldDescriptor[] m_PkFieldDescriptors = null;
0233: /**
0234: * the read/write FieldDescriptors BRJ
0235: */
0236: private FieldDescriptor[] m_RwFieldDescriptors = null;
0237: private FieldDescriptor[] m_RwNonPkFieldDescriptors = null;
0238: /**
0239: * the optimistic lockingFieldDescriptors BRJ
0240: */
0241: private FieldDescriptor[] m_lockingFieldDescriptors = null;
0242: /**
0243: * the list of classes in the extent of this class. can be empty
0244: */
0245: private Vector extentClasses = new Vector();
0246: /**
0247: * the list of class names in the extent of this class. can be empty
0248: */
0249: private Vector extentClassNames = new Vector();
0250: private Map m_fieldDescriptorNameMap = null;
0251: private Map m_collectionDescriptorNameMap = null;
0252: private Map m_objectReferenceDescriptorsNameMap = null;
0253:
0254: // BRJ: ClassDescriptor referenced by 'super' ObjectReferenceDescriptor
0255: private ClassDescriptor m_super Cld = null;
0256: private boolean m_super CldSet = false;
0257:
0258: //-----------------------------------------------------------------
0259: //-----------------------------------------------------------------
0260: // END of cached metadata information
0261: //-----------------------------------------------------------------
0262: //-----------------------------------------------------------------
0263:
0264: //---------------------------------------------------------------
0265: /**
0266: * Constructor declaration
0267: */
0268: public ClassDescriptor(DescriptorRepository pRepository) {
0269: m_repository = pRepository;
0270: m_IsolationLevel = pRepository.getDefaultIsolationLevel();
0271: }
0272:
0273: //---------------------------------------------------------------
0274: // method declarations
0275: //---------------------------------------------------------------
0276: public String getBaseClass() {
0277: return baseClass;
0278: }
0279:
0280: public void setBaseClass(String baseClass) {
0281: this .baseClass = baseClass;
0282: // first deregister
0283: getRepository().deregisterSuperClassMultipleJoinedTables(this );
0284: // register classes using mapping of classes to multiple joined tables
0285: getRepository().registerSuperClassMultipleJoinedTables(this );
0286: }
0287:
0288: // /**
0289: // * @deprecated no longer needed map class on multi joined table
0290: // */
0291: // public void setSuperPersistentFieldDescriptors(Vector superPersistentFieldDescriptors)
0292: // {
0293: // this.superPersistentFieldDescriptors = superPersistentFieldDescriptors;
0294: // }
0295: //
0296: // /**
0297: // * @deprecated no longer needed map class on multi joined table
0298: // */
0299: // public Vector getSuperPersistentFieldDescriptors()
0300: // {
0301: // return superPersistentFieldDescriptors;
0302: // }
0303:
0304: /**
0305: * Returns the appropriate {@link ObjectCacheDescriptor}
0306: * or <code>null</code> if not specified.
0307: */
0308: public ObjectCacheDescriptor getObjectCacheDescriptor() {
0309: return objectCacheDescriptor;
0310: }
0311:
0312: /**
0313: * Sets the {@link ObjectCacheDescriptor} for representing class.
0314: */
0315: public void setObjectCacheDescriptor(
0316: ObjectCacheDescriptor objectCacheDescriptor) {
0317: this .objectCacheDescriptor = objectCacheDescriptor;
0318: }
0319:
0320: /**
0321: * sets the row reader class for this descriptor
0322: */
0323: public void setRowReader(RowReader newReader) {
0324: m_rowReader = newReader;
0325: }
0326:
0327: /**
0328: * Returns the {@link org.apache.ojb.broker.accesslayer.RowReader}
0329: * for this descriptor.
0330: */
0331: public synchronized RowReader getRowReader() {
0332: if (m_rowReader == null) {
0333: Configurator configurator = OjbConfigurator.getInstance();
0334: Configuration config = configurator
0335: .getConfigurationFor(null);
0336: Class rrClass = config.getClass("RowReaderDefaultClass",
0337: RowReaderDefaultImpl.class);
0338:
0339: setRowReader(rrClass.getName());
0340: }
0341: return m_rowReader;
0342: }
0343:
0344: /**
0345: * sets the row reader class name for thie class descriptor
0346: */
0347: public void setRowReader(String newReaderClassName) {
0348: try {
0349: m_rowReader = (RowReader) ClassHelper.newInstance(
0350: newReaderClassName, ClassDescriptor.class, this );
0351: } catch (Exception e) {
0352: throw new MetadataException(
0353: "Instantiating of current set RowReader failed", e);
0354: }
0355: }
0356:
0357: public String getRowReaderClassName() {
0358: return m_rowReader != null ? m_rowReader.getClass().getName()
0359: : null;
0360: }
0361:
0362: /**
0363: * returns the name of the described class
0364: * @return String name of the described class
0365: */
0366: public String getClassNameOfObject() {
0367: return m_Class != null ? m_Class.getName() : null;
0368: }
0369:
0370: /**
0371: * returns the class object of the described class
0372: * @return Class the described class
0373: */
0374: public Class getClassOfObject() {
0375: return m_Class;
0376: }
0377:
0378: /**
0379: * sets the class object described by this descriptor.
0380: * @param c the class to describe
0381: */
0382: public void setClassOfObject(Class c) {
0383: m_Class = c;
0384: isAbstract = Modifier.isAbstract(m_Class.getModifiers());
0385: // TODO : Shouldn't the HashMap in DescriptorRepository be updated as well?
0386: }
0387:
0388: /**
0389: * adds a FIELDDESCRIPTOR to this ClassDescriptor.
0390: * @param fld
0391: */
0392: public void addFieldDescriptor(FieldDescriptor fld) {
0393: fld.setClassDescriptor(this ); // BRJ
0394: if (m_FieldDescriptions == null) {
0395: m_FieldDescriptions = new FieldDescriptor[1];
0396: m_FieldDescriptions[0] = fld;
0397: } else {
0398: int size = m_FieldDescriptions.length;
0399: FieldDescriptor[] tmpArray = new FieldDescriptor[size + 1];
0400: System.arraycopy(m_FieldDescriptions, 0, tmpArray, 0, size);
0401: tmpArray[size] = fld;
0402: m_FieldDescriptions = tmpArray;
0403: // 2. Sort fields according to their getOrder() Property
0404: Arrays.sort(m_FieldDescriptions, FieldDescriptor
0405: .getComparator());
0406: }
0407:
0408: m_fieldDescriptorNameMap = null;
0409: m_PkFieldDescriptors = null;
0410: m_nonPkFieldDescriptors = null;
0411: m_lockingFieldDescriptors = null;
0412: m_RwFieldDescriptors = null;
0413: m_RwNonPkFieldDescriptors = null;
0414: }
0415:
0416: public boolean removeFieldDescriptor(FieldDescriptor fld) {
0417: boolean result = false;
0418: if (m_FieldDescriptions == null)
0419: return result;
0420:
0421: List list = new ArrayList(Arrays.asList(m_FieldDescriptions));
0422: result = list.remove(fld);
0423: m_FieldDescriptions = (FieldDescriptor[]) list
0424: .toArray(new FieldDescriptor[list.size()]);
0425:
0426: m_fieldDescriptorNameMap = null;
0427: m_PkFieldDescriptors = null;
0428: m_nonPkFieldDescriptors = null;
0429: m_lockingFieldDescriptors = null;
0430: m_RwFieldDescriptors = null;
0431: m_RwNonPkFieldDescriptors = null;
0432: return result;
0433: }
0434:
0435: /**
0436: * Returns all defined {@link CollectionDescriptor} for
0437: * this class descriptor.
0438: */
0439: public Vector getCollectionDescriptors() {
0440: return m_CollectionDescriptors;
0441: }
0442:
0443: /**
0444: * Add a {@link CollectionDescriptor}.
0445: */
0446: public void addCollectionDescriptor(CollectionDescriptor cod) {
0447: m_CollectionDescriptors.add(cod);
0448: cod.setClassDescriptor(this ); // BRJ
0449:
0450: m_collectionDescriptorNameMap = null;
0451: }
0452:
0453: public void removeCollectionDescriptor(CollectionDescriptor cod) {
0454: m_CollectionDescriptors.remove(cod);
0455: m_collectionDescriptorNameMap = null;
0456: }
0457:
0458: /**
0459: * Returns all defined {@link ObjectReferenceDescriptor}.
0460: */
0461: public Vector getObjectReferenceDescriptors() {
0462: return m_ObjectReferenceDescriptors;
0463: }
0464:
0465: /**
0466: * Add a {@link ObjectReferenceDescriptor}.
0467: */
0468: public void addObjectReferenceDescriptor(
0469: ObjectReferenceDescriptor ord) {
0470: m_ObjectReferenceDescriptors.add(ord);
0471: ord.setClassDescriptor(this ); // BRJ
0472:
0473: m_objectReferenceDescriptorsNameMap = null;
0474: }
0475:
0476: public void removeObjectReferenceDescriptor(
0477: ObjectReferenceDescriptor ord) {
0478: m_ObjectReferenceDescriptors.remove(ord);
0479: m_objectReferenceDescriptorsNameMap = null;
0480: }
0481:
0482: /**
0483: * Get an ObjectReferenceDescriptor by name BRJ
0484: * @param name
0485: * @return ObjectReferenceDescriptor or null
0486: */
0487: public ObjectReferenceDescriptor getObjectReferenceDescriptorByName(
0488: String name) {
0489: ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) getObjectReferenceDescriptorsNameMap()
0490: .get(name);
0491:
0492: //
0493: // BRJ: if the ReferenceDescriptor is not found
0494: // look in the ClassDescriptor referenced by 'super' for it
0495: //
0496: if (ord == null) {
0497: ClassDescriptor super Cld = getSuperClassDescriptor();
0498: if (super Cld != null) {
0499: ord = super Cld.getObjectReferenceDescriptorByName(name);
0500: }
0501: }
0502: return ord;
0503: }
0504:
0505: private Map getObjectReferenceDescriptorsNameMap() {
0506: if (m_objectReferenceDescriptorsNameMap == null) {
0507: HashMap nameMap = new HashMap();
0508:
0509: Vector descriptors = getObjectReferenceDescriptors();
0510: for (int i = descriptors.size() - 1; i >= 0; i--) {
0511: ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) descriptors
0512: .get(i);
0513: nameMap.put(ord.getAttributeName(), ord);
0514: }
0515: m_objectReferenceDescriptorsNameMap = nameMap;
0516: }
0517:
0518: return m_objectReferenceDescriptorsNameMap;
0519: }
0520:
0521: /**
0522: * Get an CollectionDescriptor by name BRJ
0523: * @param name
0524: * @return CollectionDescriptor or null
0525: */
0526: public CollectionDescriptor getCollectionDescriptorByName(
0527: String name) {
0528: if (name == null) {
0529: return null;
0530: }
0531:
0532: CollectionDescriptor cod = (CollectionDescriptor) getCollectionDescriptorNameMap()
0533: .get(name);
0534:
0535: //
0536: // BRJ: if the CollectionDescriptor is not found
0537: // look in the ClassDescriptor referenced by 'super' for it
0538: //
0539: if (cod == null) {
0540: ClassDescriptor super Cld = getSuperClassDescriptor();
0541: if (super Cld != null) {
0542: cod = super Cld.getCollectionDescriptorByName(name);
0543: }
0544: }
0545:
0546: return cod;
0547: }
0548:
0549: private Map getCollectionDescriptorNameMap() {
0550: if (m_collectionDescriptorNameMap == null) {
0551: HashMap nameMap = new HashMap();
0552:
0553: Vector descriptors = getCollectionDescriptors();
0554: for (int i = descriptors.size() - 1; i >= 0; i--) {
0555: CollectionDescriptor cod = (CollectionDescriptor) descriptors
0556: .get(i);
0557: nameMap.put(cod.getAttributeName(), cod);
0558: }
0559: m_collectionDescriptorNameMap = nameMap;
0560: }
0561:
0562: return m_collectionDescriptorNameMap;
0563: }
0564:
0565: /**
0566: * Answers the ClassDescriptor referenced by 'super' ReferenceDescriptor.
0567: * @return ClassDescriptor or null
0568: */
0569: public ClassDescriptor getSuperClassDescriptor() {
0570: if (!m_super CldSet) {
0571: if (getBaseClass() != null) {
0572: m_super Cld = getRepository().getDescriptorFor(
0573: getBaseClass());
0574: if (m_super Cld.isAbstract() || m_super Cld.isInterface()) {
0575: throw new MetadataException(
0576: "Super class mapping only work for real class, but declared super class"
0577: + " is an interface or is abstract. Declared class: "
0578: + m_super Cld.getClassNameOfObject());
0579: }
0580: }
0581: m_super CldSet = true;
0582: }
0583:
0584: return m_super Cld;
0585: }
0586:
0587: /**
0588: * add an Extent class to the current descriptor
0589: * @param newExtendClass
0590: * @deprecated use {@link #addExtentClass(String newExtentClass)} instead
0591: */
0592: public void addExtentClassName(Class newExtendClass) {
0593: addExtentClass(newExtendClass);
0594: }
0595:
0596: /**
0597: * add an Extent class to the current descriptor
0598: * @param newExtendClass
0599: */
0600: public void addExtentClass(Class newExtendClass) {
0601: extentClasses.add(newExtendClass);
0602: this .addExtentClass(newExtendClass.getName());
0603: }
0604:
0605: /**
0606: * add an Extent class to the current descriptor
0607: * @param newExtentClassName name of the class to add
0608: */
0609: public void addExtentClass(String newExtentClassName) {
0610: extentClassNames.add(newExtentClassName);
0611: if (m_repository != null)
0612: m_repository.addExtent(newExtentClassName, this );
0613: }
0614:
0615: public void removeExtentClass(String extentClassName) {
0616: extentClassNames.remove(extentClassName);
0617: if (m_repository != null)
0618: m_repository.removeExtent(extentClassName);
0619: }
0620:
0621: /**
0622: * return all classes in this extent.
0623: * Creation date: (02.02.2001 17:49:11)
0624: * @return java.util.Vector
0625: */
0626: public synchronized Vector getExtentClasses() {
0627: if (extentClassNames.size() != extentClasses.size()) {
0628: extentClasses.clear();
0629: for (Iterator iter = extentClassNames.iterator(); iter
0630: .hasNext();) {
0631: String classname = (String) iter.next();
0632: Class extentClass;
0633: try {
0634: extentClass = ClassHelper.getClass(classname);
0635: } catch (ClassNotFoundException e) {
0636: throw new MetadataException(
0637: "Unable to load class ["
0638: + classname
0639: + "]. Make sure it is available on the classpath.",
0640: e);
0641: }
0642: extentClasses.add(extentClass);
0643: }
0644: }
0645: return extentClasses;
0646: }
0647:
0648: /**
0649: * Return the names of all classes in this extent
0650: * @return java.util.Vector a Vector containing the fully qualified names
0651: * of all classes in this extent
0652: */
0653: public synchronized Vector getExtentClassNames() {
0654: return this .extentClassNames;
0655: }
0656:
0657: /**
0658: * Insert the method's description here.
0659: * Creation date: (02.02.2001 17:49:11)
0660: * @return boolean
0661: */
0662: public boolean isExtent() {
0663: return (getExtentClassNames().size() > 0);
0664: }
0665:
0666: /**
0667: * Insert the method's description here.
0668: * Creation date: (26.01.2001 09:20:09)
0669: * @return java.lang.Class
0670: */
0671: public synchronized Class getProxyClass() {
0672: if ((proxyClass == null) && (proxyClassName != null)) {
0673: if (isDynamicProxy()) {
0674: /**
0675: * AClute: Return the same class back if it is dynamic. This signifies
0676: * that this class become the base to a generated sub-class, regadless
0677: * of which Proxy implementation is used
0678: */
0679: return getClassOfObject();
0680: } else {
0681: try {
0682: proxyClass = ClassHelper.getClass(proxyClassName);
0683: } catch (ClassNotFoundException e) {
0684: throw new MetadataException(e);
0685: }
0686: }
0687: }
0688: return proxyClass;
0689: }
0690:
0691: public boolean isDynamicProxy() {
0692: return DYNAMIC_STR.equalsIgnoreCase(proxyClassName);
0693: }
0694:
0695: /**
0696: * Sets the proxy class to be used.
0697: * @param newProxyClass java.lang.Class
0698: */
0699: public void setProxyClass(Class newProxyClass) {
0700: proxyClass = newProxyClass;
0701: if (proxyClass == null) {
0702: setProxyClassName(null);
0703: } else {
0704: proxyClassName = proxyClass.getName();
0705: }
0706: }
0707:
0708: /**
0709: * Sets the name of the proxy class to be used.
0710: * using "dynamic" instead of a real classname
0711: * will result in usage of dynamic proxies.
0712: * @param newProxyClassName the classname or "dynamic"
0713: */
0714: public void setProxyClassName(String newProxyClassName) {
0715: proxyClassName = newProxyClassName;
0716: }
0717:
0718: /**
0719: * Get the name of the proxy class. This method doesn't try to access
0720: * the real class, so it can be called even if the class doesn't exist.
0721: */
0722: public String getProxyClassName() {
0723: return proxyClassName;
0724: }
0725:
0726: /**
0727: * Returns array of all FieldDescriptors.
0728: */
0729: public FieldDescriptor[] getFieldDescriptions() {
0730: return m_FieldDescriptions;
0731: }
0732:
0733: /**
0734: * Returns the matching {@link FieldDescriptor}.
0735: */
0736: public FieldDescriptor getFieldDescriptorByIndex(int index) {
0737: return m_FieldDescriptions[index - 1];
0738: }
0739:
0740: /**
0741: * Returns the matching {@link FieldDescriptor} - only fields
0742: * of the current class will be scanned, to include fields defined
0743: * the the super-classes too, use method {@link #getFieldDescriptor(boolean)}.
0744: */
0745: public FieldDescriptor getFieldDescriptorByName(String name) {
0746: if (name == null || m_FieldDescriptions == null) {
0747: return null;
0748: }
0749:
0750: if (m_fieldDescriptorNameMap == null) {
0751: HashMap nameMap = new HashMap();
0752:
0753: FieldDescriptor[] descriptors = getFieldDescriptions();
0754: for (int i = descriptors.length - 1; i >= 0; i--) {
0755: FieldDescriptor fld = descriptors[i];
0756: nameMap.put(fld.getPersistentField().getName(), fld);
0757: }
0758:
0759: m_fieldDescriptorNameMap = nameMap;
0760: }
0761:
0762: return (FieldDescriptor) m_fieldDescriptorNameMap.get(name);
0763: }
0764:
0765: /**
0766: * return the FieldDescriptor for the Attribute referenced in the path<br>
0767: * the path may contain simple attribut names, functions and path expressions
0768: * using relationships <br>
0769: * ie: name, avg(price), adress.street
0770: * @param aPath the path to the attribute
0771: * @param pathHints a Map containing the class to be used for a segment or <em>null</em>
0772: * if no segment was used.
0773: * @return the FieldDescriptor or null (ie: for m:n queries)
0774: */
0775: public FieldDescriptor getFieldDescriptorForPath(String aPath,
0776: Map pathHints) {
0777: ArrayList desc = getAttributeDescriptorsForPath(aPath,
0778: pathHints);
0779: FieldDescriptor fld = null;
0780: Object temp;
0781:
0782: if (!desc.isEmpty()) {
0783: temp = desc.get(desc.size() - 1);
0784: if (temp instanceof FieldDescriptor) {
0785: fld = (FieldDescriptor) temp;
0786: }
0787: }
0788: return fld;
0789: }
0790:
0791: /**
0792: * return the FieldDescriptor for the Attribute referenced in the path<br>
0793: * the path may contain simple attribut names, functions and path expressions
0794: * using relationships <br>
0795: * ie: name, avg(price), adress.street
0796: * @param aPath the path to the attribute
0797: * @return the FieldDescriptor or null (ie: for m:n queries)
0798: */
0799: public FieldDescriptor getFieldDescriptorForPath(String aPath) {
0800: return getFieldDescriptorForPath(aPath, null);
0801: }
0802:
0803: /*
0804: arminw:
0805: TODO: this feature doesn't work, so remove this in future
0806: */
0807: /**
0808: *
0809: * @return this classes FieldDescriptor's as well as it's parents and so on and so on
0810: */
0811: public FieldDescriptor[] getFieldDescriptorsInHeirarchy() {
0812: if (super Class == null) {
0813: return getFieldDescriptions();
0814: }
0815: ClassDescriptor cldSuper = getRepository().getDescriptorFor(
0816: super Class);
0817: return appendFieldDescriptorArrays(getFieldDescriptions(),
0818: cldSuper.getFieldDescriptorsInHeirarchy());
0819: }
0820:
0821: private FieldDescriptor[] appendFieldDescriptorArrays(
0822: FieldDescriptor[] fieldDescriptions,
0823: FieldDescriptor[] fieldDescriptorsInHeirarchy) {
0824: // take the 2 arrays and add them into one
0825: int size = fieldDescriptions.length
0826: + fieldDescriptorsInHeirarchy.length;
0827: FieldDescriptor[] newArray = new FieldDescriptor[size];
0828: System.arraycopy(fieldDescriptions, 0, newArray, 0,
0829: fieldDescriptions.length);
0830: System.arraycopy(fieldDescriptorsInHeirarchy, 0, newArray,
0831: fieldDescriptions.length,
0832: fieldDescriptorsInHeirarchy.length);
0833: return newArray;
0834: }
0835:
0836: /**
0837: * Returns the first found autoincrement field
0838: * defined in this class descriptor. Use carefully
0839: * when multiple autoincrement field were defined.
0840: * @deprecated does not make sense because it's possible to
0841: * define more than one autoincrement field. Alternative
0842: * see {@link #getAutoIncrementFields}
0843: */
0844: public FieldDescriptor getAutoIncrementField() {
0845: if (m_autoIncrementField == null) {
0846: FieldDescriptor[] fds = getPkFields();
0847:
0848: for (int i = 0; i < fds.length; i++) {
0849: FieldDescriptor fd = fds[i];
0850: if (fd.isAutoIncrement()) {
0851: m_autoIncrementField = fd;
0852: break;
0853: }
0854: }
0855: }
0856: if (m_autoIncrementField == null) {
0857: LoggerFactory
0858: .getDefaultLogger()
0859: .warn(
0860: this .getClass().getName()
0861: + ": "
0862: + "Could not find autoincrement attribute for class: "
0863: + this .getClassNameOfObject());
0864: }
0865: return m_autoIncrementField;
0866: }
0867:
0868: public FieldDescriptor[] getAutoIncrementFields() {
0869: ArrayList result = new ArrayList();
0870: for (int i = 0; i < m_FieldDescriptions.length; i++) {
0871: FieldDescriptor field = m_FieldDescriptions[i];
0872: if (field.isAutoIncrement())
0873: result.add(field);
0874: }
0875: return (FieldDescriptor[]) result
0876: .toArray(new FieldDescriptor[result.size()]);
0877: }
0878:
0879: /**
0880: * returns an Array with an Objects CURRENT locking VALUES , BRJ
0881: * @throws PersistenceBrokerException if there is an erros accessing o field values
0882: */
0883: public ValueContainer[] getCurrentLockingValues(Object o)
0884: throws PersistenceBrokerException {
0885: FieldDescriptor[] fields = getLockingFields();
0886: ValueContainer[] result = new ValueContainer[fields.length];
0887: for (int i = 0; i < result.length; i++) {
0888: result[i] = new ValueContainer(fields[i]
0889: .getPersistentField().get(o), fields[i]
0890: .getJdbcType());
0891: }
0892: return result;
0893: }
0894:
0895: /**
0896: * updates the values for locking fields , BRJ
0897: * handles int, long, Timestamp
0898: * respects updateLock so locking field are only updated when updateLock is true
0899: * @throws PersistenceBrokerException if there is an erros accessing obj field values
0900: */
0901: public void updateLockingValues(Object obj)
0902: throws PersistenceBrokerException {
0903: FieldDescriptor[] fields = getLockingFields();
0904: for (int i = 0; i < fields.length; i++) {
0905: FieldDescriptor fmd = fields[i];
0906: if (fmd.isUpdateLock()) {
0907: PersistentField f = fmd.getPersistentField();
0908: Object cv = f.get(obj);
0909: // int
0910: if ((f.getType() == int.class)
0911: || (f.getType() == Integer.class)) {
0912: int newCv = 0;
0913: if (cv != null) {
0914: newCv = ((Number) cv).intValue();
0915: }
0916: newCv++;
0917: f.set(obj, new Integer(newCv));
0918: }
0919: // long
0920: else if ((f.getType() == long.class)
0921: || (f.getType() == Long.class)) {
0922: long newCv = 0;
0923: if (cv != null) {
0924: newCv = ((Number) cv).longValue();
0925: }
0926: newCv++;
0927: f.set(obj, new Long(newCv));
0928: }
0929: // Timestamp
0930: else if (f.getType() == Timestamp.class) {
0931: long newCv = System.currentTimeMillis();
0932: f.set(obj, new Timestamp(newCv));
0933: }
0934: }
0935: }
0936: }
0937:
0938: /**
0939: * return an array of NONPK-FieldDescription sorted ascending
0940: * according to the field-descriptions getOrder() property
0941: */
0942: public FieldDescriptor[] getNonPkFields() {
0943: if (m_nonPkFieldDescriptors == null) {
0944: // 1. collect all Primary Key fields from Field list
0945: Vector vec = new Vector();
0946: for (int i = 0; i < m_FieldDescriptions.length; i++) {
0947: FieldDescriptor fd = m_FieldDescriptions[i];
0948: if (!fd.isPrimaryKey()) {
0949: vec.add(fd);
0950: }
0951: }
0952: // 2. Sort fields according to their getOrder() Property
0953: Collections.sort(vec, FieldDescriptor.getComparator());
0954: m_nonPkFieldDescriptors = (FieldDescriptor[]) vec
0955: .toArray(new FieldDescriptor[vec.size()]);
0956: }
0957: return m_nonPkFieldDescriptors;
0958: }
0959:
0960: /**
0961: * Return an array of PK FieldDescription sorted ascending
0962: * according to the field-descriptions getOrder() property
0963: */
0964: public FieldDescriptor[] getPkFields() {
0965: if (m_PkFieldDescriptors == null) {
0966: // 1. collect all Primary Key fields from Field list
0967: Vector vec = new Vector();
0968: // 1.a if descriptor describes an interface: take PK fields from an implementors ClassDescriptor
0969: if (m_isInterface) {
0970: if (getExtentClasses().size() == 0) {
0971: throw new PersistenceBrokerException(
0972: "No Implementors declared for interface "
0973: + this .getClassOfObject().getName());
0974: }
0975: Class implementor = (Class) getExtentClasses().get(0);
0976: ClassDescriptor implCld = this .getRepository()
0977: .getDescriptorFor(implementor);
0978: m_PkFieldDescriptors = implCld.getPkFields();
0979: } else {
0980: FieldDescriptor[] fields;
0981: // 1.b if not an interface The classdescriptor must have FieldDescriptors
0982: fields = getFieldDescriptions();
0983: // now collect all PK fields
0984: for (int i = 0; i < fields.length; i++) {
0985: FieldDescriptor fd = fields[i];
0986: if (fd.isPrimaryKey()) {
0987: vec.add(fd);
0988: }
0989: }
0990: // 2. Sort fields according to their getOrder() Property
0991: Collections.sort(vec, FieldDescriptor.getComparator());
0992: m_PkFieldDescriptors = (FieldDescriptor[]) vec
0993: .toArray(new FieldDescriptor[vec.size()]);
0994: }
0995: }
0996: return m_PkFieldDescriptors;
0997: }
0998:
0999: /**
1000: * Returns array of read/write non pk FieldDescriptors.
1001: */
1002: public FieldDescriptor[] getNonPkRwFields() {
1003: if (m_RwNonPkFieldDescriptors == null) {
1004: FieldDescriptor[] fields = getNonPkFields();
1005: Collection rwFields = new ArrayList();
1006:
1007: for (int i = 0; i < fields.length; i++) {
1008: FieldDescriptor fd = fields[i];
1009: if (!fd.isAccessReadOnly()) {
1010: rwFields.add(fd);
1011: }
1012: }
1013: m_RwNonPkFieldDescriptors = (FieldDescriptor[]) rwFields
1014: .toArray(new FieldDescriptor[rwFields.size()]);
1015: }
1016: return m_RwNonPkFieldDescriptors;
1017: }
1018:
1019: /**
1020: * Returns array of read/write FieldDescriptors.
1021: */
1022: public FieldDescriptor[] getAllRwFields() {
1023: if (m_RwFieldDescriptors == null) {
1024: FieldDescriptor[] fields = getFieldDescriptions();
1025: Collection rwFields = new ArrayList();
1026:
1027: for (int i = 0; i < fields.length; i++) {
1028: FieldDescriptor fd = fields[i];
1029: /*
1030: arminw: if locking is enabled and the increment of locking
1031: values is done by the database, the field is read-only
1032: */
1033: if (fd.isAccessReadOnly()
1034: || (fd.isLocking() && !fd.isUpdateLock())) {
1035: continue;
1036: }
1037: rwFields.add(fd);
1038: }
1039: m_RwFieldDescriptors = (FieldDescriptor[]) rwFields
1040: .toArray(new FieldDescriptor[rwFields.size()]);
1041: }
1042:
1043: return m_RwFieldDescriptors;
1044: }
1045:
1046: /**
1047: * return an array of FieldDescription for optimistic locking sorted ascending
1048: * according to the field-descriptions getOrder() property
1049: */
1050: public FieldDescriptor[] getLockingFields() {
1051: if (m_lockingFieldDescriptors == null) {
1052: // 1. collect all Primary Key fields from Field list
1053: Vector vec = new Vector();
1054: for (int i = 0; i < m_FieldDescriptions.length; i++) {
1055: FieldDescriptor fd = m_FieldDescriptions[i];
1056: if (fd.isLocking()) {
1057: vec.add(fd);
1058: }
1059: }
1060: // 2. Sort fields according to their getOrder() Property
1061: Collections.sort(vec, FieldDescriptor.getComparator());
1062: m_lockingFieldDescriptors = (FieldDescriptor[]) vec
1063: .toArray(new FieldDescriptor[vec.size()]);
1064: }
1065: return m_lockingFieldDescriptors;
1066: }
1067:
1068: /**
1069: * return true if optimistic locking is used
1070: */
1071: public boolean isLocking() {
1072: return getLockingFields().length > 0;
1073: }
1074:
1075: /**
1076: * return all AttributeDescriptors for the path<br>
1077: * ie: partner.addresses.street returns a Collection of 3 AttributeDescriptors
1078: * (ObjectReferenceDescriptor, CollectionDescriptor, FieldDescriptor)<br>
1079: * ie: partner.addresses returns a Collection of 2 AttributeDescriptors
1080: * (ObjectReferenceDescriptor, CollectionDescriptor)
1081: * @param aPath the cleaned path to the attribute
1082: * @return ArrayList of AttributeDescriptors
1083: */
1084: public ArrayList getAttributeDescriptorsForPath(String aPath) {
1085: return getAttributeDescriptorsForPath(aPath, new HashMap());
1086: }
1087:
1088: /**
1089: * return all AttributeDescriptors for the path<br>
1090: * ie: partner.addresses.street returns a Collection of 3 AttributeDescriptors
1091: * (ObjectReferenceDescriptor, CollectionDescriptor, FieldDescriptor)<br>
1092: * ie: partner.addresses returns a Collection of 2 AttributeDescriptors
1093: * (ObjectReferenceDescriptor, CollectionDescriptor)
1094: * @param aPath the cleaned path to the attribute
1095: * @param pathHints a Map containing the class to be used for a segment or <em>null</em>
1096: * if no segment was used.
1097: * @return ArrayList of AttributeDescriptors
1098: */
1099: public ArrayList getAttributeDescriptorsForPath(String aPath,
1100: Map pathHints) {
1101: return getAttributeDescriptorsForCleanPath(SqlHelper
1102: .cleanPath(aPath), pathHints);
1103: }
1104:
1105: /**
1106: * return all AttributeDescriptors for the path<br>
1107: * ie: partner.addresses.street returns a Collection of 3 AttributeDescriptors
1108: * (ObjectReferenceDescriptor, CollectionDescriptor, FieldDescriptor)<br>
1109: * ie: partner.addresses returns a Collection of 2 AttributeDescriptors
1110: * (ObjectReferenceDescriptor, CollectionDescriptor)
1111: * @param aPath the cleaned path to the attribute
1112: * @param pathHints a Map containing the class to be used for a segment or <em>null</em>
1113: * if no segment is used.
1114: * @return ArrayList of AttributeDescriptors
1115: */
1116: private ArrayList getAttributeDescriptorsForCleanPath(String aPath,
1117: Map pathHints) {
1118: ArrayList result = new ArrayList();
1119: ClassDescriptor cld = this ;
1120: ObjectReferenceDescriptor ord;
1121: FieldDescriptor fld;
1122: String currPath = aPath;
1123: String segment;
1124: StringBuffer processedSegment = new StringBuffer();
1125: int sepPos;
1126: Class itemClass;
1127:
1128: while (currPath.length() > 0) {
1129: sepPos = currPath.indexOf(".");
1130: if (sepPos >= 0) {
1131: segment = currPath.substring(0, sepPos);
1132: currPath = currPath.substring(sepPos + 1);
1133: } else {
1134: segment = currPath;
1135: currPath = "";
1136: }
1137:
1138: if (processedSegment.length() > 0) {
1139: processedSegment.append(".");
1140: }
1141: processedSegment.append(segment);
1142:
1143: // look for 1:1 or n:1 Relationship
1144: ord = cld.getObjectReferenceDescriptorByName(segment);
1145: if (ord == null) {
1146: // look for 1:n or m:n Relationship
1147: ord = cld.getCollectionDescriptorByName(segment);
1148: }
1149:
1150: if (ord != null) {
1151: // BRJ : look for hints for the processed segment
1152: // ie: ref pointng to ClassA and ref.ref pointing to ClassC
1153: List hintClasses = pathHints != null ? (List) pathHints
1154: .get(processedSegment.toString()) : null;
1155: if (hintClasses != null && hintClasses.get(0) != null) {
1156: itemClass = (Class) hintClasses.get(0);
1157: } else {
1158: itemClass = ord.getItemClass();
1159: }
1160:
1161: cld = cld.getRepository().getDescriptorFor(itemClass);
1162: result.add(ord);
1163: } else {
1164: // look for Field
1165: fld = cld.getFieldDescriptorByName(segment);
1166: if (fld != null) {
1167: result.add(fld);
1168: }
1169: }
1170: }
1171:
1172: return result;
1173: }
1174:
1175: /**
1176: * returns the zero argument constructor for the class represented by this class descriptor
1177: * or null if a zero argument constructor does not exist. If the zero argument constructor
1178: * for this class is not public it is made accessible before being returned.
1179: */
1180: public Constructor getZeroArgumentConstructor() {
1181: if (zeroArgumentConstructor == null
1182: && !alreadyLookedupZeroArguments) {
1183: try {
1184: zeroArgumentConstructor = getClassOfObject()
1185: .getConstructor(NO_PARAMS);
1186: } catch (NoSuchMethodException e) {
1187: //no public zero argument constructor available let's try for a private/protected one
1188: try {
1189: zeroArgumentConstructor = getClassOfObject()
1190: .getDeclaredConstructor(NO_PARAMS);
1191:
1192: //we found one, now let's make it accessible
1193: zeroArgumentConstructor.setAccessible(true);
1194: } catch (NoSuchMethodException e2) {
1195: //out of options, log the fact and let the method return null
1196: LoggerFactory
1197: .getDefaultLogger()
1198: .warn(
1199: this .getClass().getName()
1200: + ": "
1201: + "No zero argument constructor defined for "
1202: + this .getClassOfObject());
1203: }
1204: }
1205:
1206: alreadyLookedupZeroArguments = true;
1207: }
1208:
1209: return zeroArgumentConstructor;
1210: }
1211:
1212: /*
1213: * @see XmlCapable#toXML()
1214: */
1215: public String toXML() {
1216: RepositoryTags tags = RepositoryTags.getInstance();
1217: String eol = System.getProperty("line.separator");
1218:
1219: // comment on class
1220: StringBuffer result = new StringBuffer(1024);
1221: result.append(eol);
1222: result.append(" <!-- Mapping for Class ");
1223: result.append(this .getClassNameOfObject());
1224: result.append(" -->");
1225: result.append(eol);
1226:
1227: // opening tag and attributes
1228: result.append(" ");
1229: result.append(tags
1230: .getOpeningTagNonClosingById(CLASS_DESCRIPTOR));
1231: result.append(eol);
1232:
1233: // class
1234: result.append(" ");
1235: result.append(tags.getAttribute(CLASS_NAME, this
1236: .getClassNameOfObject()));
1237: result.append(eol);
1238:
1239: // isolation level is optional
1240: if (null != getRepository()) {
1241: if (getIsolationLevel() != this .getRepository()
1242: .getDefaultIsolationLevel()) {
1243: result.append(" ");
1244: result.append(tags.getAttribute(ISOLATION_LEVEL, this
1245: .isolationLevelXml()));
1246: result.append(eol);
1247: }
1248: }
1249:
1250: Class theProxyClass = null;
1251: try {
1252: theProxyClass = this .getProxyClass();
1253: } catch (Throwable t) {
1254: // Ignore this exception, just try to get the Class object of the
1255: // proxy class in order to be able to decide, whether the class
1256: // is a dynamic proxy or not.
1257: }
1258:
1259: // proxy is optional
1260: if (theProxyClass != null) {
1261: if (isDynamicProxy()) // tomdz: What about VirtualProxy ?
1262: {
1263: result.append(" ");
1264: result.append(tags.getAttribute(CLASS_PROXY,
1265: DYNAMIC_STR));
1266: result.append(eol);
1267: } else {
1268: result.append(" ");
1269: result.append(tags.getAttribute(CLASS_PROXY, this
1270: .getProxyClassName()));
1271: result.append(eol);
1272: }
1273: result.append(" ");
1274: result.append(tags.getAttribute(PROXY_PREFETCHING_LIMIT, ""
1275: + this .getProxyPrefetchingLimit()));
1276: result.append(eol);
1277: }
1278:
1279: // schema is optional
1280: if (this .getSchema() != null) {
1281: result.append(" ");
1282: result.append(tags.getAttribute(SCHEMA_NAME, this
1283: .getSchema()));
1284: result.append(eol);
1285: }
1286:
1287: // table name
1288: if (this .getTableName() != null) {
1289: result.append(" ");
1290: result.append(tags.getAttribute(TABLE_NAME, this
1291: .getTableName()));
1292: result.append(eol);
1293: }
1294:
1295: // rowreader is optional
1296: if (this .getRowReaderClassName() != null) {
1297: result.append(" ");
1298: result.append(tags.getAttribute(ROW_READER, this
1299: .getRowReaderClassName()));
1300: result.append(eol);
1301: }
1302:
1303: //accept-locks is optional, enabled by default
1304: if (!this .acceptLocks) {
1305: result.append(" ");
1306: result.append(tags.getAttribute(ACCEPT_LOCKS, "false"));
1307: result.append(eol);
1308: }
1309: // sequence manager attribute not yet implemented
1310:
1311: // initialization method is optional
1312: if (this .getInitializationMethod() != null) {
1313: result.append(" ");
1314: result.append(tags.getAttribute(INITIALIZATION_METHOD, this
1315: .getInitializationMethod().getName()));
1316: result.append(eol);
1317: }
1318:
1319: // factory class is optional
1320: if (this .getFactoryClass() != null) {
1321: result.append(" ");
1322: result.append(tags.getAttribute(FACTORY_CLASS, this
1323: .getFactoryClass().getName()));
1324: result.append(eol);
1325: }
1326:
1327: // factory method is optional
1328: if (this .getFactoryMethod() != null) {
1329: result.append(" ");
1330: result.append(tags.getAttribute(FACTORY_METHOD, this
1331: .getFactoryMethod().getName()));
1332: result.append(eol);
1333: }
1334:
1335: //reference refresh is optional, disabled by default
1336: if (isAlwaysRefresh()) {
1337: result.append(" ");
1338: result.append(tags.getAttribute(REFRESH, "true"));
1339: result.append(eol);
1340: }
1341:
1342: result.append(" >");
1343: result.append(eol);
1344:
1345: // end of attributes
1346:
1347: // begin of elements
1348: if (isInterface()) {
1349: // extent-class
1350: for (int i = 0; i < getExtentClassNames().size(); i++) {
1351: result.append(" ");
1352: result.append(tags
1353: .getOpeningTagNonClosingById(CLASS_EXTENT));
1354: result.append(" ");
1355: result.append(tags.getAttribute(CLASS_REF,
1356: getExtentClassNames().get(i).toString()));
1357: result.append(" />");
1358: result.append(eol);
1359: }
1360: } else {
1361: // class extent is optional
1362: if (isExtent()) {
1363: for (int i = 0; i < getExtentClassNames().size(); i++) {
1364: result.append(" ");
1365: result.append(tags
1366: .getOpeningTagNonClosingById(CLASS_EXTENT));
1367: result.append(" ");
1368: result.append(tags.getAttribute(CLASS_REF,
1369: getExtentClassNames().get(i).toString()));
1370: result.append(" />");
1371: result.append(eol);
1372: }
1373: }
1374:
1375: // write all FieldDescriptors
1376: FieldDescriptor[] fields = getFieldDescriptions();
1377: for (int i = 0; i < fields.length; i++) {
1378: result.append(fields[i].toXML());
1379: }
1380:
1381: // write optional ReferenceDescriptors
1382: Vector refs = getObjectReferenceDescriptors();
1383: for (int i = 0; i < refs.size(); i++) {
1384: result.append(((ObjectReferenceDescriptor) refs.get(i))
1385: .toXML());
1386: }
1387:
1388: // write optional CollectionDescriptors
1389: Vector cols = getCollectionDescriptors();
1390: for (int i = 0; i < cols.size(); i++) {
1391: result.append(((CollectionDescriptor) cols.get(i))
1392: .toXML());
1393: }
1394:
1395: // write optional IndexDescriptors
1396: for (int i = 0; i < indexes.size(); i++) {
1397: IndexDescriptor indexDescriptor = (IndexDescriptor) indexes
1398: .elementAt(i);
1399: result.append(indexDescriptor.toXML());
1400: }
1401:
1402: // Write out the procedures
1403: if (this .getInsertProcedure() != null) {
1404: result.append(this .getInsertProcedure().toXML());
1405: }
1406: if (this .getUpdateProcedure() != null) {
1407: result.append(this .getUpdateProcedure().toXML());
1408: }
1409: if (this .getDeleteProcedure() != null) {
1410: result.append(this .getDeleteProcedure().toXML());
1411: }
1412: }
1413: result.append(" ");
1414: result.append(tags.getClosingTagById(CLASS_DESCRIPTOR));
1415: return result.toString();
1416: }
1417:
1418: private String isolationLevelXml() {
1419: switch (this .getIsolationLevel()) {
1420: case (IL_OPTIMISTIC): {
1421: return LITERAL_IL_OPTIMISTIC;
1422: }
1423: case (IL_READ_COMMITTED): {
1424: return LITERAL_IL_READ_COMMITTED;
1425: }
1426: case (IL_READ_UNCOMMITTED): {
1427: return LITERAL_IL_READ_UNCOMMITTED;
1428: }
1429: case (IL_REPEATABLE_READ): {
1430: return LITERAL_IL_REPEATABLE_READ;
1431: }
1432: case (IL_SERIALIZABLE): {
1433: return LITERAL_IL_SERIALIZABLE;
1434: }
1435: default: {
1436: return LITERAL_IL_READ_UNCOMMITTED;
1437: }
1438: }
1439: }
1440:
1441: /*
1442: arminw:
1443: TODO: this feature doesn't work, so remove this in future
1444: */
1445: /**
1446: * Set name of the super class.
1447: */
1448: public void setSuperClass(String classname) {
1449: this .super Class = classname;
1450: }
1451:
1452: /**
1453: * Return the super class or <code>null</code>
1454: * if not declared in repository file.
1455: */
1456: public String getSuperClass() {
1457: return super Class;
1458: }
1459:
1460: /**
1461: * TODO drop this method?
1462: */
1463: public void setSuperClassFieldRef(int fieldId) {
1464: this .super ClassFieldRef = fieldId;
1465: }
1466:
1467: /**
1468: * TODO drop this method?
1469: */
1470: public int getSuperClassFieldRef() {
1471: return super ClassFieldRef;
1472: }
1473:
1474: /**
1475: * Return true, if the described class is
1476: * an interface.
1477: */
1478: public boolean isInterface() {
1479: return m_isInterface;
1480: }
1481:
1482: /**
1483: * Set <code>true</code> if described class is
1484: * a interface.
1485: */
1486: public void setIsInterface(boolean newIsInterface) {
1487: m_isInterface = newIsInterface;
1488: }
1489:
1490: /**
1491: * @return boolean true if the mapped class is abstract
1492: */
1493: public boolean isAbstract() {
1494: return isAbstract;
1495: }
1496:
1497: /**
1498: * Returns acceptLocks.
1499: * @return boolean
1500: */
1501: public boolean isAcceptLocks() {
1502: return acceptLocks;
1503: }
1504:
1505: /**
1506: * Sets acceptLocks.
1507: * @param acceptLocks The m_acceptLocks to set
1508: */
1509: public void setAcceptLocks(boolean acceptLocks) {
1510: this .acceptLocks = acceptLocks;
1511: }
1512:
1513: /**
1514: * Gets the IndexDescriptors used for DDL generation.
1515: */
1516: public Vector getIndexes() {
1517: return indexes;
1518: }
1519:
1520: /**
1521: * Sets the IndexDescriptors used for DDL generation.
1522: */
1523: public void setIndexes(Vector indexes) {
1524: this .indexes = indexes;
1525: }
1526:
1527: /**
1528: * Gets the repository.
1529: * @return Returns a DescriptorRepository
1530: */
1531: public DescriptorRepository getRepository() {
1532: return m_repository;
1533: }
1534:
1535: /**
1536: * Sets the repository.
1537: * @param repository The repository to set
1538: */
1539: public void setRepository(DescriptorRepository repository) {
1540: m_repository = repository;
1541: }
1542:
1543: /**
1544: * returns the transaction isolation level to be used for this class. Used only in the ODMG server
1545: */
1546: public int getIsolationLevel() {
1547: return m_IsolationLevel;
1548: }
1549:
1550: /**
1551: * Method declaration
1552: * @param isoLevel
1553: */
1554: public void setIsolationLevel(int isoLevel) {
1555: m_IsolationLevel = isoLevel;
1556: }
1557:
1558: /**
1559: * Method declaration
1560: * @return table name
1561: */
1562: private String getTableName() {
1563: return m_TableName;
1564: }
1565:
1566: /**
1567: * Method declaration
1568: * @param str
1569: */
1570: public void setTableName(String str) {
1571: m_TableName = str;
1572: }
1573:
1574: /**
1575: * Answer Table name including schema BRJ
1576: */
1577: public String getFullTableName() {
1578: if (getSchema() != null)
1579: return getSchema() + "." + getTableName();
1580: else
1581: return getTableName();
1582: }
1583:
1584: /**
1585: * Gets the schema.
1586: * @return Returns a String
1587: */
1588: public String getSchema() {
1589: return schema;
1590: }
1591:
1592: /**
1593: * Sets the schema.
1594: * @param schema The schema to set
1595: */
1596: public void setSchema(String schema) {
1597: this .schema = schema;
1598: }
1599:
1600: /**
1601: * Return a string representation of this class.
1602: */
1603: public String toString() {
1604: ToStringBuilder buf = new ToStringBuilder(this ,
1605: ToStringStyle.MULTI_LINE_STYLE);
1606: return buf.append("classNameOfObject", getClassNameOfObject())
1607: .append("tableName", getTableName()).append("schema",
1608: getSchema()).append("isInterface",
1609: isInterface()).append("extendClassNames",
1610: getExtentClassNames().toString())
1611: //.append("[fieldDescriptions:")
1612: .append(getFieldDescriptions())
1613: //.append("]")
1614: .toString();
1615: }
1616:
1617: /**
1618: * sets the initialization method for this descriptor
1619: */
1620: private synchronized void setInitializationMethod(Method newMethod) {
1621: if (newMethod != null) {
1622: // make sure it's a no argument method
1623: if (newMethod.getParameterTypes().length > 0) {
1624: throw new MetadataException(
1625: "Initialization methods must be zero argument methods: "
1626: + newMethod.getClass().getName() + "."
1627: + newMethod.getName());
1628: }
1629:
1630: // make it accessible if it's not already
1631: if (!newMethod.isAccessible()) {
1632: newMethod.setAccessible(true);
1633: }
1634: }
1635: this .initializationMethod = newMethod;
1636: }
1637:
1638: /**
1639: * sets the initialization method for this descriptor by name
1640: */
1641: public synchronized void setInitializationMethod(
1642: String newMethodName) {
1643: Method newMethod = null;
1644: if (newMethodName != null) {
1645: initializationMethodName = newMethodName;
1646: try {
1647: // see if we have a publicly accessible method by the name
1648: newMethod = getClassOfObject().getMethod(newMethodName,
1649: NO_PARAMS);
1650: } catch (NoSuchMethodException e) {
1651: try {
1652: // no publicly accessible method, see if there is a private/protected one
1653: newMethod = getClassOfObject().getDeclaredMethod(
1654: newMethodName, NO_PARAMS);
1655: } catch (NoSuchMethodException e2) {
1656: // there is no such method available
1657: throw new MetadataException(
1658: "Invalid initialization method, there is not"
1659: + " a zero argument method named "
1660: + newMethodName + " on class "
1661: + getClassOfObject().getName()
1662: + ".");
1663: }
1664: }
1665: }
1666: setInitializationMethod(newMethod);
1667: }
1668:
1669: /**
1670: * Returns the initialization method for this descriptor or null if no
1671: * initialization method is defined.
1672: */
1673: public synchronized Method getInitializationMethod() {
1674: if (this .initializationMethod == null) {
1675: setInitializationMethod(initializationMethodName);
1676: }
1677: return initializationMethod;
1678: }
1679:
1680: /**
1681: * if true instances of this class are always refreshed
1682: * even if they are already in the cache.
1683: * @return boolean
1684: */
1685: public boolean isAlwaysRefresh() {
1686: return alwaysRefresh;
1687: }
1688:
1689: /**
1690: * Sets the alwaysRefresh parameter.
1691: * @param alwaysRefresh The value to set
1692: */
1693: public void setAlwaysRefresh(boolean alwaysRefresh) {
1694: this .alwaysRefresh = alwaysRefresh;
1695: }
1696:
1697: public int getProxyPrefetchingLimit() {
1698: return m_ProxyPrefetchingLimit;
1699: }
1700:
1701: public void setProxyPrefetchingLimit(int proxyPrefetchingLimit) {
1702: m_ProxyPrefetchingLimit = proxyPrefetchingLimit;
1703: }
1704:
1705: /**
1706: * Return factory class.
1707: */
1708: public synchronized Class getFactoryClass() {
1709: return this .factoryClass;
1710: }
1711:
1712: /**
1713: * Return factory method.
1714: */
1715: public synchronized Method getFactoryMethod() {
1716: if (factoryMethod == null && factoryMethodName != null) {
1717: setFactoryMethod(factoryMethodName);
1718: }
1719: return this .factoryMethod;
1720: }
1721:
1722: /**
1723: * Set the object factory for class described by this
1724: * descriptor.
1725: * @see #setFactoryMethod
1726: */
1727: public synchronized void setFactoryClass(Class newClass) {
1728: this .factoryClass = newClass;
1729: }
1730:
1731: /**
1732: * @see #setFactoryClass
1733: */
1734: public void setFactoryClass(String newClass) {
1735: if (null != newClass) {
1736: try {
1737: Class clazz = ClassHelper.getClass(newClass);
1738: setFactoryClass(clazz);
1739: } catch (Exception e) {
1740: // there is no such method available
1741: throw new MetadataException("Invalid factory class: "
1742: + newClass + ".");
1743: }
1744: } else {
1745: setFactoryClass((Class) null);
1746: }
1747: }
1748:
1749: /**
1750: * Specify the method to instantiate objects
1751: * represented by this descriptor.
1752: * @see #setFactoryClass
1753: */
1754: private synchronized void setFactoryMethod(Method newMethod) {
1755: if (newMethod != null) {
1756: // make sure it's a no argument method
1757: if (newMethod.getParameterTypes().length > 0) {
1758: throw new MetadataException(
1759: "Factory methods must be zero argument methods: "
1760: + newMethod.getClass().getName() + "."
1761: + newMethod.getName());
1762: }
1763:
1764: // make it accessible if it's not already
1765: if (!newMethod.isAccessible()) {
1766: newMethod.setAccessible(true);
1767: }
1768: }
1769:
1770: this .factoryMethod = newMethod;
1771: }
1772:
1773: /**
1774: * sets the initialization method for this descriptor by name
1775: */
1776: public synchronized void setFactoryMethod(String factoryMethodName) {
1777: Method newMethod = null;
1778: this .factoryMethodName = factoryMethodName;
1779:
1780: if (factoryMethodName != null) {
1781: try {
1782: // see if we have a publicly accessible method by the name
1783: newMethod = getFactoryClass().getMethod(
1784: factoryMethodName, NO_PARAMS);
1785: } catch (NoSuchMethodException e) {
1786: try {
1787: // no publicly accessible method, see if there is a private/protected one
1788: newMethod = getFactoryClass().getDeclaredMethod(
1789: factoryMethodName, NO_PARAMS);
1790: } catch (NoSuchMethodException e2) {
1791: // there is no such method available
1792: throw new MetadataException(
1793: "Invalid factory method, there is not"
1794: + " a zero argument method named "
1795: + factoryMethodName + " on class "
1796: + getFactoryClass().getName() + ".");
1797: }
1798: }
1799: }
1800: setFactoryMethod(newMethod);
1801: }
1802:
1803: //---------------------------------------------------------------
1804: /**
1805: * Change the descriptor for the insert procedure/function.
1806: *
1807: * @param newValue the new value.
1808: */
1809: public void setInsertProcedure(InsertProcedureDescriptor newValue) {
1810: this .insertProcedure = newValue;
1811: }
1812:
1813: //---------------------------------------------------------------
1814: /**
1815: * Retrieve the descriptor for the insert procedure/function.
1816: *
1817: * @return The current value
1818: */
1819: public InsertProcedureDescriptor getInsertProcedure() {
1820: return this .insertProcedure;
1821: }
1822:
1823: //---------------------------------------------------------------
1824: /**
1825: * Change the descriptor for the update procedure/function.
1826: *
1827: * @param newValue the new value.
1828: */
1829: public void setUpdateProcedure(UpdateProcedureDescriptor newValue) {
1830: this .updateProcedure = newValue;
1831: }
1832:
1833: //---------------------------------------------------------------
1834: /**
1835: * Retrieve the descriptor for the update procedure/function.
1836: *
1837: * @return The current value
1838: */
1839: public UpdateProcedureDescriptor getUpdateProcedure() {
1840: return this .updateProcedure;
1841: }
1842:
1843: //---------------------------------------------------------------
1844: /**
1845: * Change the descriptor for the delete procedure/function.
1846: *
1847: * @param newValue the new value.
1848: */
1849: public void setDeleteProcedure(DeleteProcedureDescriptor newValue) {
1850: this .deleteProcedure = newValue;
1851: }
1852:
1853: //---------------------------------------------------------------
1854: /**
1855: * Retrieve the descriptor for the delete procedure/function.
1856: *
1857: * @return The current value
1858: */
1859: public DeleteProcedureDescriptor getDeleteProcedure() {
1860: return this .deleteProcedure;
1861: }
1862:
1863: /**
1864: * Returns the ojbConcreteClass field or <code>null</code> if none defined.
1865: */
1866: public FieldDescriptor getOjbConcreteClassField() {
1867: // if not checked before
1868: if (!ojbConcreteFieldCheckDone) {
1869: ojbConcreteClassField = getFieldDescriptorByName(OJB_CONCRETE_CLASS);
1870: ojbConcreteFieldCheckDone = true;
1871: }
1872: return ojbConcreteClassField;
1873: }
1874:
1875: public StatementsForClassIF getStatementsForClass(
1876: ConnectionManagerIF conMan) {
1877: if (statementsForClass == null) {
1878: statementsForClass = StatementsForClassFactory
1879: .getInstance().getStatementsForClass(
1880: conMan.getConnectionDescriptor(), this );
1881: }
1882: return statementsForClass;
1883: }
1884:
1885: /**
1886: * Optional! Set the {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField}
1887: * implementation class used by this class.
1888: * @param pfClassName The full qualified class name of the
1889: * {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField}.
1890: */
1891: public void setPersistentFieldClassName(String pfClassName) {
1892: this .persistentFieldClassName = pfClassName;
1893: }
1894:
1895: /**
1896: * Get the used {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField}
1897: * implementation name.
1898: */
1899: public String getPersistentFieldClassName() {
1900: return persistentFieldClassName;
1901: }
1902:
1903: /**
1904: * Returns <em>true</em> if an DB Identity column field based sequence
1905: * manager was used. In that cases we will find an autoincrement field with
1906: * read-only access and return true, otherwise false.
1907: */
1908: public boolean useIdentityColumnField() {
1909: if (useIdentityColumn == 0) {
1910: useIdentityColumn = -1;
1911: FieldDescriptor[] pkFields = getPkFields();
1912: for (int i = 0; i < pkFields.length; i++) {
1913: // to find the identity column we search for a autoincrement
1914: // read-only field
1915: if (pkFields[i].isAutoIncrement()
1916: && pkFields[i].isAccessReadOnly()) {
1917: useIdentityColumn = 1;
1918: break;
1919: }
1920: }
1921: }
1922: return useIdentityColumn == 1;
1923: }
1924:
1925: /**
1926: * Returns all defined {@link ObjectReferenceDescriptor}.
1927: *
1928: * @param withInherited If <em>true</em> inherited super class references will be included.
1929: */
1930: public List getObjectReferenceDescriptors(boolean withInherited) {
1931: if (withInherited && getSuperClassDescriptor() != null) {
1932: List result = new ArrayList(m_ObjectReferenceDescriptors);
1933: result.addAll(getSuperClassDescriptor()
1934: .getObjectReferenceDescriptors(true));
1935: return result;
1936: } else {
1937: return m_ObjectReferenceDescriptors;
1938: }
1939: }
1940:
1941: /**
1942: * Returns all defined {@link CollectionDescriptor} for
1943: * this class descriptor.
1944: *
1945: * @param withInherited If <em>true</em> inherited super class references will be included.
1946: */
1947: public List getCollectionDescriptors(boolean withInherited) {
1948: if (withInherited && getSuperClassDescriptor() != null) {
1949: List result = new ArrayList(m_CollectionDescriptors);
1950: result.addAll(getSuperClassDescriptor()
1951: .getCollectionDescriptors(true));
1952: return result;
1953: } else {
1954: return m_CollectionDescriptors;
1955: }
1956: }
1957:
1958: /**
1959: * Return an array of all {@link FieldDescriptor} for this represented class, if
1960: * parameter <em>withInherited</em> is <em>true</em> all inherited descriptor
1961: * of declared super classes are included.
1962: *
1963: * @param withInherited If <em>true</em> inherited super class fields will be included.
1964: */
1965: public FieldDescriptor[] getFieldDescriptor(boolean withInherited) {
1966: if (withInherited && getSuperClassDescriptor() != null) {
1967: /*
1968: arminw: only return no-PK fields, because all PK fields are declared
1969: in sub-class too.
1970: */
1971: FieldDescriptor[] super Flds = getSuperClassDescriptor()
1972: .getFieldDescriptorNonPk(true);
1973: if (m_FieldDescriptions == null) {
1974: m_FieldDescriptions = new FieldDescriptor[0];
1975: }
1976: FieldDescriptor[] result = new FieldDescriptor[m_FieldDescriptions.length
1977: + super Flds.length];
1978: System.arraycopy(m_FieldDescriptions, 0, result, 0,
1979: m_FieldDescriptions.length);
1980: System.arraycopy(super Flds, 0, result,
1981: m_FieldDescriptions.length, super Flds.length);
1982: // System.out.println("all fields: " + ArrayUtils.toString(result));
1983: return result;
1984: } else {
1985: return m_FieldDescriptions;
1986: }
1987: }
1988:
1989: /**
1990: * Return an array of NON-PK {@link FieldDescriptor}, if parameter <em>withInherited</em>
1991: * is <em>true</em> all inherited descriptor of declared super classes are included.
1992: *
1993: * @param withInherited If <em>true</em> inherited super class fields will be included.
1994: */
1995: public FieldDescriptor[] getFieldDescriptorNonPk(
1996: boolean withInherited) {
1997: if (withInherited && getSuperClassDescriptor() != null) {
1998: FieldDescriptor[] flds = getNonPkFields();
1999: FieldDescriptor[] super Flds = getSuperClassDescriptor()
2000: .getFieldDescriptorNonPk(true);
2001: FieldDescriptor[] result = new FieldDescriptor[flds.length
2002: + super Flds.length];
2003: System.arraycopy(flds, 0, result, 0, flds.length);
2004: System.arraycopy(super Flds, 0, result, flds.length,
2005: super Flds.length);
2006: return result;
2007: } else {
2008: return getNonPkFields();
2009: }
2010: }
2011:
2012: /**
2013: * Returns the {@link SuperReferenceDescriptor} of this class or <em>null</em>
2014: * if none was used.
2015: *
2016: * @return The reference descriptor for the <em>super</em>-reference or <em>null</em>
2017: * if not exists.
2018: */
2019: public SuperReferenceDescriptor getSuperReference() {
2020: return (SuperReferenceDescriptor) getObjectReferenceDescriptorByName(SuperReferenceDescriptor.SUPER_FIELD_INTERNAL_NAME);
2021: }
2022: }
|