Coverage Report - org.apache.ojb.broker.metadata.ClassDescriptor
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassDescriptor
N/A
N/A
2.555
 
 1  
 package org.apache.ojb.broker.metadata;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.lang.reflect.Constructor;
 20  
 import java.lang.reflect.Method;
 21  
 import java.lang.reflect.Modifier;
 22  
 import java.sql.Timestamp;
 23  
 import java.util.ArrayList;
 24  
 import java.util.Arrays;
 25  
 import java.util.Collection;
 26  
 import java.util.Collections;
 27  
 import java.util.HashMap;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 import java.util.Vector;
 32  
 
 33  
 import org.apache.commons.lang.builder.ToStringBuilder;
 34  
 import org.apache.commons.lang.builder.ToStringStyle;
 35  
 import org.apache.ojb.broker.PersistenceBrokerException;
 36  
 import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
 37  
 import org.apache.ojb.broker.accesslayer.RowReader;
 38  
 import org.apache.ojb.broker.accesslayer.RowReaderDefaultImpl;
 39  
 import org.apache.ojb.broker.accesslayer.StatementsForClassFactory;
 40  
 import org.apache.ojb.broker.accesslayer.StatementsForClassIF;
 41  
 import org.apache.ojb.broker.core.ValueContainer;
 42  
 import org.apache.ojb.broker.locking.IsolationLevels;
 43  
 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
 44  
 import org.apache.ojb.broker.util.ClassHelper;
 45  
 import org.apache.ojb.broker.util.SqlHelper;
 46  
 import org.apache.ojb.broker.util.configuration.Configuration;
 47  
 import org.apache.ojb.broker.util.configuration.Configurator;
 48  
 import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
 49  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 50  
 
 51  
 
 52  
 /**
 53  
  * A ClassDescriptor contains all information for mapping objects of a
 54  
  * given class to database tables.
 55  
  * <br>
 56  
  * Note: Be careful when use ClassDescriptor variables or caching
 57  
  * ClassDescriptor instances, because instances could become invalid
 58  
  * during runtime (see {@link MetadataManager}).
 59  
  *
 60  
  * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
 61  
  * @version $Id: ClassDescriptor.java,v 1.1 2007-08-24 22:17:29 ewestfal Exp $
 62  
  */
 63  
 public final class ClassDescriptor extends DescriptorBase
 64  
     implements Serializable, XmlCapable, IsolationLevels
 65  
 {
 66  
         private String persistentFieldClassName;
 67  
 
 68  
     private static final long serialVersionUID = -5212253607374173965L;
 69  
 
 70  
     public static final String DYNAMIC_STR = "dynamic";
 71  
     public static final String OJB_CONCRETE_CLASS = "ojbConcreteClass";
 72  
     private static final Class[] NO_PARAMS = {};
 73  
 
 74  
     //---------------------------------------------------------------
 75  
     /**
 76  
      * The descriptor for the insert procedure/function.
 77  
      */
 78  
     private InsertProcedureDescriptor insertProcedure;
 79  
 
 80  
     //---------------------------------------------------------------
 81  
     /**
 82  
      * The descriptor for the update procedure/function.
 83  
      */
 84  
     private UpdateProcedureDescriptor updateProcedure;
 85  
 
 86  
     //---------------------------------------------------------------
 87  
     /**
 88  
      * The descriptor for the delete procedure/function.
 89  
      */
 90  
     private DeleteProcedureDescriptor deleteProcedure;
 91  
 
 92  
     //---------------------------------------------------------------
 93  
     // transient fields, to make this class serializable we have to declare
 94  
     // some transient fields and some associated string fields to reinitialze
 95  
     // transient fields after serialization
 96  
     //---------------------------------------------------------------
 97  
     /**
 98  
      * optional method to be invoked after instance fields are initialized
 99  
      */
 100  
     private transient Method initializationMethod;
 101  
     private String initializationMethodName;
 102  
 
 103  
     private transient Method factoryMethod;
 104  
     private String factoryMethodName;
 105  
     /**
 106  
      * whether we have already tried to look up the zero
 107  
      * argument constructor. Transient declared, because
 108  
      * {@link Constructor} is transient and we need to
 109  
      * reinitialize constructor after serialization.
 110  
      */
 111  
     private transient boolean alreadyLookedupZeroArguments = false;
 112  
     /**
 113  
      * the zero argument constructor for this class
 114  
      */
 115  
     private transient Constructor zeroArgumentConstructor = null;
 116  
 
 117  
     /**
 118  
      * used to signal use of ojbConcreteClass field
 119  
      */
 120  
     private transient boolean ojbConcreteFieldCheckDone = false;
 121  
     private transient FieldDescriptor ojbConcreteClassField;
 122  
     /**
 123  
      * We have to bound {@link org.apache.ojb.broker.accesslayer.StatementsForClassIF}
 124  
      * instance to this class, because metadata may change.
 125  
      */
 126  
     private transient StatementsForClassIF statementsForClass;
 127  
     //---------------------------------------------------------------
 128  
     // end transient fields
 129  
     //---------------------------------------------------------------
 130  
 
 131  
     private DescriptorRepository m_repository;
 132  
     /**
 133  
      * optional class.method to be invoked to create object instance.  Both
 134  
      * of these must be present for this function to be successful.
 135  
      */
 136  
     private Class factoryClass;
 137  
     private int useIdentityColumn = 0;
 138  
 
 139  
     private String baseClass = null;
 140  
     /**
 141  
      * transaction isolation level specified for this class, used in the ODMG server
 142  
      */
 143  
     private int m_IsolationLevel;
 144  
     /**
 145  
      * the SQL SCHEMA of the underlying table of this class
 146  
      */
 147  
     private String schema = null;
 148  
     /**
 149  
      * the described class
 150  
      */
 151  
     private Class m_Class = null;
 152  
     /**
 153  
      * whether the described class is abstract
 154  
      */
 155  
     private boolean isAbstract = false;
 156  
     /**
 157  
      * the table name used to store the scalar attributes of this class
 158  
      */
 159  
     private String m_TableName = null;
 160  
 //    private Vector superPersistentFieldDescriptors = null;
 161  
     /**
 162  
      * the RowReader for this class
 163  
      */
 164  
     private RowReader m_rowReader = null;
 165  
 /*
 166  
 arminw:
 167  
 TODO: this feature doesn't work, so remove/reuse this in future
 168  
 */
 169  
     /**
 170  
      * the class that this class extends
 171  
      */
 172  
     private String superClass;
 173  
     /**
 174  
      * reference column for the superclass
 175  
      */
 176  
     private int superClassFieldRef;
 177  
     /**
 178  
      * does the described class represent an interface?
 179  
      */
 180  
     private boolean m_isInterface = false;
 181  
     /**
 182  
      * the proxy class for the described class, may be null
 183  
      */
 184  
     private Class proxyClass = null;
 185  
     /**
 186  
      * the proxy class name for the described class, may be null
 187  
      */
 188  
     private String proxyClassName = null;
 189  
     /**
 190  
      * if false do not accept implicit locks on this class
 191  
      */
 192  
     private boolean acceptLocks = true;
 193  
     /**
 194  
      * if true instances of this class are always refreshed
 195  
      * even if they are already in the cache.
 196  
      * false by default.
 197  
      */
 198  
     private boolean alwaysRefresh = false;
 199  
     private int m_ProxyPrefetchingLimit = 50;
 200  
     /**
 201  
      * optional, ObjectCacheDescriptor for representing class
 202  
      */
 203  
     private ObjectCacheDescriptor objectCacheDescriptor;
 204  
     /**
 205  
      * the vector of indices used in DDL generation.
 206  
      */
 207  
     private Vector indexes = new Vector();
 208  
 
 209  
     //-----------------------------------------------------------------
 210  
     //-----------------------------------------------------------------
 211  
     // !!! the following arrays and maps have take care of metadata changes!!!
 212  
     //-----------------------------------------------------------------
 213  
     //-----------------------------------------------------------------
 214  
     private FieldDescriptor m_autoIncrementField = null;
 215  
     /**
 216  
      * the FieldDescriptors for the primitive attributes
 217  
      */
 218  
     private FieldDescriptor[] m_FieldDescriptions = null;
 219  
     /**
 220  
      * the descriptors for collection attributes
 221  
      */
 222  
     private Vector m_CollectionDescriptors = new Vector();
 223  
     /**
 224  
      * the descriptor for 1-1 reference attributes
 225  
      */
 226  
     private Vector m_ObjectReferenceDescriptors = new Vector();
 227  
     /**
 228  
      * the non-primary key FieldDescriptors
 229  
      */
 230  
     private FieldDescriptor[] m_nonPkFieldDescriptors = null;
 231  
     /**
 232  
      * the primary key FieldDescriptors
 233  
      */
 234  
     private FieldDescriptor[] m_PkFieldDescriptors = null;
 235  
     /**
 236  
      * the read/write FieldDescriptors BRJ
 237  
      */
 238  
     private FieldDescriptor[] m_RwFieldDescriptors = null;
 239  
     private FieldDescriptor[] m_RwNonPkFieldDescriptors = null;
 240  
     /**
 241  
      * the optimistic lockingFieldDescriptors BRJ
 242  
      */
 243  
     private FieldDescriptor[] m_lockingFieldDescriptors = null;
 244  
     /**
 245  
      * the list of classes in the extent of this class. can be empty
 246  
      */
 247  
     private Vector extentClasses = new Vector();
 248  
     /**
 249  
      * the list of class names in the extent of this class. can be empty
 250  
      */
 251  
     private Vector extentClassNames = new Vector();
 252  
     private Map m_fieldDescriptorNameMap = null;
 253  
     private Map m_collectionDescriptorNameMap = null;
 254  
     private Map m_objectReferenceDescriptorsNameMap = null;
 255  
 
 256  
     // BRJ: ClassDescriptor referenced by 'super' ObjectReferenceDescriptor
 257  
     private ClassDescriptor m_superCld = null;
 258  
     private boolean m_superCldSet = false;
 259  
 
 260  
     //-----------------------------------------------------------------
 261  
     //-----------------------------------------------------------------
 262  
     // END of cached metadata information
 263  
     //-----------------------------------------------------------------
 264  
     //-----------------------------------------------------------------
 265  
 
 266  
 
 267  
     //---------------------------------------------------------------
 268  
     /**
 269  
      * Constructor declaration
 270  
      */
 271  
     public ClassDescriptor(DescriptorRepository pRepository)
 272  
     {
 273  
         m_repository = pRepository;
 274  
         m_IsolationLevel = pRepository.getDefaultIsolationLevel();
 275  
     }
 276  
 
 277  
 
 278  
     //---------------------------------------------------------------
 279  
     // method declarations
 280  
     //---------------------------------------------------------------
 281  
     public String getBaseClass()
 282  
     {
 283  
         return baseClass;
 284  
     }
 285  
     public void setBaseClass(String baseClass)
 286  
     {
 287  
         this.baseClass = baseClass;
 288  
         // first deregister
 289  
         getRepository().deregisterSuperClassMultipleJoinedTables(this);
 290  
         // register classes using mapping of classes to multiple joined tables
 291  
         getRepository().registerSuperClassMultipleJoinedTables(this);
 292  
     }
 293  
 
 294  
 //    /**
 295  
 //     * @deprecated no longer needed map class on multi joined table
 296  
 //     */
 297  
 //    public void setSuperPersistentFieldDescriptors(Vector superPersistentFieldDescriptors)
 298  
 //    {
 299  
 //        this.superPersistentFieldDescriptors = superPersistentFieldDescriptors;
 300  
 //    }
 301  
 //
 302  
 //    /**
 303  
 //     * @deprecated no longer needed map class on multi joined table
 304  
 //     */
 305  
 //    public Vector getSuperPersistentFieldDescriptors()
 306  
 //    {
 307  
 //        return superPersistentFieldDescriptors;
 308  
 //    }
 309  
 
 310  
     /**
 311  
      * Returns the appropriate {@link ObjectCacheDescriptor}
 312  
      * or <code>null</code> if not specified.
 313  
      */
 314  
     public ObjectCacheDescriptor getObjectCacheDescriptor()
 315  
     {
 316  
         return objectCacheDescriptor;
 317  
     }
 318  
 
 319  
     /**
 320  
      * Sets the {@link ObjectCacheDescriptor} for representing class.
 321  
      */
 322  
     public void setObjectCacheDescriptor(ObjectCacheDescriptor objectCacheDescriptor)
 323  
     {
 324  
         this.objectCacheDescriptor = objectCacheDescriptor;
 325  
     }
 326  
 
 327  
 
 328  
     /**
 329  
      * sets the row reader class for this descriptor
 330  
      */
 331  
     public void setRowReader(RowReader newReader)
 332  
     {
 333  
         m_rowReader = newReader;
 334  
     }
 335  
 
 336  
     /**
 337  
      * Returns the {@link org.apache.ojb.broker.accesslayer.RowReader}
 338  
      * for this descriptor.
 339  
      */
 340  
     public synchronized RowReader getRowReader()
 341  
     {
 342  
         if (m_rowReader == null)
 343  
         {
 344  
             Configurator configurator = OjbConfigurator.getInstance();
 345  
             Configuration config = configurator.getConfigurationFor(null);
 346  
             Class rrClass = config.getClass("RowReaderDefaultClass", RowReaderDefaultImpl.class);
 347  
 
 348  
             setRowReader(rrClass.getName());
 349  
         }
 350  
         return m_rowReader;
 351  
     }
 352  
 
 353  
     /**
 354  
      * sets the row reader class name for thie class descriptor
 355  
      */
 356  
     public void setRowReader(String newReaderClassName)
 357  
     {
 358  
         try
 359  
         {
 360  
             m_rowReader =
 361  
                 (RowReader) ClassHelper.newInstance(
 362  
                     newReaderClassName,
 363  
                     ClassDescriptor.class,
 364  
                     this);
 365  
         }
 366  
         catch (Exception e)
 367  
         {
 368  
             throw new MetadataException("Instantiating of current set RowReader failed", e);
 369  
         }
 370  
     }
 371  
 
 372  
     public String getRowReaderClassName()
 373  
     {
 374  
         return m_rowReader != null ? m_rowReader.getClass().getName() : null;
 375  
     }
 376  
 
 377  
     /**
 378  
      * returns the name of the described class
 379  
      * @return String name of the described class
 380  
      */
 381  
     public String getClassNameOfObject()
 382  
     {
 383  
         return m_Class != null ? m_Class.getName() : null;
 384  
     }
 385  
 
 386  
     /**
 387  
      * returns the class object of the described class
 388  
      * @return Class the described class
 389  
      */
 390  
     public Class getClassOfObject()
 391  
     {
 392  
         return m_Class;
 393  
     }
 394  
 
 395  
     /**
 396  
      * sets the class object described by this descriptor.
 397  
      * @param c the class to describe
 398  
      */
 399  
     public void setClassOfObject(Class c)
 400  
     {
 401  
         m_Class = c;
 402  
         isAbstract = Modifier.isAbstract(m_Class.getModifiers());
 403  
         // TODO : Shouldn't the HashMap in DescriptorRepository be updated as well?
 404  
     }
 405  
 
 406  
     /**
 407  
      * adds a FIELDDESCRIPTOR to this ClassDescriptor.
 408  
      * @param fld
 409  
      */
 410  
     public void addFieldDescriptor(FieldDescriptor fld)
 411  
     {
 412  
         fld.setClassDescriptor(this); // BRJ
 413  
         if (m_FieldDescriptions == null)
 414  
         {
 415  
             m_FieldDescriptions = new FieldDescriptor[1];
 416  
             m_FieldDescriptions[0] = fld;
 417  
         }
 418  
         else
 419  
         {
 420  
             int size = m_FieldDescriptions.length;
 421  
             FieldDescriptor[] tmpArray = new FieldDescriptor[size + 1];
 422  
             System.arraycopy(m_FieldDescriptions, 0, tmpArray, 0, size);
 423  
             tmpArray[size] = fld;
 424  
             m_FieldDescriptions = tmpArray;
 425  
             // 2. Sort fields according to their getOrder() Property
 426  
             Arrays.sort(m_FieldDescriptions, FieldDescriptor.getComparator());
 427  
         }
 428  
 
 429  
         m_fieldDescriptorNameMap = null;
 430  
         m_PkFieldDescriptors = null;
 431  
         m_nonPkFieldDescriptors = null;
 432  
         m_lockingFieldDescriptors = null;
 433  
         m_RwFieldDescriptors = null;
 434  
         m_RwNonPkFieldDescriptors = null;
 435  
     }
 436  
 
 437  
     public boolean removeFieldDescriptor(FieldDescriptor fld)
 438  
     {
 439  
         boolean result = false;
 440  
         if(m_FieldDescriptions == null) return result;
 441  
 
 442  
         List list = new ArrayList(Arrays.asList(m_FieldDescriptions));
 443  
         result = list.remove(fld);
 444  
         m_FieldDescriptions = (FieldDescriptor[]) list.toArray(new FieldDescriptor[list.size()]);
 445  
 
 446  
         m_fieldDescriptorNameMap = null;
 447  
         m_PkFieldDescriptors = null;
 448  
         m_nonPkFieldDescriptors = null;
 449  
         m_lockingFieldDescriptors = null;
 450  
         m_RwFieldDescriptors = null;
 451  
         m_RwNonPkFieldDescriptors = null;
 452  
         return result;
 453  
     }
 454  
 
 455  
     /**
 456  
      * Returns all defined {@link CollectionDescriptor} for
 457  
      * this class descriptor.
 458  
      */
 459  
     public Vector getCollectionDescriptors()
 460  
     {
 461  
         return m_CollectionDescriptors;
 462  
     }
 463  
 
 464  
     /**
 465  
      * Add a {@link CollectionDescriptor}.
 466  
      */
 467  
     public void addCollectionDescriptor(CollectionDescriptor cod)
 468  
     {
 469  
         m_CollectionDescriptors.add(cod);
 470  
         cod.setClassDescriptor(this); // BRJ
 471  
 
 472  
         m_collectionDescriptorNameMap = null;
 473  
     }
 474  
 
 475  
     public void removeCollectionDescriptor(CollectionDescriptor cod)
 476  
     {
 477  
         m_CollectionDescriptors.remove(cod);
 478  
         m_collectionDescriptorNameMap = null;
 479  
     }
 480  
 
 481  
     /**
 482  
      * Returns all defined {@link ObjectReferenceDescriptor}.
 483  
      */
 484  
     public Vector getObjectReferenceDescriptors()
 485  
     {
 486  
         return m_ObjectReferenceDescriptors;
 487  
     }
 488  
 
 489  
     /**
 490  
      * Add a {@link ObjectReferenceDescriptor}.
 491  
      */
 492  
     public void addObjectReferenceDescriptor(ObjectReferenceDescriptor ord)
 493  
     {
 494  
         m_ObjectReferenceDescriptors.add(ord);
 495  
         ord.setClassDescriptor(this); // BRJ
 496  
 
 497  
         m_objectReferenceDescriptorsNameMap = null;
 498  
     }
 499  
 
 500  
     public void removeObjectReferenceDescriptor(ObjectReferenceDescriptor ord)
 501  
     {
 502  
         m_ObjectReferenceDescriptors.remove(ord);
 503  
         m_objectReferenceDescriptorsNameMap = null;
 504  
     }
 505  
 
 506  
     /**
 507  
      * Get an ObjectReferenceDescriptor by name BRJ
 508  
      * @param name
 509  
      * @return ObjectReferenceDescriptor or null
 510  
      */
 511  
     public ObjectReferenceDescriptor getObjectReferenceDescriptorByName(String name)
 512  
     {
 513  
         ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor)
 514  
             getObjectReferenceDescriptorsNameMap().get(name);
 515  
 
 516  
         //
 517  
         // BRJ: if the ReferenceDescriptor is not found
 518  
         // look in the ClassDescriptor referenced by 'super' for it
 519  
         //
 520  
         if (ord == null)
 521  
         {
 522  
             ClassDescriptor superCld = getSuperClassDescriptor();
 523  
             if (superCld != null)
 524  
             {
 525  
                 ord = superCld.getObjectReferenceDescriptorByName(name);
 526  
             }
 527  
         }
 528  
         return ord;
 529  
     }
 530  
 
 531  
     private Map getObjectReferenceDescriptorsNameMap()
 532  
     {
 533  
         if (m_objectReferenceDescriptorsNameMap == null)
 534  
         {
 535  
             HashMap nameMap = new HashMap();
 536  
 
 537  
             Vector descriptors = getObjectReferenceDescriptors();
 538  
             for (int i = descriptors.size() - 1; i >= 0; i--)
 539  
             {
 540  
                 ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) descriptors.get(i);
 541  
                 nameMap.put(ord.getAttributeName(), ord);
 542  
             }
 543  
             m_objectReferenceDescriptorsNameMap = nameMap;
 544  
         }
 545  
 
 546  
         return m_objectReferenceDescriptorsNameMap;
 547  
     }
 548  
 
 549  
     /**
 550  
      * Get an CollectionDescriptor by name  BRJ
 551  
      * @param name
 552  
      * @return CollectionDescriptor or null
 553  
      */
 554  
     public CollectionDescriptor getCollectionDescriptorByName(String name)
 555  
     {
 556  
         if (name == null)
 557  
         {
 558  
             return null;
 559  
         }
 560  
 
 561  
         CollectionDescriptor cod  = (CollectionDescriptor) getCollectionDescriptorNameMap().get(name);
 562  
 
 563  
         //
 564  
         // BRJ: if the CollectionDescriptor is not found
 565  
         // look in the ClassDescriptor referenced by 'super' for it
 566  
         //
 567  
         if (cod == null)
 568  
         {
 569  
             ClassDescriptor superCld = getSuperClassDescriptor();
 570  
             if (superCld != null)
 571  
             {
 572  
                 cod = superCld.getCollectionDescriptorByName(name);
 573  
             }
 574  
         }
 575  
 
 576  
         return cod;
 577  
     }
 578  
 
 579  
     private Map getCollectionDescriptorNameMap()
 580  
     {
 581  
         if (m_collectionDescriptorNameMap == null)
 582  
         {
 583  
             HashMap nameMap = new HashMap();
 584  
 
 585  
             Vector descriptors = getCollectionDescriptors();
 586  
             for (int i = descriptors.size() - 1; i >= 0; i--)
 587  
             {
 588  
                 CollectionDescriptor cod = (CollectionDescriptor) descriptors.get(i);
 589  
                 nameMap.put(cod.getAttributeName(), cod);
 590  
             }
 591  
             m_collectionDescriptorNameMap = nameMap;
 592  
         }
 593  
 
 594  
         return m_collectionDescriptorNameMap;
 595  
     }
 596  
 
 597  
     /**
 598  
      * Answers the ClassDescriptor referenced by 'super' ReferenceDescriptor.
 599  
      * @return ClassDescriptor or null
 600  
      */
 601  
     public ClassDescriptor getSuperClassDescriptor()
 602  
     {
 603  
         if (!m_superCldSet)
 604  
         {
 605  
             if(getBaseClass() != null)
 606  
             {
 607  
                 m_superCld = getRepository().getDescriptorFor(getBaseClass());
 608  
                 if(m_superCld.isAbstract() || m_superCld.isInterface())
 609  
                 {
 610  
                     throw new MetadataException("Super class mapping only work for real class, but declared super class" +
 611  
                             " is an interface or is abstract. Declared class: " + m_superCld.getClassNameOfObject());
 612  
                 }
 613  
             }
 614  
             m_superCldSet = true;
 615  
         }
 616  
 
 617  
         return m_superCld;
 618  
     }
 619  
 
 620  
     /**
 621  
      * add an Extent class to the current descriptor
 622  
      * @param newExtendClass
 623  
      * @deprecated use {@link #addExtentClass(String newExtentClass)} instead
 624  
      */
 625  
     public void addExtentClassName(Class newExtendClass)
 626  
     {
 627  
         addExtentClass(newExtendClass);
 628  
     }
 629  
 
 630  
     /**
 631  
      * add an Extent class to the current descriptor
 632  
      * @param newExtendClass
 633  
      */
 634  
     public void addExtentClass(Class newExtendClass)
 635  
     {
 636  
         extentClasses.add(newExtendClass);
 637  
         this.addExtentClass(newExtendClass.getName());
 638  
     }
 639  
 
 640  
     /**
 641  
      * add an Extent class to the current descriptor
 642  
      * @param newExtentClassName name of the class to add
 643  
      */
 644  
     public void addExtentClass(String newExtentClassName)
 645  
     {
 646  
         extentClassNames.add(newExtentClassName);
 647  
         if(m_repository != null) m_repository.addExtent(newExtentClassName, this);
 648  
     }
 649  
 
 650  
     public void removeExtentClass(String extentClassName)
 651  
     {
 652  
         extentClassNames.remove(extentClassName);
 653  
         if(m_repository != null) m_repository.removeExtent(extentClassName);
 654  
     }
 655  
 
 656  
     /**
 657  
      * return all classes in this extent.
 658  
      * Creation date: (02.02.2001 17:49:11)
 659  
      * @return java.util.Vector
 660  
      */
 661  
     public synchronized Vector getExtentClasses()
 662  
     {
 663  
         if (extentClassNames.size() != extentClasses.size())
 664  
         {
 665  
             extentClasses.clear();
 666  
             for (Iterator iter = extentClassNames.iterator(); iter.hasNext();)
 667  
             {
 668  
                 String classname = (String) iter.next();
 669  
                 Class extentClass;
 670  
                 try
 671  
                 {
 672  
                     extentClass = ClassHelper.getClass(classname);
 673  
                 }
 674  
                 catch (ClassNotFoundException e)
 675  
                 {
 676  
                     throw new MetadataException(
 677  
                         "Unable to load class ["
 678  
                             + classname
 679  
                             + "]. Make sure it is available on the classpath.",
 680  
                         e);
 681  
                 }
 682  
                 extentClasses.add(extentClass);
 683  
             }
 684  
         }
 685  
         return extentClasses;
 686  
     }
 687  
 
 688  
 
 689  
     /**
 690  
      * Return the names of all classes in this extent
 691  
      * @return java.util.Vector a Vector containing the fully qualified names
 692  
      * of all classes in this extent
 693  
      */
 694  
     public synchronized Vector getExtentClassNames()
 695  
     {
 696  
         return this.extentClassNames;
 697  
     }
 698  
 
 699  
     /**
 700  
      * Insert the method's description here.
 701  
      * Creation date: (02.02.2001 17:49:11)
 702  
      * @return boolean
 703  
      */
 704  
     public boolean isExtent()
 705  
     {
 706  
         return (getExtentClassNames().size() > 0);
 707  
     }
 708  
 
 709  
     /**
 710  
      * Insert the method's description here.
 711  
      * Creation date: (26.01.2001 09:20:09)
 712  
      * @return java.lang.Class
 713  
      */
 714  
     public synchronized Class getProxyClass()
 715  
     {
 716  
         if ((proxyClass == null) && (proxyClassName != null))
 717  
         {
 718  
             if (isDynamicProxy())
 719  
             {
 720  
                 /**
 721  
                  * AClute: Return the same class back if it is dynamic. This signifies
 722  
                  * that this class become the base to a generated sub-class, regadless
 723  
                  * of which Proxy implementation is used
 724  
                  */
 725  
                 return getClassOfObject();
 726  
             }
 727  
             else
 728  
             {
 729  
                 try
 730  
                 {
 731  
                     proxyClass = ClassHelper.getClass(proxyClassName);
 732  
                 }
 733  
                 catch (ClassNotFoundException e)
 734  
                 {
 735  
                     throw new MetadataException(e);
 736  
                 }
 737  
             }
 738  
         }
 739  
         return proxyClass;
 740  
     }
 741  
 
 742  
     public boolean isDynamicProxy()
 743  
     {
 744  
         return DYNAMIC_STR.equalsIgnoreCase(proxyClassName);
 745  
     }
 746  
 
 747  
     /**
 748  
      * Sets the proxy class to be used.
 749  
      * @param newProxyClass java.lang.Class
 750  
      */
 751  
     public void setProxyClass(Class newProxyClass)
 752  
     {
 753  
         proxyClass = newProxyClass;
 754  
         if (proxyClass == null)
 755  
         {
 756  
             setProxyClassName(null);
 757  
         }
 758  
         else
 759  
         {
 760  
             proxyClassName = proxyClass.getName();
 761  
         }
 762  
     }
 763  
 
 764  
     /**
 765  
      * Sets the name of the proxy class to be used.
 766  
      * using "dynamic" instead of a real classname
 767  
      * will result in usage of dynamic proxies.
 768  
      * @param newProxyClassName the classname or "dynamic"
 769  
      */
 770  
     public void setProxyClassName(String newProxyClassName)
 771  
     {
 772  
         proxyClassName = newProxyClassName;
 773  
     }
 774  
 
 775  
     /**
 776  
      * Get the name of the proxy class. This method doesn't try to access
 777  
      * the real class, so it can be called even if the class doesn't exist.
 778  
      */
 779  
     public String getProxyClassName()
 780  
     {
 781  
         return proxyClassName;
 782  
     }
 783  
 
 784  
     /**
 785  
      * Returns array of all FieldDescriptors.
 786  
      */
 787  
     public FieldDescriptor[] getFieldDescriptions()
 788  
     {
 789  
         return m_FieldDescriptions;
 790  
     }
 791  
 
 792  
     /**
 793  
      * Returns the matching {@link FieldDescriptor}.
 794  
      */
 795  
     public FieldDescriptor getFieldDescriptorByIndex(int index)
 796  
     {
 797  
         return m_FieldDescriptions[index - 1];
 798  
     }
 799  
 
 800  
     /**
 801  
      * Returns the matching {@link FieldDescriptor} - only fields
 802  
      * of the current class will be scanned, to include fields defined
 803  
      * the the super-classes too, use method {@link #getFieldDescriptor(boolean)}.
 804  
      */
 805  
     public FieldDescriptor getFieldDescriptorByName(String name)
 806  
     {
 807  
         if (name == null || m_FieldDescriptions == null)
 808  
         {
 809  
             return null;
 810  
         }
 811  
 
 812  
         if (m_fieldDescriptorNameMap == null)
 813  
         {
 814  
             HashMap nameMap = new HashMap();
 815  
 
 816  
             FieldDescriptor[] descriptors = getFieldDescriptions();
 817  
             for (int i = descriptors.length - 1; i >= 0; i--)
 818  
             {
 819  
                 FieldDescriptor fld = descriptors[i];
 820  
                 nameMap.put(fld.getPersistentField().getName(), fld);
 821  
             }
 822  
 
 823  
             m_fieldDescriptorNameMap = nameMap;
 824  
         }
 825  
 
 826  
         return (FieldDescriptor) m_fieldDescriptorNameMap.get(name);
 827  
     }
 828  
 
 829  
     /**
 830  
      * return the FieldDescriptor for the Attribute referenced in the path<br>
 831  
      * the path may contain simple attribut names, functions and path expressions
 832  
      * using relationships <br>
 833  
      * ie: name, avg(price), adress.street
 834  
      * @param aPath the path to the attribute
 835  
      * @param pathHints a Map containing the class to be used for a segment or <em>null</em>
 836  
      * if no segment was used.
 837  
      * @return the FieldDescriptor or null (ie: for m:n queries)
 838  
      */
 839  
     public FieldDescriptor getFieldDescriptorForPath(String aPath, Map pathHints)
 840  
     {
 841  
         ArrayList desc = getAttributeDescriptorsForPath(aPath, pathHints);
 842  
         FieldDescriptor fld = null;
 843  
         Object temp;
 844  
 
 845  
         if (!desc.isEmpty())
 846  
         {
 847  
             temp = desc.get(desc.size() - 1);
 848  
             if (temp instanceof FieldDescriptor)
 849  
             {
 850  
                 fld = (FieldDescriptor) temp;
 851  
             }
 852  
         }
 853  
         return fld;
 854  
     }
 855  
 
 856  
     /**
 857  
      * return the FieldDescriptor for the Attribute referenced in the path<br>
 858  
      * the path may contain simple attribut names, functions and path expressions
 859  
      * using relationships <br>
 860  
      * ie: name, avg(price), adress.street
 861  
      * @param aPath the path to the attribute
 862  
      * @return the FieldDescriptor or null (ie: for m:n queries)
 863  
      */
 864  
     public FieldDescriptor getFieldDescriptorForPath(String aPath)
 865  
     {
 866  
         return getFieldDescriptorForPath(aPath, null);
 867  
     }
 868  
 /*
 869  
 arminw:
 870  
 TODO: this feature doesn't work, so remove this in future
 871  
 */
 872  
     /**
 873  
      *
 874  
      * @return this classes FieldDescriptor's as well as it's parents and so on and so on
 875  
      */
 876  
     public FieldDescriptor[] getFieldDescriptorsInHeirarchy()
 877  
     {
 878  
         if (superClass == null)
 879  
         {
 880  
             return getFieldDescriptions();
 881  
         }
 882  
         ClassDescriptor cldSuper = getRepository().getDescriptorFor(superClass);
 883  
         return appendFieldDescriptorArrays(
 884  
             getFieldDescriptions(),
 885  
             cldSuper.getFieldDescriptorsInHeirarchy());
 886  
     }
 887  
 
 888  
     private FieldDescriptor[] appendFieldDescriptorArrays(
 889  
         FieldDescriptor[] fieldDescriptions,
 890  
         FieldDescriptor[] fieldDescriptorsInHeirarchy)
 891  
     {
 892  
         // take the 2 arrays and add them into one
 893  
         int size = fieldDescriptions.length + fieldDescriptorsInHeirarchy.length;
 894  
         FieldDescriptor[] newArray = new FieldDescriptor[size];
 895  
         System.arraycopy(fieldDescriptions, 0, newArray, 0, fieldDescriptions.length);
 896  
         System.arraycopy(fieldDescriptorsInHeirarchy, 0, newArray, fieldDescriptions.length, fieldDescriptorsInHeirarchy.length);
 897  
         return newArray;
 898  
     }
 899  
 
 900  
     /**
 901  
      * Returns the first found autoincrement field
 902  
      * defined in this class descriptor. Use carefully
 903  
      * when multiple autoincrement field were defined.
 904  
      * @deprecated does not make sense because it's possible to
 905  
      * define more than one autoincrement field. Alternative
 906  
      * see {@link #getAutoIncrementFields}
 907  
      */
 908  
     public FieldDescriptor getAutoIncrementField()
 909  
     {
 910  
         if (m_autoIncrementField == null)
 911  
         {
 912  
             FieldDescriptor[] fds = getPkFields();
 913  
 
 914  
             for (int i = 0; i < fds.length; i++)
 915  
             {
 916  
                 FieldDescriptor fd = fds[i];
 917  
                 if (fd.isAutoIncrement())
 918  
                 {
 919  
                     m_autoIncrementField = fd;
 920  
                     break;
 921  
                 }
 922  
             }
 923  
         }
 924  
         if (m_autoIncrementField == null)
 925  
         {
 926  
             LoggerFactory.getDefaultLogger().warn(
 927  
                 this.getClass().getName()
 928  
                     + ": "
 929  
                     + "Could not find autoincrement attribute for class: "
 930  
                     + this.getClassNameOfObject());
 931  
         }
 932  
         return m_autoIncrementField;
 933  
     }
 934  
 
 935  
     public FieldDescriptor[] getAutoIncrementFields()
 936  
     {
 937  
         ArrayList result = new ArrayList();
 938  
         for (int i = 0; i < m_FieldDescriptions.length; i++)
 939  
         {
 940  
             FieldDescriptor field = m_FieldDescriptions[i];
 941  
             if(field.isAutoIncrement()) result.add(field);
 942  
         }
 943  
         return (FieldDescriptor[]) result.toArray(new FieldDescriptor[result.size()]);
 944  
     }
 945  
 
 946  
     /**
 947  
      * returns an Array with an Objects CURRENT locking VALUES , BRJ
 948  
      * @throws PersistenceBrokerException if there is an erros accessing o field values
 949  
      */
 950  
     public ValueContainer[] getCurrentLockingValues(Object o) throws PersistenceBrokerException
 951  
     {
 952  
         FieldDescriptor[] fields = getLockingFields();
 953  
         ValueContainer[] result = new ValueContainer[fields.length];
 954  
         for (int i = 0; i < result.length; i++)
 955  
         {
 956  
             result[i] = new ValueContainer(fields[i].getPersistentField().get(o), fields[i].getJdbcType());
 957  
         }
 958  
         return result;
 959  
     }
 960  
 
 961  
     /**
 962  
      * updates the values for locking fields , BRJ
 963  
      * handles int, long, Timestamp
 964  
      * respects updateLock so locking field are only updated when updateLock is true
 965  
      * @throws PersistenceBrokerException if there is an erros accessing obj field values
 966  
      */
 967  
     public void updateLockingValues(Object obj) throws PersistenceBrokerException
 968  
     {
 969  
         FieldDescriptor[] fields = getLockingFields();
 970  
         for (int i = 0; i < fields.length; i++)
 971  
         {
 972  
             FieldDescriptor fmd = fields[i];
 973  
             if (fmd.isUpdateLock())
 974  
             {
 975  
                 PersistentField f = fmd.getPersistentField();
 976  
                 Object cv = f.get(obj);
 977  
                 // int
 978  
                 if ((f.getType() == int.class) || (f.getType() == Integer.class))
 979  
                 {
 980  
                     int newCv = 0;
 981  
                     if (cv != null)
 982  
                     {
 983  
                         newCv = ((Number) cv).intValue();
 984  
                     }
 985  
                     newCv++;
 986  
                     f.set(obj, new Integer(newCv));
 987  
                 }
 988  
                 // long
 989  
                 else if ((f.getType() == long.class) || (f.getType() == Long.class))
 990  
                 {
 991  
                     long newCv = 0;
 992  
                     if (cv != null)
 993  
                     {
 994  
                         newCv = ((Number) cv).longValue();
 995  
                     }
 996  
                     newCv++;
 997  
                     f.set(obj, new Long(newCv));
 998  
                 }
 999  
                 // Timestamp
 1000  
                 else if (f.getType() == Timestamp.class)
 1001  
                 {
 1002  
                     long newCv = System.currentTimeMillis();
 1003  
                     f.set(obj, new Timestamp(newCv));
 1004  
                 }
 1005  
             }
 1006  
         }
 1007  
     }
 1008  
 
 1009  
     /**
 1010  
      * return an array of NONPK-FieldDescription sorted ascending
 1011  
      * according to the field-descriptions getOrder() property
 1012  
      */
 1013  
     public FieldDescriptor[] getNonPkFields()
 1014  
     {
 1015  
         if (m_nonPkFieldDescriptors == null)
 1016  
         {
 1017  
             // 1. collect all Primary Key fields from Field list
 1018  
             Vector vec = new Vector();
 1019  
             for (int i = 0; i < m_FieldDescriptions.length; i++)
 1020  
             {
 1021  
                 FieldDescriptor fd = m_FieldDescriptions[i];
 1022  
                 if (!fd.isPrimaryKey())
 1023  
                 {
 1024  
                     vec.add(fd);
 1025  
                 }
 1026  
             }
 1027  
             // 2. Sort fields according to their getOrder() Property
 1028  
             Collections.sort(vec, FieldDescriptor.getComparator());
 1029  
             m_nonPkFieldDescriptors =
 1030  
                 (FieldDescriptor[]) vec.toArray(new FieldDescriptor[vec.size()]);
 1031  
         }
 1032  
         return m_nonPkFieldDescriptors;
 1033  
     }
 1034  
 
 1035  
     /**
 1036  
      * Return an array of PK FieldDescription sorted ascending
 1037  
      * according to the field-descriptions getOrder() property
 1038  
      */
 1039  
     public FieldDescriptor[] getPkFields()
 1040  
     {
 1041  
         if (m_PkFieldDescriptors == null)
 1042  
         {
 1043  
             // 1. collect all Primary Key fields from Field list
 1044  
             Vector vec = new Vector();
 1045  
             // 1.a if descriptor describes an interface: take PK fields from an implementors ClassDescriptor
 1046  
             if (m_isInterface)
 1047  
             {
 1048  
                 if (getExtentClasses().size() == 0)
 1049  
                 {
 1050  
                     throw new PersistenceBrokerException(
 1051  
                         "No Implementors declared for interface "
 1052  
                             + this.getClassOfObject().getName());
 1053  
                 }
 1054  
                 Class implementor = (Class) getExtentClasses().get(0);
 1055  
                 ClassDescriptor implCld = this.getRepository().getDescriptorFor(implementor);
 1056  
                 m_PkFieldDescriptors = implCld.getPkFields();
 1057  
             }
 1058  
             else
 1059  
             {
 1060  
                 FieldDescriptor[] fields;
 1061  
                 // 1.b if not an interface The classdescriptor must have FieldDescriptors
 1062  
                 fields = getFieldDescriptions();
 1063  
                 // now collect all PK fields
 1064  
                 for (int i = 0; i < fields.length; i++)
 1065  
                 {
 1066  
                     FieldDescriptor fd = fields[i];
 1067  
                     if (fd.isPrimaryKey())
 1068  
                     {
 1069  
                         vec.add(fd);
 1070  
                     }
 1071  
                 }
 1072  
                 // 2. Sort fields according to their getOrder() Property
 1073  
                 Collections.sort(vec, FieldDescriptor.getComparator());
 1074  
                 m_PkFieldDescriptors = (FieldDescriptor[]) vec.toArray(new FieldDescriptor[vec.size()]);
 1075  
             }
 1076  
         }
 1077  
         return m_PkFieldDescriptors;
 1078  
     }
 1079  
 
 1080  
     /**
 1081  
      * Returns array of read/write non pk FieldDescriptors.
 1082  
      */
 1083  
     public FieldDescriptor[] getNonPkRwFields()
 1084  
     {
 1085  
         if (m_RwNonPkFieldDescriptors == null)
 1086  
         {
 1087  
             FieldDescriptor[] fields = getNonPkFields();
 1088  
             Collection rwFields = new ArrayList();
 1089  
 
 1090  
             for (int i = 0; i < fields.length; i++)
 1091  
             {
 1092  
                 FieldDescriptor fd = fields[i];
 1093  
                 if (!fd.isAccessReadOnly())
 1094  
                 {
 1095  
                     rwFields.add(fd);
 1096  
                 }
 1097  
             }
 1098  
             m_RwNonPkFieldDescriptors =
 1099  
                 (FieldDescriptor[]) rwFields.toArray(new FieldDescriptor[rwFields.size()]);
 1100  
         }
 1101  
         return m_RwNonPkFieldDescriptors;
 1102  
     }
 1103  
 
 1104  
     /**
 1105  
      * Returns array of read/write FieldDescriptors.
 1106  
      */
 1107  
     public FieldDescriptor[] getAllRwFields()
 1108  
     {
 1109  
         if (m_RwFieldDescriptors == null)
 1110  
         {
 1111  
             FieldDescriptor[] fields = getFieldDescriptions();
 1112  
             Collection rwFields = new ArrayList();
 1113  
 
 1114  
             for (int i = 0; i < fields.length; i++)
 1115  
             {
 1116  
                 FieldDescriptor fd = fields[i];
 1117  
                 /*
 1118  
                 arminw: if locking is enabled and the increment of locking
 1119  
                 values is done by the database, the field is read-only
 1120  
                 */
 1121  
                 if(fd.isAccessReadOnly() || (fd.isLocking() && !fd.isUpdateLock()))
 1122  
                 {
 1123  
                     continue;
 1124  
                 }
 1125  
                 rwFields.add(fd);
 1126  
             }
 1127  
             m_RwFieldDescriptors =
 1128  
                 (FieldDescriptor[]) rwFields.toArray(new FieldDescriptor[rwFields.size()]);
 1129  
         }
 1130  
 
 1131  
         return m_RwFieldDescriptors;
 1132  
     }
 1133  
 
 1134  
     /**
 1135  
      * return an array of FieldDescription for optimistic locking sorted ascending
 1136  
      * according to the field-descriptions getOrder() property
 1137  
      */
 1138  
     public FieldDescriptor[] getLockingFields()
 1139  
     {
 1140  
         if (m_lockingFieldDescriptors == null)
 1141  
         {
 1142  
             // 1. collect all Primary Key fields from Field list
 1143  
             Vector vec = new Vector();
 1144  
             for (int i = 0; i < m_FieldDescriptions.length; i++)
 1145  
             {
 1146  
                 FieldDescriptor fd = m_FieldDescriptions[i];
 1147  
                 if (fd.isLocking())
 1148  
                 {
 1149  
                     vec.add(fd);
 1150  
                 }
 1151  
             }
 1152  
             // 2. Sort fields according to their getOrder() Property
 1153  
             Collections.sort(vec, FieldDescriptor.getComparator());
 1154  
             m_lockingFieldDescriptors =
 1155  
                 (FieldDescriptor[]) vec.toArray(new FieldDescriptor[vec.size()]);
 1156  
         }
 1157  
         return m_lockingFieldDescriptors;
 1158  
     }
 1159  
 
 1160  
     /**
 1161  
      * return true if optimistic locking is used
 1162  
      */
 1163  
     public boolean isLocking()
 1164  
     {
 1165  
         return getLockingFields().length > 0;
 1166  
     }
 1167  
 
 1168  
     /**
 1169  
      * return all AttributeDescriptors for the path<br>
 1170  
      * ie: partner.addresses.street returns a Collection of 3 AttributeDescriptors
 1171  
      * (ObjectReferenceDescriptor, CollectionDescriptor, FieldDescriptor)<br>
 1172  
      * ie: partner.addresses returns a Collection of 2 AttributeDescriptors
 1173  
      * (ObjectReferenceDescriptor, CollectionDescriptor)
 1174  
      * @param aPath the cleaned path to the attribute
 1175  
      * @return ArrayList of AttributeDescriptors
 1176  
      */
 1177  
     public ArrayList getAttributeDescriptorsForPath(String aPath)
 1178  
     {
 1179  
         return getAttributeDescriptorsForPath(aPath, new HashMap());
 1180  
     }
 1181  
 
 1182  
     /**
 1183  
      * return all AttributeDescriptors for the path<br>
 1184  
      * ie: partner.addresses.street returns a Collection of 3 AttributeDescriptors
 1185  
      * (ObjectReferenceDescriptor, CollectionDescriptor, FieldDescriptor)<br>
 1186  
      * ie: partner.addresses returns a Collection of 2 AttributeDescriptors
 1187  
      * (ObjectReferenceDescriptor, CollectionDescriptor)
 1188  
      * @param aPath the cleaned path to the attribute
 1189  
      * @param pathHints a Map containing the class to be used for a segment or <em>null</em>
 1190  
      * if no segment was used.
 1191  
      * @return ArrayList of AttributeDescriptors
 1192  
      */
 1193  
     public ArrayList getAttributeDescriptorsForPath(String aPath, Map pathHints)
 1194  
     {
 1195  
         return getAttributeDescriptorsForCleanPath(SqlHelper.cleanPath(aPath), pathHints);
 1196  
     }
 1197  
 
 1198  
     /**
 1199  
      * return all AttributeDescriptors for the path<br>
 1200  
      * ie: partner.addresses.street returns a Collection of 3 AttributeDescriptors
 1201  
      * (ObjectReferenceDescriptor, CollectionDescriptor, FieldDescriptor)<br>
 1202  
      * ie: partner.addresses returns a Collection of 2 AttributeDescriptors
 1203  
      * (ObjectReferenceDescriptor, CollectionDescriptor)
 1204  
      * @param aPath the cleaned path to the attribute
 1205  
      * @param pathHints a Map containing the class to be used for a segment or <em>null</em>
 1206  
      * if no segment is used.
 1207  
      * @return ArrayList of AttributeDescriptors
 1208  
      */
 1209  
     private ArrayList getAttributeDescriptorsForCleanPath(String aPath, Map pathHints)
 1210  
     {
 1211  
         ArrayList result = new ArrayList();
 1212  
         ClassDescriptor cld = this;
 1213  
         ObjectReferenceDescriptor ord;
 1214  
         FieldDescriptor fld;
 1215  
         String currPath = aPath;
 1216  
         String segment;
 1217  
         StringBuffer processedSegment = new StringBuffer();
 1218  
         int sepPos;
 1219  
         Class itemClass;
 1220  
 
 1221  
         while (currPath.length() > 0)
 1222  
         {
 1223  
             sepPos = currPath.indexOf(".");
 1224  
             if (sepPos >= 0)
 1225  
             {
 1226  
                 segment = currPath.substring(0, sepPos);
 1227  
                 currPath = currPath.substring(sepPos + 1);
 1228  
             }
 1229  
             else
 1230  
             {
 1231  
                 segment = currPath;
 1232  
                 currPath = "";
 1233  
             }
 1234  
 
 1235  
             if (processedSegment.length() > 0)
 1236  
             {
 1237  
                 processedSegment.append(".");
 1238  
             }
 1239  
             processedSegment.append(segment);
 1240  
 
 1241  
             // look for 1:1 or n:1 Relationship
 1242  
             ord = cld.getObjectReferenceDescriptorByName(segment);
 1243  
             if (ord == null)
 1244  
             {
 1245  
                 // look for 1:n or m:n Relationship
 1246  
                 ord = cld.getCollectionDescriptorByName(segment);
 1247  
             }
 1248  
 
 1249  
             if (ord != null)
 1250  
             {
 1251  
                 // BRJ : look for hints for the processed segment
 1252  
                 // ie: ref pointng to ClassA and ref.ref pointing to ClassC
 1253  
                 List hintClasses = pathHints != null ? (List) pathHints.get(processedSegment.toString()) : null;
 1254  
                 if (hintClasses != null && hintClasses.get(0) != null)
 1255  
                 {
 1256  
                     itemClass = (Class) hintClasses.get(0);
 1257  
                 }
 1258  
                 else
 1259  
                 {
 1260  
                     itemClass = ord.getItemClass();
 1261  
                 }
 1262  
 
 1263  
                 cld = cld.getRepository().getDescriptorFor(itemClass);
 1264  
                 result.add(ord);
 1265  
             }
 1266  
             else
 1267  
             {
 1268  
                 // look for Field
 1269  
                 fld = cld.getFieldDescriptorByName(segment);
 1270  
                 if (fld != null)
 1271  
                 {
 1272  
                     result.add(fld);
 1273  
                 }
 1274  
             }
 1275  
         }
 1276  
 
 1277  
         return result;
 1278  
     }
 1279  
 
 1280  
     /**
 1281  
      * returns the zero argument constructor for the class represented by this class descriptor
 1282  
      * or null if a zero argument constructor does not exist.  If the zero argument constructor
 1283  
      * for this class is not public it is made accessible before being returned.
 1284  
      */
 1285  
     public Constructor getZeroArgumentConstructor()
 1286  
     {
 1287  
         if (zeroArgumentConstructor == null && !alreadyLookedupZeroArguments)
 1288  
         {
 1289  
             try
 1290  
             {
 1291  
                 zeroArgumentConstructor = getClassOfObject().getConstructor(NO_PARAMS);
 1292  
             }
 1293  
             catch (NoSuchMethodException e)
 1294  
             {
 1295  
                 //no public zero argument constructor available let's try for a private/protected one
 1296  
                 try
 1297  
                 {
 1298  
                     zeroArgumentConstructor = getClassOfObject().getDeclaredConstructor(NO_PARAMS);
 1299  
 
 1300  
                     //we found one, now let's make it accessible
 1301  
                     zeroArgumentConstructor.setAccessible(true);
 1302  
                 }
 1303  
                 catch (NoSuchMethodException e2)
 1304  
                 {
 1305  
                     //out of options, log the fact and let the method return null
 1306  
                     LoggerFactory.getDefaultLogger().warn(
 1307  
                         this.getClass().getName()
 1308  
                             + ": "
 1309  
                             + "No zero argument constructor defined for "
 1310  
                             + this.getClassOfObject());
 1311  
                 }
 1312  
             }
 1313  
 
 1314  
             alreadyLookedupZeroArguments = true;
 1315  
         }
 1316  
 
 1317  
         return zeroArgumentConstructor;
 1318  
     }
 1319  
 
 1320  
     /*
 1321  
      * @see XmlCapable#toXML()
 1322  
      */
 1323  
     public String toXML()
 1324  
     {
 1325  
         RepositoryTags tags = RepositoryTags.getInstance();
 1326  
         String eol = System.getProperty("line.separator");
 1327  
 
 1328  
         // comment on class
 1329  
         StringBuffer result = new StringBuffer(1024);
 1330  
         result.append( eol);
 1331  
         result.append( "  <!-- Mapping for Class ");
 1332  
         result.append( this.getClassNameOfObject());
 1333  
         result.append( " -->");
 1334  
         result.append( eol );
 1335  
 
 1336  
         // opening tag and attributes
 1337  
         result.append( "  ");
 1338  
         result.append( tags.getOpeningTagNonClosingById(CLASS_DESCRIPTOR));
 1339  
         result.append( eol );
 1340  
 
 1341  
         // class
 1342  
         result.append( "    ");
 1343  
         result.append( tags.getAttribute(CLASS_NAME, this.getClassNameOfObject()));
 1344  
         result.append( eol );
 1345  
 
 1346  
         // isolation level is optional
 1347  
         if (null != getRepository())
 1348  
         {
 1349  
             if (getIsolationLevel() != this.getRepository().getDefaultIsolationLevel())
 1350  
             {
 1351  
                 result.append( "    ");
 1352  
                 result.append( tags.getAttribute(ISOLATION_LEVEL, this.isolationLevelXml()) );
 1353  
                 result.append( eol );
 1354  
             }
 1355  
         }
 1356  
 
 1357  
         Class theProxyClass = null;
 1358  
         try
 1359  
         {
 1360  
             theProxyClass = this.getProxyClass();
 1361  
         }
 1362  
         catch (Throwable t)
 1363  
         {
 1364  
             // Ignore this exception, just try to get the Class object of the
 1365  
             // proxy class in order to be able to decide, whether the class
 1366  
             // is a dynamic proxy or not.
 1367  
         }
 1368  
 
 1369  
         // proxy is optional
 1370  
         if (theProxyClass != null)
 1371  
         {
 1372  
             if (isDynamicProxy())   // tomdz: What about VirtualProxy ?
 1373  
             {
 1374  
                 result.append( "    ");
 1375  
                 result.append( tags.getAttribute(CLASS_PROXY, DYNAMIC_STR));
 1376  
                 result.append( eol );
 1377  
                 }
 1378  
             else
 1379  
             {
 1380  
                     result.append( "    ");
 1381  
             result.append( tags.getAttribute(CLASS_PROXY, this.getProxyClassName()));
 1382  
             result.append( eol );
 1383  
             }
 1384  
             result.append( "        ");
 1385  
         result.append( tags.getAttribute(PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit()));
 1386  
         result.append( eol );
 1387  
         }
 1388  
 
 1389  
         // schema is optional
 1390  
         if (this.getSchema() != null)
 1391  
         {
 1392  
             result.append( "    ");
 1393  
             result.append( tags.getAttribute(SCHEMA_NAME, this.getSchema()));
 1394  
             result.append( eol );
 1395  
         }
 1396  
 
 1397  
         // table name
 1398  
         if (this.getTableName() != null)
 1399  
         {
 1400  
             result.append("    ");
 1401  
             result.append( tags.getAttribute(TABLE_NAME, this.getTableName()));
 1402  
             result.append( eol );
 1403  
         }
 1404  
 
 1405  
         // rowreader is optional
 1406  
         if (this.getRowReaderClassName() != null)
 1407  
         {
 1408  
             result.append( "    ");
 1409  
             result.append( tags.getAttribute(ROW_READER, this.getRowReaderClassName()));
 1410  
             result.append( eol );
 1411  
         }
 1412  
 
 1413  
         //accept-locks is optional, enabled by default
 1414  
         if (!this.acceptLocks)
 1415  
         {
 1416  
             result.append( "        ");
 1417  
             result.append( tags.getAttribute(ACCEPT_LOCKS, "false"));
 1418  
             result.append( eol );
 1419  
         }
 1420  
         // sequence manager attribute not yet implemented
 1421  
 
 1422  
         // initialization method is optional
 1423  
         if (this.getInitializationMethod() != null)
 1424  
         {
 1425  
             result.append( "    ");
 1426  
             result.append( tags.getAttribute(INITIALIZATION_METHOD, this.getInitializationMethod().getName()));
 1427  
             result.append( eol );
 1428  
         }
 1429  
 
 1430  
         // factory class is optional
 1431  
         if (this.getFactoryClass() != null)
 1432  
         {
 1433  
             result.append( "    ");
 1434  
             result.append( tags.getAttribute(FACTORY_CLASS, this.getFactoryClass().getName()) );
 1435  
             result.append( eol );
 1436  
         }
 1437  
 
 1438  
         //        factory method is optional
 1439  
         if (this.getFactoryMethod() != null)
 1440  
         {
 1441  
             result.append( "    ");
 1442  
             result.append( tags.getAttribute(FACTORY_METHOD, this.getFactoryMethod().getName()) );
 1443  
             result.append( eol );
 1444  
         }
 1445  
 
 1446  
         //reference refresh is optional, disabled by default
 1447  
         if (isAlwaysRefresh())
 1448  
         {
 1449  
             result.append( "    ");
 1450  
             result.append( tags.getAttribute(REFRESH, "true"));
 1451  
             result.append( eol );
 1452  
         }
 1453  
 
 1454  
         result.append( "  >");
 1455  
         result.append( eol );
 1456  
 
 1457  
         // end of attributes
 1458  
 
 1459  
         // begin of elements
 1460  
         if (isInterface())
 1461  
         {
 1462  
             // extent-class
 1463  
             for (int i = 0; i < getExtentClassNames().size(); i++)
 1464  
             {
 1465  
                 result.append( "      ");
 1466  
                 result.append( tags.getOpeningTagNonClosingById(CLASS_EXTENT));
 1467  
                 result.append( " " );
 1468  
                 result.append( tags.getAttribute(CLASS_REF, getExtentClassNames().get(i).toString()) );
 1469  
                 result.append( " />");
 1470  
                 result.append( eol );
 1471  
             }
 1472  
         }
 1473  
         else
 1474  
         {
 1475  
             // class extent is optional
 1476  
             if (isExtent())
 1477  
             {
 1478  
                 for (int i = 0; i < getExtentClassNames().size(); i++)
 1479  
                 {
 1480  
                     result.append( "      ");
 1481  
                     result.append( tags.getOpeningTagNonClosingById(CLASS_EXTENT));
 1482  
                     result.append( " " );
 1483  
                     result.append( tags.getAttribute(CLASS_REF, getExtentClassNames().get(i).toString()) );
 1484  
                     result.append( " />");
 1485  
                     result.append( eol );
 1486  
                 }
 1487  
             }
 1488  
 
 1489  
             // write all FieldDescriptors
 1490  
             FieldDescriptor[] fields = getFieldDescriptions();
 1491  
             for (int i = 0; i < fields.length; i++)
 1492  
             {
 1493  
                 result.append( fields[i].toXML() );
 1494  
             }
 1495  
 
 1496  
             // write optional ReferenceDescriptors
 1497  
             Vector refs = getObjectReferenceDescriptors();
 1498  
             for (int i = 0; i < refs.size(); i++)
 1499  
             {
 1500  
                 result.append( ((ObjectReferenceDescriptor) refs.get(i)).toXML() );
 1501  
             }
 1502  
 
 1503  
             // write optional CollectionDescriptors
 1504  
             Vector cols = getCollectionDescriptors();
 1505  
             for (int i = 0; i < cols.size(); i++)
 1506  
             {
 1507  
                 result.append( ((CollectionDescriptor) cols.get(i)).toXML() );
 1508  
             }
 1509  
 
 1510  
             // write optional IndexDescriptors
 1511  
             for (int i = 0; i < indexes.size(); i++)
 1512  
             {
 1513  
                 IndexDescriptor indexDescriptor = (IndexDescriptor) indexes.elementAt(i);
 1514  
                 result.append( indexDescriptor.toXML() );
 1515  
             }
 1516  
 
 1517  
             // Write out the procedures
 1518  
             if (this.getInsertProcedure() != null)
 1519  
             {
 1520  
                 result.append( this.getInsertProcedure().toXML() );
 1521  
             }
 1522  
             if (this.getUpdateProcedure() != null)
 1523  
             {
 1524  
                 result.append( this.getUpdateProcedure().toXML() );
 1525  
             }
 1526  
             if (this.getDeleteProcedure() != null)
 1527  
             {
 1528  
                 result.append( this.getDeleteProcedure().toXML() );
 1529  
             }
 1530  
         }
 1531  
         result.append( "  ");
 1532  
         result.append( tags.getClosingTagById(CLASS_DESCRIPTOR) );
 1533  
         return result.toString();
 1534  
     }
 1535  
 
 1536  
     private String isolationLevelXml()
 1537  
     {
 1538  
         switch (this.getIsolationLevel())
 1539  
         {
 1540  
             case (IL_OPTIMISTIC) :
 1541  
                 {
 1542  
                     return LITERAL_IL_OPTIMISTIC;
 1543  
                 }
 1544  
             case (IL_READ_COMMITTED) :
 1545  
                 {
 1546  
                     return LITERAL_IL_READ_COMMITTED;
 1547  
                 }
 1548  
             case (IL_READ_UNCOMMITTED) :
 1549  
                 {
 1550  
                     return LITERAL_IL_READ_UNCOMMITTED;
 1551  
                 }
 1552  
             case (IL_REPEATABLE_READ) :
 1553  
                 {
 1554  
                     return LITERAL_IL_REPEATABLE_READ;
 1555  
                 }
 1556  
             case (IL_SERIALIZABLE) :
 1557  
                 {
 1558  
                     return LITERAL_IL_SERIALIZABLE;
 1559  
                 }
 1560  
             default :
 1561  
                 {
 1562  
                     return LITERAL_IL_READ_UNCOMMITTED;
 1563  
                 }
 1564  
         }
 1565  
     }
 1566  
 /*
 1567  
 arminw:
 1568  
 TODO: this feature doesn't work, so remove this in future
 1569  
 */
 1570  
     /**
 1571  
      * Set name of the super class.
 1572  
      */
 1573  
     public void setSuperClass(String classname)
 1574  
     {
 1575  
         this.superClass = classname;
 1576  
     }
 1577  
 
 1578  
     /**
 1579  
      * Return the super class or <code>null</code>
 1580  
      * if not declared in repository file.
 1581  
      */
 1582  
     public String getSuperClass()
 1583  
     {
 1584  
         return superClass;
 1585  
     }
 1586  
 
 1587  
     /**
 1588  
      * TODO drop this method?
 1589  
      */
 1590  
     public void setSuperClassFieldRef(int fieldId)
 1591  
     {
 1592  
         this.superClassFieldRef = fieldId;
 1593  
     }
 1594  
 
 1595  
     /**
 1596  
      * TODO drop this method?
 1597  
      */
 1598  
     public int getSuperClassFieldRef()
 1599  
     {
 1600  
         return superClassFieldRef;
 1601  
     }
 1602  
 
 1603  
     /**
 1604  
      * Return true, if the described class is
 1605  
      * an interface.
 1606  
      */
 1607  
     public boolean isInterface()
 1608  
     {
 1609  
         return m_isInterface;
 1610  
     }
 1611  
 
 1612  
     /**
 1613  
      * Set <code>true</code> if described class is
 1614  
      * a interface.
 1615  
      */
 1616  
     public void setIsInterface(boolean newIsInterface)
 1617  
     {
 1618  
         m_isInterface = newIsInterface;
 1619  
     }
 1620  
 
 1621  
     /**
 1622  
      * @return boolean true if the mapped class is abstract
 1623  
      */
 1624  
     public boolean isAbstract()
 1625  
     {
 1626  
         return isAbstract;
 1627  
     }
 1628  
 
 1629  
     /**
 1630  
      * Returns acceptLocks.
 1631  
      * @return boolean
 1632  
      */
 1633  
     public boolean isAcceptLocks()
 1634  
     {
 1635  
         return acceptLocks;
 1636  
     }
 1637  
 
 1638  
     /**
 1639  
      * Sets acceptLocks.
 1640  
      * @param acceptLocks The m_acceptLocks to set
 1641  
      */
 1642  
     public void setAcceptLocks(boolean acceptLocks)
 1643  
     {
 1644  
         this.acceptLocks = acceptLocks;
 1645  
     }
 1646  
 
 1647  
     /**
 1648  
      * Gets the IndexDescriptors used for DDL generation.
 1649  
      */
 1650  
     public Vector getIndexes()
 1651  
     {
 1652  
         return indexes;
 1653  
     }
 1654  
 
 1655  
     /**
 1656  
      * Sets the IndexDescriptors used for DDL generation.
 1657  
      */
 1658  
     public void setIndexes(Vector indexes)
 1659  
     {
 1660  
         this.indexes = indexes;
 1661  
     }
 1662  
 
 1663  
     /**
 1664  
      * Gets the repository.
 1665  
      * @return Returns a DescriptorRepository
 1666  
      */
 1667  
     public DescriptorRepository getRepository()
 1668  
     {
 1669  
         return m_repository;
 1670  
     }
 1671  
 
 1672  
     /**
 1673  
      * Sets the repository.
 1674  
      * @param repository The repository to set
 1675  
      */
 1676  
     public void setRepository(DescriptorRepository repository)
 1677  
     {
 1678  
         m_repository = repository;
 1679  
     }
 1680  
 
 1681  
     /**
 1682  
      * returns the transaction isolation level to be used for this class. Used only in the ODMG server
 1683  
      */
 1684  
     public int getIsolationLevel()
 1685  
     {
 1686  
         return m_IsolationLevel;
 1687  
     }
 1688  
 
 1689  
     /**
 1690  
      * Method declaration
 1691  
      * @param isoLevel
 1692  
      */
 1693  
     public void setIsolationLevel(int isoLevel)
 1694  
     {
 1695  
         m_IsolationLevel = isoLevel;
 1696  
     }
 1697  
 
 1698  
     /**
 1699  
      * Method declaration
 1700  
      * @return table name
 1701  
      */
 1702  
     private String getTableName()
 1703  
     {
 1704  
         return m_TableName;
 1705  
     }
 1706  
 
 1707  
     /**
 1708  
      * Method declaration
 1709  
      * @param str
 1710  
      */
 1711  
     public void setTableName(String str)
 1712  
     {
 1713  
         m_TableName = str;
 1714  
     }
 1715  
 
 1716  
     /**
 1717  
      * Answer Table name including schema    BRJ
 1718  
      */
 1719  
     public String getFullTableName()
 1720  
     {
 1721  
         if (getSchema() != null)
 1722  
             return getSchema() + "." + getTableName();
 1723  
         else
 1724  
             return getTableName();
 1725  
     }
 1726  
 
 1727  
     /**
 1728  
      * Gets the schema.
 1729  
      * @return Returns a String
 1730  
      */
 1731  
     public String getSchema()
 1732  
     {
 1733  
         return schema;
 1734  
     }
 1735  
 
 1736  
     /**
 1737  
      * Sets the schema.
 1738  
      * @param schema The schema to set
 1739  
      */
 1740  
     public void setSchema(String schema)
 1741  
     {
 1742  
         this.schema = schema;
 1743  
     }
 1744  
 
 1745  
     /**
 1746  
      * Return a string representation of this class.
 1747  
      */
 1748  
     public String toString()
 1749  
     {
 1750  
         ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
 1751  
         return buf
 1752  
             .append("classNameOfObject", getClassNameOfObject())
 1753  
             .append("tableName", getTableName())
 1754  
             .append("schema", getSchema())
 1755  
             .append("isInterface", isInterface())
 1756  
             .append("extendClassNames", getExtentClassNames().toString())
 1757  
             //.append("[fieldDescriptions:")
 1758  
             .append(getFieldDescriptions())
 1759  
             //.append("]")
 1760  
             .toString();
 1761  
     }
 1762  
 
 1763  
     /**
 1764  
      * sets the initialization method for this descriptor
 1765  
      */
 1766  
     private synchronized void setInitializationMethod(Method newMethod)
 1767  
     {
 1768  
         if (newMethod != null)
 1769  
         {
 1770  
             // make sure it's a no argument method
 1771  
             if (newMethod.getParameterTypes().length > 0)
 1772  
             {
 1773  
                 throw new MetadataException(
 1774  
                     "Initialization methods must be zero argument methods: "
 1775  
                         + newMethod.getClass().getName()
 1776  
                         + "."
 1777  
                         + newMethod.getName());
 1778  
             }
 1779  
 
 1780  
             // make it accessible if it's not already
 1781  
             if (!newMethod.isAccessible())
 1782  
             {
 1783  
                 newMethod.setAccessible(true);
 1784  
             }
 1785  
         }
 1786  
         this.initializationMethod = newMethod;
 1787  
     }
 1788  
 
 1789  
     /**
 1790  
      * sets the initialization method for this descriptor by name
 1791  
      */
 1792  
     public synchronized void setInitializationMethod(String newMethodName)
 1793  
     {
 1794  
         Method newMethod = null;
 1795  
         if (newMethodName != null)
 1796  
         {
 1797  
             initializationMethodName = newMethodName;
 1798  
             try
 1799  
             {
 1800  
                 // see if we have a publicly accessible method by the name
 1801  
                 newMethod = getClassOfObject().getMethod(newMethodName, NO_PARAMS);
 1802  
             }
 1803  
             catch (NoSuchMethodException e)
 1804  
             {
 1805  
                 try
 1806  
                 {
 1807  
                     // no publicly accessible method, see if there is a private/protected one
 1808  
                     newMethod = getClassOfObject().getDeclaredMethod(newMethodName, NO_PARAMS);
 1809  
                 }
 1810  
                 catch (NoSuchMethodException e2)
 1811  
                 {
 1812  
                     // there is no such method available
 1813  
                     throw new MetadataException(
 1814  
                         "Invalid initialization method, there is not"
 1815  
                             + " a zero argument method named "
 1816  
                             + newMethodName
 1817  
                             + " on class "
 1818  
                             + getClassOfObject().getName()
 1819  
                             + ".");
 1820  
                 }
 1821  
             }
 1822  
         }
 1823  
         setInitializationMethod(newMethod);
 1824  
     }
 1825  
 
 1826  
     /**
 1827  
      * Returns the initialization method for this descriptor or null if no
 1828  
      * initialization method is defined.
 1829  
      */
 1830  
     public synchronized Method getInitializationMethod()
 1831  
     {
 1832  
         if(this.initializationMethod == null)
 1833  
         {
 1834  
             setInitializationMethod(initializationMethodName);
 1835  
         }
 1836  
         return initializationMethod;
 1837  
     }
 1838  
 
 1839  
     /**
 1840  
      * if true instances of this class are always refreshed
 1841  
      * even if they are already in the cache.
 1842  
      * @return boolean
 1843  
      */
 1844  
     public boolean isAlwaysRefresh()
 1845  
     {
 1846  
         return alwaysRefresh;
 1847  
     }
 1848  
 
 1849  
     /**
 1850  
      * Sets the alwaysRefresh parameter.
 1851  
      * @param alwaysRefresh The value to set
 1852  
      */
 1853  
     public void setAlwaysRefresh(boolean alwaysRefresh)
 1854  
     {
 1855  
         this.alwaysRefresh = alwaysRefresh;
 1856  
     }
 1857  
 
 1858  
     public int getProxyPrefetchingLimit()
 1859  
     {
 1860  
         return m_ProxyPrefetchingLimit;
 1861  
     }
 1862  
 
 1863  
     public void setProxyPrefetchingLimit(int proxyPrefetchingLimit)
 1864  
     {
 1865  
         m_ProxyPrefetchingLimit = proxyPrefetchingLimit;
 1866  
     }
 1867  
 
 1868  
     /**
 1869  
      * Return factory class.
 1870  
      */
 1871  
     public synchronized Class getFactoryClass()
 1872  
     {
 1873  
         return this.factoryClass;
 1874  
     }
 1875  
 
 1876  
     /**
 1877  
      * Return factory method.
 1878  
      */
 1879  
     public synchronized Method getFactoryMethod()
 1880  
     {
 1881  
         if(factoryMethod == null && factoryMethodName != null)
 1882  
         {
 1883  
             setFactoryMethod(factoryMethodName);
 1884  
         }
 1885  
         return this.factoryMethod;
 1886  
     }
 1887  
 
 1888  
     /**
 1889  
      * Set the object factory for class described by this
 1890  
      * descriptor.
 1891  
      * @see #setFactoryMethod
 1892  
      */
 1893  
     public synchronized void setFactoryClass(Class newClass)
 1894  
     {
 1895  
         this.factoryClass = newClass;
 1896  
     }
 1897  
 
 1898  
     /**
 1899  
      * @see #setFactoryClass
 1900  
      */
 1901  
     public void setFactoryClass(String newClass)
 1902  
     {
 1903  
         if (null != newClass)
 1904  
         {
 1905  
             try
 1906  
             {
 1907  
                 Class clazz = ClassHelper.getClass(newClass);
 1908  
                 setFactoryClass(clazz);
 1909  
             }
 1910  
             catch (Exception e)
 1911  
             {
 1912  
                 // there is no such method available
 1913  
                 throw new MetadataException("Invalid factory class: " + newClass + ".");
 1914  
             }
 1915  
         }
 1916  
         else
 1917  
         {
 1918  
             setFactoryClass((Class) null);
 1919  
         }
 1920  
     }
 1921  
 
 1922  
     /**
 1923  
      * Specify the method to instantiate objects
 1924  
      * represented by this descriptor.
 1925  
      * @see #setFactoryClass 
 1926  
      */
 1927  
     private synchronized void setFactoryMethod(Method newMethod)
 1928  
     {
 1929  
         if (newMethod != null)
 1930  
         {
 1931  
             // make sure it's a no argument method
 1932  
             if (newMethod.getParameterTypes().length > 0)
 1933  
             {
 1934  
                 throw new MetadataException(
 1935  
                     "Factory methods must be zero argument methods: "
 1936  
                         + newMethod.getClass().getName()
 1937  
                         + "."
 1938  
                         + newMethod.getName());
 1939  
             }
 1940  
 
 1941  
             // make it accessible if it's not already
 1942  
             if (!newMethod.isAccessible())
 1943  
             {
 1944  
                 newMethod.setAccessible(true);
 1945  
             }
 1946  
         }
 1947  
 
 1948  
         this.factoryMethod = newMethod;
 1949  
     }
 1950  
 
 1951  
     /**
 1952  
      * sets the initialization method for this descriptor by name
 1953  
      */
 1954  
     public synchronized void setFactoryMethod(String factoryMethodName)
 1955  
     {
 1956  
         Method newMethod = null;
 1957  
         this.factoryMethodName = factoryMethodName;
 1958  
 
 1959  
         if (factoryMethodName != null)
 1960  
         {
 1961  
             try
 1962  
             {
 1963  
                 // see if we have a publicly accessible method by the name
 1964  
                 newMethod = getFactoryClass().getMethod(factoryMethodName, NO_PARAMS);
 1965  
             }
 1966  
             catch (NoSuchMethodException e)
 1967  
             {
 1968  
                 try
 1969  
                 {
 1970  
                     // no publicly accessible method, see if there is a private/protected one
 1971  
                     newMethod = getFactoryClass().getDeclaredMethod(factoryMethodName, NO_PARAMS);
 1972  
                 }
 1973  
                 catch (NoSuchMethodException e2)
 1974  
                 {
 1975  
                     // there is no such method available
 1976  
                     throw new MetadataException(
 1977  
                         "Invalid factory method, there is not"
 1978  
                             + " a zero argument method named "
 1979  
                             + factoryMethodName
 1980  
                             + " on class "
 1981  
                             + getFactoryClass().getName()
 1982  
                             + ".");
 1983  
                 }
 1984  
             }
 1985  
         }
 1986  
         setFactoryMethod(newMethod);
 1987  
     }
 1988  
 
 1989  
     //---------------------------------------------------------------
 1990  
     /**
 1991  
      * Change the descriptor for the insert procedure/function.
 1992  
      *
 1993  
      * @param newValue the new value.
 1994  
      */
 1995  
     public void setInsertProcedure(InsertProcedureDescriptor newValue)
 1996  
     {
 1997  
         this.insertProcedure = newValue;
 1998  
     }
 1999  
 
 2000  
     //---------------------------------------------------------------
 2001  
     /**
 2002  
      * Retrieve the descriptor for the insert procedure/function.
 2003  
      *
 2004  
      * @return The current value
 2005  
      */
 2006  
     public InsertProcedureDescriptor getInsertProcedure()
 2007  
     {
 2008  
         return this.insertProcedure;
 2009  
     }
 2010  
 
 2011  
     //---------------------------------------------------------------
 2012  
     /**
 2013  
      * Change the descriptor for the update procedure/function.
 2014  
      *
 2015  
      * @param newValue the new value.
 2016  
      */
 2017  
     public void setUpdateProcedure(UpdateProcedureDescriptor newValue)
 2018  
     {
 2019  
         this.updateProcedure = newValue;
 2020  
     }
 2021  
 
 2022  
     //---------------------------------------------------------------
 2023  
     /**
 2024  
      * Retrieve the descriptor for the update procedure/function.
 2025  
      *
 2026  
      * @return The current value
 2027  
      */
 2028  
     public UpdateProcedureDescriptor getUpdateProcedure()
 2029  
     {
 2030  
         return this.updateProcedure;
 2031  
     }
 2032  
 
 2033  
     //---------------------------------------------------------------
 2034  
     /**
 2035  
      * Change the descriptor for the delete procedure/function.
 2036  
      *
 2037  
      * @param newValue the new value.
 2038  
      */
 2039  
     public void setDeleteProcedure(DeleteProcedureDescriptor newValue)
 2040  
     {
 2041  
         this.deleteProcedure = newValue;
 2042  
     }
 2043  
 
 2044  
     //---------------------------------------------------------------
 2045  
     /**
 2046  
      * Retrieve the descriptor for the delete procedure/function.
 2047  
      *
 2048  
      * @return The current value
 2049  
      */
 2050  
     public DeleteProcedureDescriptor getDeleteProcedure()
 2051  
     {
 2052  
         return this.deleteProcedure;
 2053  
     }
 2054  
 
 2055  
     /**
 2056  
      * Returns the ojbConcreteClass field or <code>null</code> if none defined.
 2057  
      */
 2058  
     public FieldDescriptor getOjbConcreteClassField()
 2059  
     {
 2060  
         // if not checked before
 2061  
         if(!ojbConcreteFieldCheckDone)
 2062  
         {
 2063  
             ojbConcreteClassField = getFieldDescriptorByName(OJB_CONCRETE_CLASS);
 2064  
             ojbConcreteFieldCheckDone = true;
 2065  
         }
 2066  
         return ojbConcreteClassField;
 2067  
     }
 2068  
 
 2069  
     public StatementsForClassIF getStatementsForClass(ConnectionManagerIF conMan)
 2070  
     {
 2071  
         if(statementsForClass == null)
 2072  
         {
 2073  
            statementsForClass = StatementsForClassFactory.getInstance().
 2074  
                    getStatementsForClass(conMan.getConnectionDescriptor(), this);
 2075  
         }
 2076  
         return statementsForClass;
 2077  
     }
 2078  
 
 2079  
 
 2080  
     /**
 2081  
      * Optional! Set the {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField}
 2082  
      * implementation class used by this class.
 2083  
      * @param pfClassName The full qualified class name of the
 2084  
      * {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField}.
 2085  
      */
 2086  
     public void setPersistentFieldClassName(String pfClassName)
 2087  
     {
 2088  
                 this.persistentFieldClassName = pfClassName;
 2089  
     }
 2090  
 
 2091  
 
 2092  
     /**
 2093  
      * Get the used {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField}
 2094  
      * implementation name.
 2095  
      */
 2096  
     public String getPersistentFieldClassName()
 2097  
     {
 2098  
                 return persistentFieldClassName;
 2099  
     }
 2100  
 
 2101  
     /**
 2102  
      * Returns <em>true</em> if an DB Identity column field based sequence
 2103  
      * manager was used. In that cases we will find an autoincrement field with
 2104  
      * read-only access and return true, otherwise false.
 2105  
      */
 2106  
      public boolean useIdentityColumnField()
 2107  
      {
 2108  
          if(useIdentityColumn == 0)
 2109  
          {
 2110  
              useIdentityColumn = -1;
 2111  
              FieldDescriptor[] pkFields = getPkFields();
 2112  
              for (int i = 0; i < pkFields.length; i++)
 2113  
              {
 2114  
                  // to find the identity column we search for a autoincrement
 2115  
                  // read-only field
 2116  
                 if (pkFields[i].isAutoIncrement() && pkFields[i].isAccessReadOnly())
 2117  
                 {
 2118  
                     useIdentityColumn = 1;
 2119  
                     break;
 2120  
                 }
 2121  
              }
 2122  
          }
 2123  
         return useIdentityColumn == 1;
 2124  
      }
 2125  
 
 2126  
     /**
 2127  
      * Returns all defined {@link ObjectReferenceDescriptor}.
 2128  
      *
 2129  
      * @param withInherited If <em>true</em> inherited super class references will be included.
 2130  
      */
 2131  
     public List getObjectReferenceDescriptors(boolean withInherited)
 2132  
     {
 2133  
         if(withInherited && getSuperClassDescriptor() != null)
 2134  
         {
 2135  
             List result = new ArrayList(m_ObjectReferenceDescriptors);
 2136  
             result.addAll(getSuperClassDescriptor().getObjectReferenceDescriptors(true));
 2137  
             return result;
 2138  
         }
 2139  
         else
 2140  
         {
 2141  
             return m_ObjectReferenceDescriptors;
 2142  
         }
 2143  
     }
 2144  
 
 2145  
     /**
 2146  
      * Returns all defined {@link CollectionDescriptor} for
 2147  
      * this class descriptor.
 2148  
      *
 2149  
      * @param withInherited If <em>true</em> inherited super class references will be included.
 2150  
      */
 2151  
     public List getCollectionDescriptors(boolean withInherited)
 2152  
     {
 2153  
         if(withInherited && getSuperClassDescriptor() != null)
 2154  
         {
 2155  
             List result = new ArrayList(m_CollectionDescriptors);
 2156  
             result.addAll(getSuperClassDescriptor().getCollectionDescriptors(true));
 2157  
             return result;
 2158  
         }
 2159  
         else
 2160  
         {
 2161  
             return m_CollectionDescriptors;
 2162  
         }
 2163  
     }
 2164  
 
 2165  
     /**
 2166  
      * Return an array of all {@link FieldDescriptor} for this represented class, if
 2167  
      * parameter <em>withInherited</em> is <em>true</em> all inherited descriptor
 2168  
      * of declared super classes are included.
 2169  
      *
 2170  
      * @param withInherited If <em>true</em> inherited super class fields will be included.
 2171  
      */
 2172  
     public FieldDescriptor[] getFieldDescriptor(boolean withInherited)
 2173  
     {
 2174  
         if(withInherited && getSuperClassDescriptor() != null)
 2175  
         {
 2176  
             /*
 2177  
             arminw: only return no-PK fields, because all PK fields are declared
 2178  
             in sub-class too.
 2179  
             */
 2180  
             FieldDescriptor[] superFlds = getSuperClassDescriptor().getFieldDescriptorNonPk(true);
 2181  
             if(m_FieldDescriptions == null)
 2182  
             {
 2183  
                 m_FieldDescriptions = new FieldDescriptor[0];
 2184  
             }
 2185  
             FieldDescriptor[] result = new FieldDescriptor[m_FieldDescriptions.length + superFlds.length];
 2186  
             System.arraycopy(m_FieldDescriptions, 0, result, 0, m_FieldDescriptions.length);
 2187  
             System.arraycopy(superFlds, 0, result, m_FieldDescriptions.length, superFlds.length);
 2188  
             // System.out.println("all fields: " + ArrayUtils.toString(result));
 2189  
             return result;
 2190  
         }
 2191  
         else
 2192  
         {
 2193  
             return m_FieldDescriptions;
 2194  
         }
 2195  
     }
 2196  
 
 2197  
     /**
 2198  
      * Return an array of NON-PK {@link FieldDescriptor}, if parameter <em>withInherited</em>
 2199  
      * is <em>true</em> all inherited descriptor of declared super classes are included.
 2200  
      *
 2201  
      * @param withInherited If <em>true</em> inherited super class fields will be included.
 2202  
      */
 2203  
     public FieldDescriptor[] getFieldDescriptorNonPk(boolean withInherited)
 2204  
     {
 2205  
         if(withInherited && getSuperClassDescriptor() != null)
 2206  
         {
 2207  
             FieldDescriptor[] flds = getNonPkFields();
 2208  
             FieldDescriptor[] superFlds = getSuperClassDescriptor().getFieldDescriptorNonPk(true);
 2209  
             FieldDescriptor[] result = new FieldDescriptor[flds.length + superFlds.length];
 2210  
             System.arraycopy(flds, 0, result, 0, flds.length);
 2211  
             System.arraycopy(superFlds, 0, result, flds.length, superFlds.length);
 2212  
             return result;
 2213  
         }
 2214  
         else
 2215  
         {
 2216  
             return getNonPkFields();
 2217  
         }
 2218  
     }
 2219  
 
 2220  
     /**
 2221  
      * Returns the {@link SuperReferenceDescriptor} of this class or <em>null</em>
 2222  
      * if none was used.
 2223  
      *
 2224  
      * @return The reference descriptor for the <em>super</em>-reference or <em>null</em>
 2225  
      * if not exists.
 2226  
      */
 2227  
     public SuperReferenceDescriptor getSuperReference()
 2228  
     {
 2229  
         return (SuperReferenceDescriptor) getObjectReferenceDescriptorByName(SuperReferenceDescriptor.SUPER_FIELD_INTERNAL_NAME);
 2230  
     }
 2231  
 }