You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2007/05/16 01:10:15 UTC
svn commit: r538372 - in
/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata:
ClassDescriptor.java DescriptorRepository.java
Author: arminw
Date: Tue May 15 16:10:14 2007
New Revision: 538372
URL: http://svn.apache.org/viewvc?view=rev&rev=538372
Log:
rename/add new methods for better handling of subclasses and classes mapped to same table, optimize source
Modified:
db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/DescriptorRepository.java
Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java?view=diff&rev=538372&r1=538371&r2=538372
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java Tue May 15 16:10:14 2007
@@ -25,11 +25,11 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
+import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.ojb.broker.PersistenceBrokerException;
@@ -41,8 +41,9 @@
import org.apache.ojb.broker.core.ValueContainer;
import org.apache.ojb.broker.locking.IsolationLevels;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
-import org.apache.ojb.broker.util.ClassHelper;
import org.apache.ojb.broker.util.AttributeTokenizer;
+import org.apache.ojb.broker.util.ClassHelper;
+import org.apache.ojb.broker.util.ShortcutMapper;
import org.apache.ojb.broker.util.configuration.Configuration;
import org.apache.ojb.broker.util.configuration.Configurator;
import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
@@ -62,8 +63,6 @@
public final class ClassDescriptor extends DescriptorBase
implements Serializable, XmlCapable, IsolationLevels
{
- private String persistentFieldClassName;
-
private static final long serialVersionUID = -5212253607374173965L;
public static final String DYNAMIC_STR = "dynamic";
@@ -133,6 +132,7 @@
* of these must be present for this function to be successful.
*/
private Class factoryClass;
+ private String persistentFieldClassName;
private int useIdentityColumn = 0;
/**
* Indicate whether or not this class has LOB fields.
@@ -255,17 +255,17 @@
* the list of classes in the extent of this class. can be empty
*/
private Vector extentClasses = new Vector();
- /**
- * the list of class names in the extent of this class. can be empty
- */
- private Vector extentClassNames = new Vector();
private Map m_fieldDescriptorNameMap = null;
private Map m_collectionDescriptorNameMap = null;
private Map m_objectReferenceDescriptorsNameMap = null;
// BRJ: ClassDescriptor referenced by 'super' ObjectReferenceDescriptor
private ClassDescriptor m_superCld = null;
- private boolean m_superCldSet = false;
+ /**
+ * Indicate if <tt>true</tt> that at least one autoincrement primary
+ * key field exists.
+ */
+ private Boolean autoincrementPrimaryKey;
//-----------------------------------------------------------------
//-----------------------------------------------------------------
@@ -295,10 +295,11 @@
public void setBaseClass(String baseClass)
{
this.baseClass = baseClass;
+ this.m_superCld = null;
// first deregister
- getRepository().deregisterSuperClassMultipleJoinedTables(this);
+ getRepository().deregisterTablePerSubclassInheritance(this);
// register classes using mapping of classes to multiple joined tables
- getRepository().registerSuperClassMultipleJoinedTables(this);
+ getRepository().registerTablePerSubclassInheritance(this);
}
// /**
@@ -369,7 +370,7 @@
{
m_rowReader =
(RowReader) ClassHelper.newInstance(
- newReaderClassName,
+ ShortcutMapper.resolve(newReaderClassName, RowReader.class),
ClassDescriptor.class,
this);
}
@@ -614,20 +615,16 @@
*/
public ClassDescriptor getSuperClassDescriptor()
{
- if (!m_superCldSet)
+ if (baseClass != null && m_superCld == null)
{
- if(getBaseClass() != null)
+ m_superCld = getRepository().getDescriptorFor(getBaseClass());
+ if(m_superCld.isAbstract() || m_superCld.isInterface())
{
- m_superCld = getRepository().getDescriptorFor(getBaseClass());
- if(m_superCld.isAbstract() || m_superCld.isInterface())
- {
- throw new MetadataException("Super class mapping only work for real class, but declared super class" +
- " is an interface or is abstract. Declared class: " + m_superCld.getClassNameOfObject());
- }
+ throw new MetadataException("Super class mapping only work for real classes, but declared super class "
+ + baseClass + " is an interface or is abstract and can't be used by class: "
+ + m_superCld.getClassNameOfObject());
}
- m_superCldSet = true;
}
-
return m_superCld;
}
@@ -642,88 +639,104 @@
}
/**
- * add an Extent class to the current descriptor
- * @param newExtendClass
+ * Add an <em>extent class</em> to the current class descriptor.
+ *
+ * @param extent name of the class to add.
*/
- public void addExtentClass(Class newExtendClass)
+ public void addExtentClass(Class extent)
{
- extentClasses.add(newExtendClass);
- this.addExtentClass(newExtendClass.getName());
+ if(!extentClasses.contains(extent))
+ {
+ extentClasses.add(extent);
+ if(m_repository != null) m_repository.addSuperClassForExtent(extent, this);
+ }
}
/**
- * add an Extent class to the current descriptor
- * @param newExtentClassName name of the class to add
+ * Add an <em>extent class</em> to the current class descriptor.
+ *
+ * @param extent name of the class to add.
*/
- public void addExtentClass(String newExtentClassName)
+ public void addExtentClass(String extent)
{
- extentClassNames.add(newExtentClassName);
- if(m_repository != null) m_repository.addExtent(newExtentClassName, this);
+ try
+ {
+ Class extentClass = ClassHelper.getClass(extent);
+ addExtentClass(extentClass);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new MetadataException("Adding of extent fails: Unable to load class [" + extent
+ + "]. Make sure it is available on the classpath.", e);
+ }
}
- public void removeExtentClass(String extentClassName)
+ /**
+ * Remove an <em>extent class</em> from the current class descriptor.
+ * @param extent name of the class to remove.
+ */
+ public void removeExtentClass(String extent)
{
- extentClassNames.remove(extentClassName);
- if(m_repository != null) m_repository.removeExtent(extentClassName);
+ try
+ {
+ Class extentClass = ClassHelper.getClass(extent);
+ removeExtentClass(extentClass);
+ }
+ catch (ClassNotFoundException e)
+ {
+ LoggerFactory.getDefaultLogger().error("Remove of extent fails: Unable to find class [" + extent
+ + "]. Make sure it is available on the classpath.", e);
+ }
}
/**
- * return all classes in this extent.
- * Creation date: (02.02.2001 17:49:11)
- * @return java.util.Vector
+ * Remove an <em>extent class</em> from the current class descriptor.
+ * @param extent name of the class to remove.
*/
- public synchronized Vector getExtentClasses()
+ public void removeExtentClass(Class extent)
+ {
+ boolean result = extentClasses.remove(extent);
+ if(result && m_repository != null) m_repository.removeSuperClassForExtent(extent);
+ }
+
+ /**
+ * Return all <em>extent classes</em> in this extent.
+ *
+ * @return The list of classes.
+ */
+ public Vector getExtentClasses()
{
- if (extentClassNames.size() != extentClasses.size())
- {
- extentClasses.clear();
- for (Iterator iter = extentClassNames.iterator(); iter.hasNext();)
- {
- String classname = (String) iter.next();
- Class extentClass;
- try
- {
- extentClass = ClassHelper.getClass(classname);
- }
- catch (ClassNotFoundException e)
- {
- throw new MetadataException(
- "Unable to load class ["
- + classname
- + "]. Make sure it is available on the classpath.",
- e);
- }
- extentClasses.add(extentClass);
- }
- }
return extentClasses;
}
/**
- * Return the names of all classes in this extent
- * @return java.util.Vector a Vector containing the fully qualified names
- * of all classes in this extent
+ * Return the names of all classes in this extent.
+ *
+ * @return a list containing the fully qualified names
+ * of all extent classes provided by this class.
*/
- public synchronized Vector getExtentClassNames()
+ public Vector getExtentClassNames()
{
- return this.extentClassNames;
+ Vector list = new Vector();
+ for(int i = 0; i < extentClasses.size(); i++)
+ {
+ Class result = (Class) extentClasses.get(i);
+ list.add(result.getName());
+ }
+ return list;
}
/**
- * Insert the method's description here.
- * Creation date: (02.02.2001 17:49:11)
- * @return boolean
+ * Returns <em>true</em> if this class has <em>extent classes</em>.
*/
public boolean isExtent()
{
- return (getExtentClassNames().size() > 0);
+ return !extentClasses.isEmpty();
}
/**
- * Insert the method's description here.
- * Creation date: (26.01.2001 09:20:09)
- * @return java.lang.Class
+ * Returns the proxy class of this class or <em>null</em> if not set.
*/
public synchronized Class getProxyClass()
{
@@ -1053,7 +1066,7 @@
if (m_PkFieldDescriptors == null)
{
// 1. collect all Primary Key fields from Field list
- Vector vec = new Vector();
+ ArrayList pkList = new ArrayList();
// 1.a if descriptor describes an interface: take PK fields from an implementors ClassDescriptor
if (isInterface())
{
@@ -1071,12 +1084,12 @@
FieldDescriptor fd = fields[i];
if (fd.isPrimaryKey())
{
- vec.add(fd);
+ pkList.add(fd);
}
}
// 2. Sort fields according to their getOrder() Property
- Collections.sort(vec, FieldDescriptor.getComparator());
- m_PkFieldDescriptors = (FieldDescriptor[]) vec.toArray(new FieldDescriptor[vec.size()]);
+ Collections.sort(pkList, FieldDescriptor.getComparator());
+ m_PkFieldDescriptors = (FieldDescriptor[]) pkList.toArray(new FieldDescriptor[pkList.size()]);
}
}
return m_PkFieldDescriptors;
@@ -1325,366 +1338,120 @@
return zeroArgumentConstructor;
}
- /*
- * @see XmlCapable#toXML()
+/*
+arminw:
+TODO: this feature doesn't work, so remove this in future
+*/
+ /**
+ * Set name of the super class.
*/
- public String toXML()
+ public void setSuperClass(String classname)
{
- RepositoryTags tags = RepositoryTags.getInstance();
- String eol = System.getProperty("line.separator");
+ this.superClass = classname;
+ }
- // comment on class
- StringBuffer result = new StringBuffer(1024);
- result.append( eol);
- result.append( " <!-- Mapping for Class ");
- result.append( this.getClassNameOfObject());
- result.append( " -->");
- result.append( eol );
+ /**
+ * Return the super class or <code>null</code>
+ * if not declared in repository file.
+ */
+ public String getSuperClass()
+ {
+ return superClass;
+ }
- // opening tag and attributes
- result.append( " ");
- result.append( tags.getOpeningTagNonClosingById(CLASS_DESCRIPTOR));
- result.append( eol );
+ /**
+ * TODO drop this method?
+ */
+ public void setSuperClassFieldRef(int fieldId)
+ {
+ this.superClassFieldRef = fieldId;
+ }
- // class
- result.append( " ");
- result.append( tags.getAttribute(CLASS_NAME, this.getClassNameOfObject()));
- result.append( eol );
+ /**
+ * TODO drop this method?
+ */
+ public int getSuperClassFieldRef()
+ {
+ return superClassFieldRef;
+ }
- // isolation level is optional
- if (null != getRepository())
- {
- if (getIsolationLevel() != this.getRepository().getDefaultIsolationLevel())
- {
- result.append( " ");
- result.append( tags.getAttribute(ISOLATION_LEVEL, this.isolationLevelXml()) );
- result.append( eol );
- }
- }
+ /**
+ * Return true, if the described class is
+ * an interface.
+ */
+ public boolean isInterface()
+ {
+ return m_isInterface;
+ }
- Class theProxyClass = null;
- try
- {
- theProxyClass = this.getProxyClass();
- }
- catch (Throwable t)
- {
- // Ignore this exception, just try to get the Class object of the
- // proxy class in order to be able to decide, whether the class
- // is a dynamic proxy or not.
- }
+ /**
+ * Set <code>true</code> if described class is
+ * a interface.
+ */
+ public void setIsInterface(boolean newIsInterface)
+ {
+ m_isInterface = newIsInterface;
+ }
- // proxy is optional
- if (theProxyClass != null)
- {
- if (isDynamicProxy()) // tomdz: What about VirtualProxy ?
- {
- result.append( " ");
- result.append( tags.getAttribute(CLASS_PROXY, DYNAMIC_STR));
- result.append( eol );
- }
- else
- {
- result.append( " ");
- result.append( tags.getAttribute(CLASS_PROXY, this.getProxyClassName()));
- result.append( eol );
- }
- result.append( " ");
- result.append( tags.getAttribute(PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit()));
- result.append( eol );
- }
+ /**
+ * @return boolean true if the mapped class is abstract
+ */
+ public boolean isAbstract()
+ {
+ return isAbstract;
+ }
- // schema is optional
- if (this.getSchema() != null)
- {
- result.append( " ");
- result.append( tags.getAttribute(SCHEMA_NAME, this.getSchema()));
- result.append( eol );
- }
+ /**
+ * Returns acceptLocks.
+ * @return boolean
+ */
+ public boolean isAcceptLocks()
+ {
+ return acceptLocks;
+ }
- // table name
- if (this.getTableName() != null)
- {
- result.append(" ");
- result.append( tags.getAttribute(TABLE_NAME, this.getTableName()));
- result.append( eol );
- }
+ /**
+ * Sets acceptLocks.
+ * @param acceptLocks The m_acceptLocks to set
+ */
+ public void setAcceptLocks(boolean acceptLocks)
+ {
+ this.acceptLocks = acceptLocks;
+ }
- // rowreader is optional
- if (this.getRowReaderClassName() != null)
- {
- result.append( " ");
- result.append( tags.getAttribute(ROW_READER, this.getRowReaderClassName()));
- result.append( eol );
- }
+ /**
+ * Gets the IndexDescriptors used for DDL generation.
+ */
+ public Vector getIndexes()
+ {
+ return indexes;
+ }
- //accept-locks is optional, enabled by default
- if (!this.acceptLocks)
- {
- result.append( " ");
- result.append( tags.getAttribute(ACCEPT_LOCKS, "false"));
- result.append( eol );
- }
- // sequence manager attribute not yet implemented
+ /**
+ * Sets the IndexDescriptors used for DDL generation.
+ */
+ public void setIndexes(Vector indexes)
+ {
+ this.indexes = indexes;
+ }
- // initialization method is optional
- if (this.getInitializationMethod() != null)
- {
- result.append( " ");
- result.append( tags.getAttribute(INITIALIZATION_METHOD, this.getInitializationMethod().getName()));
- result.append( eol );
- }
+ /**
+ * Gets the repository.
+ * @return Returns a DescriptorRepository
+ */
+ public DescriptorRepository getRepository()
+ {
+ return m_repository;
+ }
- // factory class is optional
- if (this.getFactoryClass() != null)
- {
- result.append( " ");
- result.append( tags.getAttribute(FACTORY_CLASS, this.getFactoryClass().getName()) );
- result.append( eol );
- }
-
- // factory method is optional
- if (this.getFactoryMethod() != null)
- {
- result.append( " ");
- result.append( tags.getAttribute(FACTORY_METHOD, this.getFactoryMethod().getName()) );
- result.append( eol );
- }
-
- //reference refresh is optional, disabled by default
- if (isAlwaysRefresh())
- {
- result.append( " ");
- result.append( tags.getAttribute(REFRESH, "true"));
- result.append( eol );
- }
-
- result.append( " >");
- result.append( eol );
-
- // end of attributes
-
- // begin of elements
- if (isInterface())
- {
- // extent-class
- for (int i = 0; i < getExtentClassNames().size(); i++)
- {
- result.append( " ");
- result.append( tags.getOpeningTagNonClosingById(CLASS_EXTENT));
- result.append( " " );
- result.append( tags.getAttribute(CLASS_REF, getExtentClassNames().get(i).toString()) );
- result.append( " />");
- result.append( eol );
- }
- }
- else
- {
- // class extent is optional
- if (isExtent())
- {
- for (int i = 0; i < getExtentClassNames().size(); i++)
- {
- result.append( " ");
- result.append( tags.getOpeningTagNonClosingById(CLASS_EXTENT));
- result.append( " " );
- result.append( tags.getAttribute(CLASS_REF, getExtentClassNames().get(i).toString()) );
- result.append( " />");
- result.append( eol );
- }
- }
-
- // write all FieldDescriptors
- FieldDescriptor[] fields = getFieldDescriptions();
- for (int i = 0; i < fields.length; i++)
- {
- result.append( fields[i].toXML() );
- }
-
- // write optional ReferenceDescriptors
- Vector refs = getObjectReferenceDescriptors();
- for (int i = 0; i < refs.size(); i++)
- {
- result.append( ((ObjectReferenceDescriptor) refs.get(i)).toXML() );
- }
-
- // write optional CollectionDescriptors
- Vector cols = getCollectionDescriptors();
- for (int i = 0; i < cols.size(); i++)
- {
- result.append( ((CollectionDescriptor) cols.get(i)).toXML() );
- }
-
- // write optional IndexDescriptors
- for (int i = 0; i < indexes.size(); i++)
- {
- IndexDescriptor indexDescriptor = (IndexDescriptor) indexes.elementAt(i);
- result.append( indexDescriptor.toXML() );
- }
-
- // Write out the procedures
- if (this.getInsertProcedure() != null)
- {
- result.append( this.getInsertProcedure().toXML() );
- }
- if (this.getUpdateProcedure() != null)
- {
- result.append( this.getUpdateProcedure().toXML() );
- }
- if (this.getDeleteProcedure() != null)
- {
- result.append( this.getDeleteProcedure().toXML() );
- }
- }
- result.append( " ");
- result.append( tags.getClosingTagById(CLASS_DESCRIPTOR) );
- return result.toString();
- }
-
- private String isolationLevelXml()
- {
- switch (this.getIsolationLevel())
- {
- case (IL_OPTIMISTIC) :
- {
- return LITERAL_IL_OPTIMISTIC;
- }
- case (IL_READ_COMMITTED) :
- {
- return LITERAL_IL_READ_COMMITTED;
- }
- case (IL_READ_UNCOMMITTED) :
- {
- return LITERAL_IL_READ_UNCOMMITTED;
- }
- case (IL_REPEATABLE_READ) :
- {
- return LITERAL_IL_REPEATABLE_READ;
- }
- case (IL_SERIALIZABLE) :
- {
- return LITERAL_IL_SERIALIZABLE;
- }
- default :
- {
- return LITERAL_IL_READ_UNCOMMITTED;
- }
- }
- }
-/*
-arminw:
-TODO: this feature doesn't work, so remove this in future
-*/
- /**
- * Set name of the super class.
- */
- public void setSuperClass(String classname)
- {
- this.superClass = classname;
- }
-
- /**
- * Return the super class or <code>null</code>
- * if not declared in repository file.
- */
- public String getSuperClass()
- {
- return superClass;
- }
-
- /**
- * TODO drop this method?
- */
- public void setSuperClassFieldRef(int fieldId)
- {
- this.superClassFieldRef = fieldId;
- }
-
- /**
- * TODO drop this method?
- */
- public int getSuperClassFieldRef()
- {
- return superClassFieldRef;
- }
-
- /**
- * Return true, if the described class is
- * an interface.
- */
- public boolean isInterface()
- {
- return m_isInterface;
- }
-
- /**
- * Set <code>true</code> if described class is
- * a interface.
- */
- public void setIsInterface(boolean newIsInterface)
- {
- m_isInterface = newIsInterface;
- }
-
- /**
- * @return boolean true if the mapped class is abstract
- */
- public boolean isAbstract()
- {
- return isAbstract;
- }
-
- /**
- * Returns acceptLocks.
- * @return boolean
- */
- public boolean isAcceptLocks()
- {
- return acceptLocks;
- }
-
- /**
- * Sets acceptLocks.
- * @param acceptLocks The m_acceptLocks to set
- */
- public void setAcceptLocks(boolean acceptLocks)
- {
- this.acceptLocks = acceptLocks;
- }
-
- /**
- * Gets the IndexDescriptors used for DDL generation.
- */
- public Vector getIndexes()
- {
- return indexes;
- }
-
- /**
- * Sets the IndexDescriptors used for DDL generation.
- */
- public void setIndexes(Vector indexes)
- {
- this.indexes = indexes;
- }
-
- /**
- * Gets the repository.
- * @return Returns a DescriptorRepository
- */
- public DescriptorRepository getRepository()
- {
- return m_repository;
- }
-
- /**
- * Sets the repository.
- * @param repository The repository to set
- */
- public void setRepository(DescriptorRepository repository)
- {
- m_repository = repository;
- }
+ /**
+ * Sets the repository.
+ * @param repository The repository to set
+ */
+ public void setRepository(DescriptorRepository repository)
+ {
+ m_repository = repository;
+ }
/**
* returns the transaction isolation level to be used for this class. Used only in the ODMG server
@@ -1751,27 +1518,9 @@
}
/**
- * Return a string representation of this class.
+ * sets the initialization method for this descriptor
*/
- public String toString()
- {
- ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
- return buf
- .append("classNameOfObject", getClassNameOfObject())
- .append("tableName", getTableName())
- .append("schema", getSchema())
- .append("isInterface", isInterface())
- .append("extendClassNames", getExtentClassNames().toString())
- //.append("[fieldDescriptions:")
- .append(getFieldDescriptions())
- //.append("]")
- .toString();
- }
-
- /**
- * sets the initialization method for this descriptor
- */
- private synchronized void setInitializationMethod(Method newMethod)
+ private synchronized void setInitializationMethod(Method newMethod)
{
if (newMethod != null)
{
@@ -2093,7 +1842,7 @@
*/
public void setPersistentFieldClassName(String pfClassName)
{
- this.persistentFieldClassName = pfClassName;
+ this.persistentFieldClassName = pfClassName;
}
@@ -2316,5 +2065,311 @@
public void setStateDetection(boolean stateDetection)
{
this.stateDetection = stateDetection;
+ }
+
+ public boolean hasAutoincrementPrimaryKey()
+ {
+ if(autoincrementPrimaryKey == null)
+ {
+ boolean result = false;
+ FieldDescriptor[] pks;
+ /*
+ if table per subclass inheritance is used we have to lookup
+ the PK fields of the base class to get the correct setting,
+ because in all sub-classes the autoincrement setting is always 'false'
+ */
+ if(getSuperClassDescriptor() != null)
+ {
+ ClassDescriptor baseClass = getSuperClassDescriptor();
+ while(baseClass.getSuperClassDescriptor() != null)
+ {
+ baseClass = baseClass.getSuperClassDescriptor();
+ }
+ pks = baseClass.getPkFields();
+ }
+ else
+ {
+ pks = getPkFields();
+ }
+ for(int i = 0; i < pks.length; i++)
+ {
+ FieldDescriptor pk = pks[i];
+ if(pk.isAutoIncrement())
+ {
+ result = true;
+ break;
+ }
+ }
+ autoincrementPrimaryKey = result ? Boolean.TRUE : Boolean.FALSE;
+ }
+ return autoincrementPrimaryKey.booleanValue();
+ }
+
+ /**
+ * Return a string representation of this class.
+ */
+ public String toString()
+ {
+ ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
+ return buf
+ .append("classNameOfObject", getClassNameOfObject())
+ .append("tableName", getTableName())
+ .append("schema", getSchema())
+ .append("baseClass", baseClass)
+ .append("proxyClass", proxyClassName)
+ .append("factoryClass", factoryClass)
+ .append("factoryMethod", factoryMethodName)
+ .append("extendClassNames", getExtentClassNames().toString())
+ //.append("[fieldDescriptions:")
+ .append("#fields==>", ArrayUtils.toString(getFieldDescriptor(false)))
+ //.append("]")
+ .toString();
+ }
+
+ /*
+ * @see XmlCapable#toXML()
+ */
+ public String toXML()
+ {
+ RepositoryTags tags = RepositoryTags.getInstance();
+ String eol = System.getProperty("line.separator");
+
+ // comment on class
+ StringBuffer result = new StringBuffer(1024);
+ result.append( eol);
+ result.append( " <!-- Mapping for Class ");
+ result.append( this.getClassNameOfObject());
+ result.append( " -->");
+ result.append( eol );
+
+ // opening tag and attributes
+ result.append( " ");
+ result.append( tags.getOpeningTagNonClosingById(CLASS_DESCRIPTOR));
+ result.append( eol );
+
+ // class
+ result.append( " ");
+ result.append( tags.getAttribute(CLASS_NAME, this.getClassNameOfObject()));
+ result.append( eol );
+
+ // isolation level is optional
+ if (null != getRepository())
+ {
+ if (getIsolationLevel() != this.getRepository().getDefaultIsolationLevel())
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(ISOLATION_LEVEL, this.isolationLevelXml()) );
+ result.append( eol );
+ }
+ }
+
+ Class theProxyClass = null;
+ try
+ {
+ theProxyClass = this.getProxyClass();
+ }
+ catch (Throwable t)
+ {
+ // Ignore this exception, just try to get the Class object of the
+ // proxy class in order to be able to decide, whether the class
+ // is a dynamic proxy or not.
+ }
+
+ // proxy is optional
+ if (theProxyClass != null)
+ {
+ if (isDynamicProxy()) // tomdz: What about VirtualProxy ?
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(CLASS_PROXY, DYNAMIC_STR));
+ result.append( eol );
+ }
+ else
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(CLASS_PROXY, this.getProxyClassName()));
+ result.append( eol );
+ }
+ result.append( " ");
+ result.append( tags.getAttribute(PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit()));
+ result.append( eol );
+ }
+
+ // schema is optional
+ if (this.getSchema() != null)
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(SCHEMA_NAME, this.getSchema()));
+ result.append( eol );
+ }
+
+ // table name
+ if (this.getTableName() != null)
+ {
+ result.append(" ");
+ result.append( tags.getAttribute(TABLE_NAME, this.getTableName()));
+ result.append( eol );
+ }
+
+ // rowreader is optional
+ if (this.getRowReaderClassName() != null)
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(ROW_READER, this.getRowReaderClassName()));
+ result.append( eol );
+ }
+
+ //accept-locks is optional, enabled by default
+ if (!this.acceptLocks)
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(ACCEPT_LOCKS, "false"));
+ result.append( eol );
+ }
+ // sequence manager attribute not yet implemented
+
+ // initialization method is optional
+ if (this.getInitializationMethod() != null)
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(INITIALIZATION_METHOD, this.getInitializationMethod().getName()));
+ result.append( eol );
+ }
+
+ // factory class is optional
+ if (this.getFactoryClass() != null)
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(FACTORY_CLASS, this.getFactoryClass().getName()) );
+ result.append( eol );
+ }
+
+ // factory method is optional
+ if (this.getFactoryMethod() != null)
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(FACTORY_METHOD, this.getFactoryMethod().getName()) );
+ result.append( eol );
+ }
+
+ //reference refresh is optional, disabled by default
+ if (isAlwaysRefresh())
+ {
+ result.append( " ");
+ result.append( tags.getAttribute(REFRESH, "true"));
+ result.append( eol );
+ }
+
+ result.append( " >");
+ result.append( eol );
+
+ // end of attributes
+
+ // begin of elements
+ if (isInterface())
+ {
+ // extent-class
+ for (int i = 0; i < getExtentClassNames().size(); i++)
+ {
+ result.append( " ");
+ result.append( tags.getOpeningTagNonClosingById(CLASS_EXTENT));
+ result.append( " " );
+ result.append( tags.getAttribute(CLASS_REF, getExtentClassNames().get(i).toString()) );
+ result.append( " />");
+ result.append( eol );
+ }
+ }
+ else
+ {
+ // class extent is optional
+ if (isExtent())
+ {
+ for (int i = 0; i < getExtentClassNames().size(); i++)
+ {
+ result.append( " ");
+ result.append( tags.getOpeningTagNonClosingById(CLASS_EXTENT));
+ result.append( " " );
+ result.append( tags.getAttribute(CLASS_REF, getExtentClassNames().get(i).toString()) );
+ result.append( " />");
+ result.append( eol );
+ }
+ }
+
+ // write all FieldDescriptors
+ FieldDescriptor[] fields = getFieldDescriptions();
+ for (int i = 0; i < fields.length; i++)
+ {
+ result.append( fields[i].toXML() );
+ }
+
+ // write optional ReferenceDescriptors
+ Vector refs = getObjectReferenceDescriptors();
+ for (int i = 0; i < refs.size(); i++)
+ {
+ result.append( ((ObjectReferenceDescriptor) refs.get(i)).toXML() );
+ }
+
+ // write optional CollectionDescriptors
+ Vector cols = getCollectionDescriptors();
+ for (int i = 0; i < cols.size(); i++)
+ {
+ result.append( ((CollectionDescriptor) cols.get(i)).toXML() );
+ }
+
+ // write optional IndexDescriptors
+ for (int i = 0; i < indexes.size(); i++)
+ {
+ IndexDescriptor indexDescriptor = (IndexDescriptor) indexes.elementAt(i);
+ result.append( indexDescriptor.toXML() );
+ }
+
+ // Write out the procedures
+ if (this.getInsertProcedure() != null)
+ {
+ result.append( this.getInsertProcedure().toXML() );
+ }
+ if (this.getUpdateProcedure() != null)
+ {
+ result.append( this.getUpdateProcedure().toXML() );
+ }
+ if (this.getDeleteProcedure() != null)
+ {
+ result.append( this.getDeleteProcedure().toXML() );
+ }
+ }
+ result.append( " ");
+ result.append( tags.getClosingTagById(CLASS_DESCRIPTOR) );
+ return result.toString();
+ }
+
+ private String isolationLevelXml()
+ {
+ switch (this.getIsolationLevel())
+ {
+ case (IL_OPTIMISTIC) :
+ {
+ return LITERAL_IL_OPTIMISTIC;
+ }
+ case (IL_READ_COMMITTED) :
+ {
+ return LITERAL_IL_READ_COMMITTED;
+ }
+ case (IL_READ_UNCOMMITTED) :
+ {
+ return LITERAL_IL_READ_UNCOMMITTED;
+ }
+ case (IL_REPEATABLE_READ) :
+ {
+ return LITERAL_IL_REPEATABLE_READ;
+ }
+ case (IL_SERIALIZABLE) :
+ {
+ return LITERAL_IL_SERIALIZABLE;
+ }
+ default :
+ {
+ return LITERAL_IL_READ_UNCOMMITTED;
+ }
+ }
}
}
Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/DescriptorRepository.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/DescriptorRepository.java?view=diff&rev=538372&r1=538371&r2=538372
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/DescriptorRepository.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/DescriptorRepository.java Tue May 15 16:10:14 2007
@@ -25,7 +25,6 @@
import java.util.Map;
import java.util.Set;
-import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
@@ -76,11 +75,12 @@
* (@see DescriptorRepository#getExtentClass). To speed up the costy
* evaluation, we use this tiny hash map.
*/
- private final Map extentTable;
-
- private Map superClassMultipleJoinedTablesMap;
+ private final Map superClassForExtentMap;
+ private final Map superClassMultipleJoinedTablesMap;
+ private final Map classesToSameTableMap;
private transient Map m_multiMappedTableMap;
+ private transient Map m_subClassesToSameTableMap;
private transient Map m_topLevelClassTable;
private transient Map m_firstConcreteClassMap;
private transient Map m_allConcreteSubClass;
@@ -94,9 +94,10 @@
*/
public DescriptorRepository() throws PersistenceBrokerException
{
- descriptorTable = new HashMap();
- extentTable = new HashMap();
- superClassMultipleJoinedTablesMap = new HashMap();
+ descriptorTable = new HashMap(30);
+ superClassForExtentMap = new HashMap(30);
+ superClassMultipleJoinedTablesMap = new HashMap(30);
+ classesToSameTableMap = new HashMap(30);
}
public static String getVersion()
@@ -105,47 +106,56 @@
}
/**
+ * Returns a map with all class names as key and the associated
+ * {@link ClassDescriptor} as value.
+ * @return The map used by this class (not cloned!).
+ */
+ public Map getDescriptorTable()
+ {
+ return descriptorTable;
+ }
+
+ private synchronized void changeDescriptorEvent()
+ {
+ m_multiMappedTableMap = null;
+ m_topLevelClassTable = null;
+ m_firstConcreteClassMap = null;
+ m_allConcreteSubClass = null;
+ m_batchConnectionKeyToFKMap = null;
+ m_subClassesToSameTableMap = null;
+ }
+
+ /**
* Add a pair of extent/classdescriptor to the extentTable to gain speed
- * while retrieval of extents.
- * @param classname the name of the extent itself
+ * while retrieval of super class descriptor for a given extent class.
+ *
+ * @param extent the name of the extent itself
* @param cld the class descriptor, where it belongs to
*/
- void addExtent(String classname, ClassDescriptor cld)
+ void addSuperClassForExtent(Class extent, ClassDescriptor cld)
{
- synchronized (extentTable)
+ synchronized (superClassForExtentMap)
{
- extentTable.put(classname, cld);
+ superClassForExtentMap.put(extent, cld);
}
}
/**
* Remove a pair of extent/classdescriptor from the extentTable.
- * @param classname the name of the extent itself
+ *
+ * @param extent the class of the extent itself.
*/
- void removeExtent(String classname)
+ void removeSuperClassForExtent(Class extent)
{
- synchronized (extentTable)
+ synchronized (superClassForExtentMap)
{
// returns the super class for given extent class name
- ClassDescriptor cld = (ClassDescriptor) extentTable.remove(classname);
- if(cld != null && m_topLevelClassTable != null)
+ ClassDescriptor cld = (ClassDescriptor) superClassForExtentMap.remove(extent);
+ if(cld != null)
{
- Class extClass;
- try
- {
- extClass = ClassHelper.getClass(classname);
- }
- catch (ClassNotFoundException e)
- {
- // Should not happen
- throw new MetadataException("Can't instantiate class object for needed extent remove", e);
- }
// remove extent from super class descriptor
- cld.removeExtentClass(classname);
- m_topLevelClassTable.remove(extClass);
- // clear map with first concrete classes, because the removed
- // extent could be such a first found concrete class
- m_firstConcreteClassMap = null;
+ cld.removeExtentClass(extent);
+ changeDescriptorEvent();
}
}
}
@@ -169,9 +179,9 @@
Class retval = (Class) m_topLevelClassTable.get(clazz);
if (retval == null)
{
- synchronized (extentTable)
+ synchronized (superClassForExtentMap)
{
- ClassDescriptor cld = (ClassDescriptor) extentTable.get(clazz.getName());
+ ClassDescriptor cld = (ClassDescriptor) superClassForExtentMap.get(clazz);
if (cld == null)
{
// walk the super-references
@@ -219,6 +229,10 @@
}
/**
+ * Returns all {@link FieldDescriptor} of the specified class and all sub-classes mapped
+ * to the same table as the specified one. This means all fields included in a table-per-hierarchy
+ * inheritance mapping via OJB's extent declaration.
+ *
* @return all field descriptors for a class that belongs to a set of classes mapped
* to the same table, otherwise the select queries produced won't contain the necessary
* information to materialize extents mapped to the same class.
@@ -248,7 +262,6 @@
then you can lose the stream data."
*/
List allFieldDescriptors = new ArrayList();
-
Set visitedColumns = new HashSet();
ClassDescriptor temp;
FieldDescriptor[] fields;
@@ -285,47 +298,150 @@
return retval;
}
- private List getClassesMappedToSameTable(ClassDescriptor targetCld)
+ private void registerClassesMappedToSameTable(ClassDescriptor cld)
{
- /*
- try to find an extent that contains clazz
- clone map to avoid synchronization problems, because another thread
- can do a put(..) operation on descriptor table
- */
- Iterator iter = ((HashMap)descriptorTable.clone()).values().iterator();
- List retval = new ArrayList();
- /*
- make sure that target class is at first position
- this is mandatory, because only this way we can guarantee to extract
- the correct field-descriptor in method #getAllMappedColumns
- */
- retval.add(targetCld);
- while (iter.hasNext())
+ String tableName = cld.getFullTableName();
+ if(tableName != null)
{
- ClassDescriptor cld = (ClassDescriptor) iter.next();
- if (cld.getFullTableName() != null)
+ List result = (List) classesToSameTableMap.get(cld.getFullTableName());
+ if(result == null)
{
- if (cld.getFullTableName().equals(targetCld.getFullTableName())
- && !targetCld.getClassOfObject().equals(cld.getClassOfObject()))
- {
- retval.add(cld);
- }
+ result = new ArrayList();
+ result.add(cld);
+ classesToSameTableMap.put(cld.getFullTableName(), result);
+ }
+ else
+ {
+ result.add(cld);
}
}
- return retval;
}
- public Map getDescriptorTable()
+ private void deregisterClassesToSameTable(ClassDescriptor cld)
{
- return descriptorTable;
+ String tableName = cld.getFullTableName();
+ if(tableName != null)
+ {
+ List result = (List) classesToSameTableMap.get(cld.getFullTableName());
+ if(result != null)
+ {
+ result.remove(cld);
+ }
+ }
+ }
+
+ /**
+ * Returns a list of all {@link ClassDescriptor} mapped to the same table as the
+ * specified class - independent from any inheritance mappings. The specified
+ * descriptor is included in the returned list.
+ *
+ * @param cld The souce class descriptor.
+ * @return A list of classes mapped to the same table. If the specified class isn't
+ * mapped to a table <em>null</em> will be returned. If no other class is mapped to
+ * the same table the list only contains the specified {@link ClassDescriptor}.
+ * @see #getSubClassesMappedToSameTable(ClassDescriptor)
+ * @see #getSubClassesMultipleJoinedTables(ClassDescriptor, boolean)
+ */
+ public List getClassesMappedToSameTable(ClassDescriptor cld)
+ {
+ if(cld.getFullTableName() == null)
+ {
+ return null;
+ }
+ else
+ {
+ List result = (List) classesToSameTableMap.get(cld.getFullTableName());
+ if(result == null || result.isEmpty())
+ {
+ throw new MetadataException("Inconsistent metadata detected, the specified descriptor for class "
+ + cld.getClassNameOfObject() + " seems not or only partially registered");
+ }
+ return result;
+ }
+ }
+
+// replaced by #getClassesMappedToSameTable
+// private List getAllMappedToSameTable(ClassDescriptor cld)
+// {
+// /*
+// try to find an extent that contains clazz
+// clone map to avoid synchronization problems, because another thread
+// can do a put(..) operation on descriptor table
+// */
+// Iterator iter = ((HashMap)descriptorTable.clone()).values().iterator();
+// List retval = new ArrayList();
+// /*
+// make sure that target class is at first position
+// this is mandatory, because only this way we can guarantee to extract
+// the correct field-descriptor in method #getAllMappedColumns
+// */
+// retval.add(cld);
+// while (iter.hasNext())
+// {
+// ClassDescriptor tmpCld = (ClassDescriptor) iter.next();
+// if (tmpCld.getFullTableName() != null)
+// {
+// if (tmpCld.getFullTableName().equals(cld.getFullTableName())
+// && !cld.getClassOfObject().equals(tmpCld.getClassOfObject()))
+// {
+// retval.add(tmpCld);
+// }
+// }
+// }
+// return retval;
+// }
+
+ /**
+ * Return a list of sub-class {@link ClassDescriptor} mapped to the same table
+ * as the specified class using OJB's table-per-hierarchy inheritence via
+ * extent-declaration.
+ *
+ * @param cld The source class descriptor.
+ * @return A list of found descriptor. If the specified class isn't mapped
+ * to a table <em>null</em> will be returned. If no sub-classes can be found
+ * an empty list is returned.
+ * @see #getSubClassesMultipleJoinedTables(ClassDescriptor, boolean)
+ * @see #getClassesMappedToSameTable(ClassDescriptor)
+ */
+ public List getSubClassesMappedToSameTable(ClassDescriptor cld)
+ {
+ if(m_subClassesToSameTableMap == null)
+ {
+ m_subClassesToSameTableMap = new HashMap();
+ }
+ // we can't do anything if class is not mapped to a table
+ if(cld.getFullTableName() == null) return null;
+
+ List result = (List) m_subClassesToSameTableMap.get(cld);
+ if(result == null)
+ {
+ result = new ArrayList();
+ Collection extents = getSubclassDescriptors(cld);
+ if(extents != null)
+ {
+ for(Iterator iterator = extents.iterator(); iterator.hasNext();)
+ {
+ ClassDescriptor tmp = (ClassDescriptor) iterator.next();
+ if(cld.getFullTableName().equals(tmp.getFullTableName()))
+ {
+ result.add(tmp);
+ }
+ }
+ }
+ m_subClassesToSameTableMap.put(cld, result);
+ }
+ return result;
}
/**
* Return the first found concrete class {@link ClassDescriptor}.
* This means a class which is not an interface or an abstract class.
* If given class descriptor is a concrete class, given class descriptor
- * was returned. If no concrete class can be found <code>null</code> will be
- * returned.
+ * was returned.
+ *
+ * @param cld The {@link ClassDescriptor} to search for concrete class.
+ * @return The first found concrete class or if the specified class is
+ * already a non-interface or abstract class.
*/
public ClassDescriptor findFirstConcreteClass(ClassDescriptor cld)
{
@@ -350,8 +466,8 @@
}
else
{
- LoggerFactory.getDefaultLogger().error("["+this.getClass().getName()+"] Found interface/abstract class" +
- " in metadata declarations without concrete class: "+cld.getClassNameOfObject());
+ log.error("Found interface/abstract class in metadata declarations without " +
+ "concrete class extent: "+cld.getClassNameOfObject());
}
m_firstConcreteClassMap.put(cld.getClassNameOfObject(), result);
}
@@ -368,44 +484,66 @@
* of a given super class.
*
* @return a collection of ClassDescriptor objects
+ * @deprecated please use {@link #getSubclassDescriptors(org.apache.ojb.broker.metadata.ClassDescriptor)}.
*/
public Collection getAllConcreteSubclassDescriptors(ClassDescriptor aCld)
{
+ return getSubclassDescriptors(aCld);
+ }
+
+ /**
+ * Utility method to discover all concrete (none abstract or interface) sub-class
+ * {@link ClassDescriptor} of the specified class using OJB's extent-declaration -
+ * includes all class mapping using table-per-hierarchy or table-per-class inheritance
+ * via OJB's extent-declaration.
+ *
+ * @return A collection of {@link ClassDescriptor} objects.
+ */
+ public Collection getSubclassDescriptors(ClassDescriptor cld)
+ {
if(m_allConcreteSubClass == null)
{
m_allConcreteSubClass = new HashMap();
}
- Collection concreteSubclassClds = (Collection) m_allConcreteSubClass.get(aCld.getClassOfObject());
+ Collection concreteSubclassClds = (Collection) m_allConcreteSubClass.get(cld.getClassOfObject());
if (concreteSubclassClds == null)
{
- // BRJ: ListOrderedSet prevents duplicates and ensures the order.
- concreteSubclassClds = new ListOrderedSet();
- Iterator iter = aCld.getExtentClasses().iterator();
+ // BRJ: As long as we do not have an ordered Set
+ // duplicates have to be prevented manually.
+ // a HashSet should not be used because the order is unpredictable
+ concreteSubclassClds = new ArrayList();
+ Iterator iter = cld.getExtentClasses().iterator();
while (iter.hasNext())
{
Class extentClass = (Class) iter.next();
ClassDescriptor extCld = getDescriptorFor(extentClass);
- if (aCld.equals(extCld))
+ if (cld.equals(extCld))
{
// prevent infinite recursion caused by cyclic references
continue;
}
if (!extCld.isInterface() && !extCld.isAbstract())
{
- concreteSubclassClds.add(extCld);
+ if (!concreteSubclassClds.contains(extCld))
+ {
+ concreteSubclassClds.add(extCld);
+ }
}
// recurse
- Iterator subIter = getAllConcreteSubclassDescriptors(extCld).iterator();
+ Iterator subIter = getSubclassDescriptors(extCld).iterator();
while (subIter.hasNext())
{
ClassDescriptor subCld = (ClassDescriptor)subIter.next();
- concreteSubclassClds.add(subCld);
+ if (!concreteSubclassClds.contains(subCld))
+ {
+ concreteSubclassClds.add(subCld);
+ }
}
}
- m_allConcreteSubClass.put(aCld.getClassOfObject(), concreteSubclassClds);
+ m_allConcreteSubClass.put(cld.getClassOfObject(), concreteSubclassClds);
}
return concreteSubclassClds;
@@ -454,8 +592,13 @@
}
/**
- * Add a ClassDescriptor to the internal Hashtable<br>
- * Set the Repository for ClassDescriptor
+ * Register an persistence capable class and add a {@link ClassDescriptor}
+ * - it's important that the added instance is completely configurated before
+ * before calling this method.
+ *
+ * @param c The class to register.
+ * @param cld The associated {@link ClassDescriptor}.
+ * @see #remove(Class) to remove an added descriptor.
*/
public void put(Class c, ClassDescriptor cld)
{
@@ -463,26 +606,60 @@
}
/**
- * Add a ClassDescriptor to the internal Hashtable<br>
- * Set the Repository for ClassDescriptor
+ * Register an persistence capable class and add a {@link ClassDescriptor}
+ * - it's important that the added instance is completely configurated before
+ * before calling this method.
+ *
+ * @param classname The full qualified class name to register.
+ * @param cld The associated {@link ClassDescriptor}.
+ * @see #remove(String) to remove an added descriptor.
*/
public void put(String classname, ClassDescriptor cld)
{
cld.setRepository(this); // BRJ
synchronized (descriptorTable)
{
+ if(descriptorTable.containsKey(classname))
+ {
+// try{throw new Exception("Warn: New class-descriptor added (without removing the old one first) for: "
+// + classname);}catch(Exception e)
+// {
+// log.warn("Replace already registered class '" + classname + "' with descriptor " + cld, e);
+// }
+ log.warn("Replace already registered class '" + classname + "' with descriptor " + cld);
+ }
descriptorTable.put(classname, cld);
List extentClasses = cld.getExtentClasses();
for (int i = 0; i < extentClasses.size(); ++i)
{
- addExtent(((Class) extentClasses.get(i)).getName(), cld);
+ addSuperClassForExtent(((Class) extentClasses.get(i)), cld);
}
+ registerClassesMappedToSameTable(cld);
changeDescriptorEvent();
}
}
+ /**
+ * Remove an registered {@link ClassDescriptor} of a persistence
+ * capable object.
+ * <br/>
+ * NOTE: All <em>extent class</em> entries of this class in other classes will be removed too.
+ *
+ * @param className The full qualified class name.
+ * @see #put(String, ClassDescriptor) to add an {@link ClassDescriptor}.
+ */
public void remove(String className)
{
+ Class clazz = null;
+ try
+ {
+ clazz = ClassHelper.getClass(className);
+ }
+ catch(ClassNotFoundException e)
+ {
+ log.error("Remove of class fails: Unable to find class [" + className
+ + "]. Make sure it is available on the classpath.", e);
+ }
synchronized (descriptorTable)
{
ClassDescriptor cld = (ClassDescriptor) descriptorTable.remove(className);
@@ -494,32 +671,47 @@
{
((ClassDescriptor) it.next()).removeExtentClass(className);
}
- removeExtent(className);
+ removeSuperClassForExtent(clazz);
List extentClasses = cld.getExtentClasses();
for (int i = 0; i < extentClasses.size(); ++i)
{
- removeExtent(((Class) extentClasses.get(i)).getName());
+ removeSuperClassForExtent(((Class) extentClasses.get(i)));
}
+ deregisterClassesToSameTable(cld);
changeDescriptorEvent();
// deregister classes using mapping of classes to multiple joined tables
// the registration is done by the class-descriptor itself
- deregisterSuperClassMultipleJoinedTables(cld);
+ deregisterTablePerSubclassInheritance(cld);
}
}
}
+ /**
+ * Remove an registered {@link ClassDescriptor} of a persistence
+ * capable object.
+ * <br/>
+ * NOTE: All <em>extent class</em> entries of this class in other classes will be removed too.
+ *
+ * @param clazz The class.
+ * @see #put(Class, ClassDescriptor) to add an {@link ClassDescriptor}.
+ */
public void remove(Class clazz)
{
remove(clazz.getName());
}
- private synchronized void changeDescriptorEvent()
+ /**
+ * Remove an registered {@link ClassDescriptor} of a persistence
+ * capable object.
+ * <br/>
+ * NOTE: All <em>extent class</em> entries of this class in other classes will be removed too.
+ *
+ * @param cld The {@link ClassDescriptor} of the class.
+ * @see #put(Class, ClassDescriptor) to add an {@link ClassDescriptor}.
+ */
+ public void remove(ClassDescriptor cld)
{
- m_multiMappedTableMap = null;
- m_topLevelClassTable = null;
- m_firstConcreteClassMap = null;
- m_allConcreteSubClass = null;
- m_batchConnectionKeyToFKMap = null;
+ remove(cld.getClassNameOfObject());
}
/**
@@ -534,89 +726,6 @@
}
/**
- * Returns the defaultIsolationLevel.
- * @return int
- */
- public int getDefaultIsolationLevel()
- {
- return defaultIsolationLevel;
- }
-
- /**
- * Sets the defaultIsolationLevel.
- * @param defaultIsolationLevel The defaultIsolationLevel to set
- */
- public void setDefaultIsolationLevel(int defaultIsolationLevel)
- {
- this.defaultIsolationLevel = defaultIsolationLevel;
- }
-
- /**
- * returns a string representation
- */
- public String toString()
- {
- Iterator it = descriptorTable.entrySet().iterator();
- ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
- String className = "class name: ";
- String tableName = "> table name: ";
- while (it.hasNext())
- {
- Map.Entry me = (Map.Entry) it.next();
- ClassDescriptor descriptor = (ClassDescriptor) me.getValue();
- buf.append(className + me.getKey() + " =", tableName + descriptor.getFullTableName());
- }
- return buf.toString();
- }
-
- /*
- * @see XmlCapable#toXML()
- */
- public String toXML()
- {
- String eol = SystemUtils.LINE_SEPARATOR;
- StringBuffer buf = new StringBuffer();
-
- // write all ClassDescriptors
- Iterator i = this.iterator();
- while (i.hasNext())
- {
- buf.append(((XmlCapable) i.next()).toXML()).append(eol);
- }
- return buf.toString();
- }
-
- /**
- * returns IsolationLevel literal as matching
- * to the corresponding id
- * @return the IsolationLevel literal
- */
- protected String getIsolationLevelAsString()
- {
- if (defaultIsolationLevel == IL_READ_UNCOMMITTED)
- {
- return LITERAL_IL_READ_UNCOMMITTED;
- }
- else if (defaultIsolationLevel == IL_READ_COMMITTED)
- {
- return LITERAL_IL_READ_COMMITTED;
- }
- else if (defaultIsolationLevel == IL_REPEATABLE_READ)
- {
- return LITERAL_IL_REPEATABLE_READ;
- }
- else if (defaultIsolationLevel == IL_SERIALIZABLE)
- {
- return LITERAL_IL_SERIALIZABLE;
- }
- else if (defaultIsolationLevel == IL_OPTIMISTIC)
- {
- return LITERAL_IL_OPTIMISTIC;
- }
- return LITERAL_IL_READ_UNCOMMITTED;
- }
-
- /**
* Starts by looking to see if the <code>className</code> is
* already mapped specifically to the descritpor repository.
* If the <code>className</code> is not specifically mapped we
@@ -698,16 +807,16 @@
}
/**
- * Internal used! Register sub-classes of specified class when mapping class to
- * multiple joined tables is used. Normally this method is called by the {@link ClassDescriptor}
- * itself.
+ * Internal used! Register the specified class as sub-class of it's base class.
+ * Specific method when table per subclass inheritance is used. Normally this
+ * method is called by the {@link ClassDescriptor} itself.
*
* @param cld The {@link ClassDescriptor} of the class to register.
*/
- protected void registerSuperClassMultipleJoinedTables(ClassDescriptor cld)
+ protected void registerTablePerSubclassInheritance(ClassDescriptor cld)
{
/*
- arminw: Sadly, we can't map to sub class-descriptor, because it's not guaranteed
+ arminw: Unfortunately, we can't map class-descriptors, because it's not guaranteed
that they exist when this method is called. Thus we map the class instance instead
of the class-descriptor.
*/
@@ -750,7 +859,7 @@
*
* @param cld The {@link ClassDescriptor} of the class to register.
*/
- protected void deregisterSuperClassMultipleJoinedTables(ClassDescriptor cld)
+ protected void deregisterTablePerSubclassInheritance(ClassDescriptor cld)
{
try
{
@@ -790,44 +899,73 @@
/**
* Return <em>sub-classes</em> of the specified class using the
- * <em>"super"-Reference</em> concept.
+ * <em>"super"-Reference</em> concept - table-per-subclass inheritance.
+ *
* @param cld The {@link ClassDescriptor} of the class to search for sub-classes.
* @param wholeTree If set <em>true</em>, the whole sub-class tree of the specified
* class will be returned. If <em>false</em> only the direct sub-classes of the specified class
* will be returned.
* @return An array of <em>sub-classes</em> for the specified class.
+ * @see #getClassesMappedToSameTable(ClassDescriptor)
+ * @see #getSubClassesMappedToSameTable(ClassDescriptor)
*/
public Class[] getSubClassesMultipleJoinedTables(ClassDescriptor cld, boolean wholeTree)
{
- ArrayList result = new ArrayList();
- createResultSubClassesMultipleJoinedTables(result, cld, wholeTree);
- return (Class[]) result.toArray(new Class[result.size()]);
+ List result = createResultSubClassesMultipleJoinedTables(cld, wholeTree);
+ return result != null ? (Class[]) result.toArray(new Class[result.size()]) : new Class[]{};
}
/**
* Add all sub-classes using multiple joined tables feature for specified class.
- * @param result The list to add results.
+ *
* @param cld The {@link ClassDescriptor} of the class to search for sub-classes.
* @param wholeTree If set <em>true</em>, the whole sub-class tree of the specified
* class will be returned. If <em>false</em> only the direct sub-classes of the specified class
* will be returned.
+ * @return A list of sub classes or <em>null</em> if none found.
*/
- private void createResultSubClassesMultipleJoinedTables(List result, ClassDescriptor cld, boolean wholeTree)
+ private List createResultSubClassesMultipleJoinedTables(ClassDescriptor cld, boolean wholeTree)
{
List tmp = (List) superClassMultipleJoinedTablesMap.get(cld.getClassOfObject());
- if(tmp != null)
+ if(wholeTree && tmp != null && tmp.size() > 0)
{
- result.addAll(tmp);
- if(wholeTree)
+ ArrayList list = new ArrayList(tmp);
+ for(int i = 0; i < tmp.size(); i++)
{
- for(int i = 0; i < tmp.size(); i++)
- {
- Class subClass = (Class) tmp.get(i);
- ClassDescriptor subCld = getDescriptorFor(subClass);
- createResultSubClassesMultipleJoinedTables(result, subCld, wholeTree);
- }
+ Class subClass = (Class) tmp.get(i);
+ ClassDescriptor subCld = getDescriptorFor(subClass);
+ List subList = createResultSubClassesMultipleJoinedTables(subCld, wholeTree);
+ if(subList != null) list.addAll(subList);
}
+ tmp = list;
}
+ return tmp;
+ }
+
+ /**
+ * Returns whether or not mapped classes should be included in
+ * object state detection. Default state is <em>true</em>.
+ *
+ * @return If <em>true</em> the classes will be included in
+ * automatic object state detection.
+ * @see #setStateDetection(boolean)
+ */
+ public boolean isStateDetection()
+ {
+ return stateDetection;
+ }
+
+ /**
+ * If the used API supports object state detection (e.g. ODMG-api does),
+ * this attribute indicate whether or not this mapped classes should be
+ * included in object state detection (automatic check for changed object fields).
+ *
+ * @param stateDetection Set <em>true</em> if automatic state detection should
+ * be enabled.
+ */
+ public void setStateDetection(boolean stateDetection)
+ {
+ this.stateDetection = stateDetection;
}
/**
@@ -904,17 +1042,15 @@
{
String tableName;
HashSet tableNamesSet = new HashSet();
- Collection extents = desc.getExtentClasses();
-
tableName = desc.getFullTableName();
if (tableName != null)
{
tableNamesSet.add(tableName);
}
+ Collection extents = getSubclassDescriptors(desc);
for (Iterator it = extents.iterator(); it.hasNext();)
{
- Class extClass = (Class) it.next();
- ClassDescriptor extDesc = getDescriptorFor(extClass);
+ ClassDescriptor extDesc = (ClassDescriptor) it.next();
tableName = extDesc.getFullTableName();
if (tableName != null)
{
@@ -925,34 +1061,85 @@
}
/**
- * Returns whether or not mapped classes should be included in
- * object state detection. Default state is <em>true</em>.
- *
- * @return If <em>true</em> the classes will be included in
- * automatic object state detection.
- * @see #setStateDetection(boolean)
+ * Returns the defaultIsolationLevel.
+ * @return int
*/
- public boolean isStateDetection()
+ public int getDefaultIsolationLevel()
{
- return stateDetection;
+ return defaultIsolationLevel;
}
/**
- * If the used API supports object state detection (e.g. ODMG-api does),
- * this attribute indicate whether or not this mapped classes should be
- * included in object state detection (automatic check for changed object fields).
- *
- * @param stateDetection Set <em>true</em> if automatic state detection should
- * be enabled.
+ * Sets the defaultIsolationLevel.
+ * @param defaultIsolationLevel The defaultIsolationLevel to set
*/
- public void setStateDetection(boolean stateDetection)
+ public void setDefaultIsolationLevel(int defaultIsolationLevel)
{
- this.stateDetection = stateDetection;
+ this.defaultIsolationLevel = defaultIsolationLevel;
+ }
+
+ /**
+ * returns IsolationLevel literal as matching
+ * to the corresponding id
+ * @return the IsolationLevel literal
+ */
+ protected String getIsolationLevelAsString()
+ {
+ if (defaultIsolationLevel == IL_READ_UNCOMMITTED)
+ {
+ return LITERAL_IL_READ_UNCOMMITTED;
+ }
+ else if (defaultIsolationLevel == IL_READ_COMMITTED)
+ {
+ return LITERAL_IL_READ_COMMITTED;
+ }
+ else if (defaultIsolationLevel == IL_REPEATABLE_READ)
+ {
+ return LITERAL_IL_REPEATABLE_READ;
+ }
+ else if (defaultIsolationLevel == IL_SERIALIZABLE)
+ {
+ return LITERAL_IL_SERIALIZABLE;
+ }
+ else if (defaultIsolationLevel == IL_OPTIMISTIC)
+ {
+ return LITERAL_IL_OPTIMISTIC;
+ }
+ return LITERAL_IL_READ_UNCOMMITTED;
}
- protected void finalize() throws Throwable
+ /**
+ * returns a string representation
+ */
+ public String toString()
{
- log.info("# finalize DescriptorRepository instance #");
- super.finalize();
+ Iterator it = descriptorTable.entrySet().iterator();
+ ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
+ String className = "class name: ";
+ String tableName = "> table name: ";
+ while (it.hasNext())
+ {
+ Map.Entry me = (Map.Entry) it.next();
+ ClassDescriptor descriptor = (ClassDescriptor) me.getValue();
+ buf.append(className + me.getKey() + " =", tableName + descriptor.getFullTableName());
+ }
+ return buf.toString();
+ }
+
+ /*
+ * @see XmlCapable#toXML()
+ */
+ public String toXML()
+ {
+ String eol = SystemUtils.LINE_SEPARATOR;
+ StringBuffer buf = new StringBuffer();
+
+ // write all ClassDescriptors
+ Iterator i = this.iterator();
+ while (i.hasNext())
+ {
+ buf.append(((XmlCapable) i.next()).toXML()).append(eol);
+ }
+ return buf.toString();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org