Index: cpa/src/main/java/org/exolab/castor/jdo/engine/SQLEngine.java =================================================================== --- cpa/src/main/java/org/exolab/castor/jdo/engine/SQLEngine.java (revision 8890) +++ cpa/src/main/java/org/exolab/castor/jdo/engine/SQLEngine.java (working copy) @@ -30,6 +30,7 @@ import org.castor.cpa.persistence.sql.engine.SQLStatementUpdate; import org.castor.cpa.persistence.sql.engine.info.InfoFactory; import org.castor.cpa.persistence.sql.engine.info.TableInfo; +import org.castor.cpa.util.JDOClassDescriptorResolver; import org.castor.persist.ProposedEntity; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.PersistenceException; @@ -49,6 +50,8 @@ import org.exolab.castor.persist.spi.PersistenceFactory; import org.exolab.castor.persist.spi.PersistenceQuery; import org.exolab.castor.persist.spi.QueryExpression; +import org.exolab.castor.xml.ClassDescriptorResolver; +import org.exolab.castor.xml.ResolverException; /** * The SQL engine performs persistence of one object type against one @@ -212,13 +215,117 @@ _storeStatement = new SQLStatementUpdate(this); } - public SQLRelationLoader createSQLRelationLoader(final String manyTable, - final String[] idSQL, final int[] idType, - final TypeConvertor[] idTo, final TypeConvertor[] idFrom, - final String[] relatedIdSQL, final int[] relatedIdType, - final TypeConvertor[] ridTo, final TypeConvertor[] ridFrom) { - return new SQLRelationLoader(manyTable, idSQL, idType, idTo, idFrom, - relatedIdSQL, relatedIdType, ridTo, ridFrom, _factory); + /** + * {@inheritDoc} + */ + public SQLRelationLoader createSQLRelationLoader( + final ClassDescriptorResolver classDescriptorResolver, + final ClassDescriptor classDescriptor, final FieldDescriptor[] identityDescriptors, + final FieldDescriptor fieldDescriptor) throws MappingException { + FieldDescriptorJDONature nature = new FieldDescriptorJDONature(fieldDescriptor); + + // the fields is not primitive + String[] relatedIdSQL = null; + int[] relatedIdType = null; + TypeConvertor[] relatedIdConvertTo = null; + TypeConvertor[] relatedIdConvertFrom = null; + + String manyTable = nature.getManyTable(); + + String[] idSQL = new String[identityDescriptors.length]; + int[] idType = new int[identityDescriptors.length]; + TypeConvertor[] idConvertFrom = new TypeConvertor[identityDescriptors.length]; + TypeConvertor[] idConvertTo = new TypeConvertor[identityDescriptors.length]; + FieldDescriptor[] identityFieldDescriptors = + ((ClassDescriptorImpl) classDescriptor).getIdentities(); + int identityFieldCount = 0; + for (FieldDescriptor identityFieldDescriptor : identityFieldDescriptors) { + if (identityFieldDescriptor.hasNature( + FieldDescriptorJDONature.class.getName())) { + idSQL[identityFieldCount] = new FieldDescriptorJDONature( + identityFieldDescriptor).getSQLName()[0]; + int[] type = new FieldDescriptorJDONature( + identityFieldDescriptor).getSQLType(); + idType[identityFieldCount] = (type == null) ? 0 : type[0]; + FieldHandlerImpl fieldHandler = + (FieldHandlerImpl) identityFieldDescriptor.getHandler(); + idConvertTo[identityFieldCount] = fieldHandler.getConvertTo(); + idConvertFrom[identityFieldCount] = fieldHandler.getConvertFrom(); + } else { + throw new MappingException( + "Identity type must contains sql information: " + + classDescriptor.getJavaClass().getName()); + } + identityFieldCount++; + } + + ClassDescriptor relatedClassDescriptor = null; + try { + JDOClassDescriptorResolver jdoCDR = + (JDOClassDescriptorResolver) classDescriptorResolver; + relatedClassDescriptor = + jdoCDR.resolve(fieldDescriptor.getFieldType().getName()); + } catch (ResolverException e) { + throw new MappingException("Problem resolving class descriptor for class " + + fieldDescriptor.getClass().getName(), e); + } + + if (relatedClassDescriptor.hasNature(ClassDescriptorJDONature.class.getName())) { + FieldDescriptor[] relatedIdentityDescriptors = + ((ClassDescriptorImpl) relatedClassDescriptor).getIdentities(); + relatedIdSQL = new String[relatedIdentityDescriptors.length]; + relatedIdType = new int[relatedIdentityDescriptors.length]; + relatedIdConvertTo = new TypeConvertor[relatedIdentityDescriptors.length]; + relatedIdConvertFrom = new TypeConvertor[relatedIdentityDescriptors.length]; + int relatedIdentityCount = 0; + for (FieldDescriptor relatedIdentityDescriptor : relatedIdentityDescriptors) { + if (relatedIdentityDescriptor.hasNature( + FieldDescriptorJDONature.class.getName())) { + FieldDescriptorJDONature relatedNature = new FieldDescriptorJDONature( + relatedIdentityDescriptor); + String[] tempId = relatedNature.getSQLName(); + relatedIdSQL[relatedIdentityCount] = + (tempId == null) ? null : tempId[0]; + int[] tempType = relatedNature.getSQLType(); + relatedIdType[relatedIdentityCount] = + (tempType == null) ? 0 : tempType[0]; + FieldHandlerImpl fh = (FieldHandlerImpl) + relatedIdentityDescriptors[relatedIdentityCount].getHandler(); + relatedIdConvertTo[relatedIdentityCount] = fh.getConvertTo(); + relatedIdConvertFrom[relatedIdentityCount] = fh.getConvertFrom(); + } else { + throw new MappingException("Field type is not persistence-capable: " + + relatedIdentityDescriptors[relatedIdentityCount] + .getFieldName()); + } + relatedIdentityCount++; + } + } + + // if many-key exist, idSQL is overridden + String[] manyKey = nature.getManyKey(); + if ((manyKey != null) && (manyKey.length != 0)) { + if (manyKey.length != idSQL.length) { + throw new MappingException( + "The number of many-keys doesn't match referred object: " + + classDescriptor.getJavaClass().getName()); + } + idSQL = manyKey; + } + + // if name="" exist, relatedIdSQL is overridden + String[] manyName = nature.getSQLName(); + if ((manyName != null) && (manyName.length != 0)) { + if (manyName.length != relatedIdSQL.length) { + throw new MappingException( + "The number of many-keys doesn't match referred object: " + + relatedClassDescriptor.getJavaClass().getName()); + } + relatedIdSQL = manyName; + } + + return new SQLRelationLoader(manyTable, idSQL, idType, idConvertTo, idConvertFrom, + relatedIdSQL, relatedIdType, relatedIdConvertTo, relatedIdConvertFrom, _factory); } public SQLColumnInfo[] getColumnInfoForIdentities() { Index: cpa/src/main/java/org/exolab/castor/persist/ClassMolder.java =================================================================== --- cpa/src/main/java/org/exolab/castor/persist/ClassMolder.java (revision 8890) +++ cpa/src/main/java/org/exolab/castor/persist/ClassMolder.java (working copy) @@ -53,7 +53,6 @@ import org.apache.commons.logging.LogFactory; import org.castor.core.util.Messages; import org.castor.cpa.persistence.sql.engine.CastorConnection; -import org.castor.cpa.util.JDOClassDescriptorResolver; import org.castor.jdo.util.ClassLoadingUtils; import org.castor.persist.ProposedEntity; import org.castor.persist.TransactionContext; @@ -74,16 +73,13 @@ import org.exolab.castor.mapping.FieldDescriptor; import org.exolab.castor.mapping.FieldHandler; import org.exolab.castor.mapping.MappingException; -import org.exolab.castor.mapping.TypeConvertor; import org.exolab.castor.mapping.loader.ClassDescriptorHelper; import org.exolab.castor.mapping.loader.ClassDescriptorImpl; -import org.exolab.castor.mapping.loader.FieldHandlerImpl; import org.exolab.castor.mapping.xml.NamedNativeQuery; import org.exolab.castor.persist.spi.CallbackInterceptor; import org.exolab.castor.persist.spi.Identity; import org.exolab.castor.persist.spi.Persistence; import org.exolab.castor.xml.ClassDescriptorResolver; -import org.exolab.castor.xml.ResolverException; /** * ClassMolder is a 'binder' for one type of data object and its corresponding @@ -245,110 +241,9 @@ if (fieldDescriptor.hasNature(FieldDescriptorJDONature.class.getName()) && new FieldDescriptorJDONature(fieldDescriptor).getManyTable() != null) { - FieldDescriptorJDONature nature = new FieldDescriptorJDONature(fieldDescriptor); - - // the fields is not primitive - String[] relatedIdSQL = null; - int[] relatedIdType = null; - TypeConvertor[] relatedIdConvertTo = null; - TypeConvertor[] relatedIdConvertFrom = null; - - String manyTable = nature.getManyTable(); - - String[] idSQL = new String[identityDescriptors.length]; - int[] idType = new int[identityDescriptors.length]; - TypeConvertor[] idConvertFrom = new TypeConvertor[identityDescriptors.length]; - TypeConvertor[] idConvertTo = new TypeConvertor[identityDescriptors.length]; - FieldDescriptor[] identityFieldDescriptors = - ((ClassDescriptorImpl) classDescriptor).getIdentities(); - int identityFieldCount = 0; - for (FieldDescriptor identityFieldDescriptor : identityFieldDescriptors) { - if (identityFieldDescriptor.hasNature( - FieldDescriptorJDONature.class.getName())) { - idSQL[identityFieldCount] = new FieldDescriptorJDONature( - identityFieldDescriptor).getSQLName()[0]; - int[] type = new FieldDescriptorJDONature( - identityFieldDescriptor).getSQLType(); - idType[identityFieldCount] = (type == null) ? 0 : type[0]; - FieldHandlerImpl fieldHandler = - (FieldHandlerImpl) identityFieldDescriptor.getHandler(); - idConvertTo[identityFieldCount] = fieldHandler.getConvertTo(); - idConvertFrom[identityFieldCount] = fieldHandler.getConvertFrom(); - } else { - throw new MappingException( - "Identity type must contains sql information: " + _name); - } - identityFieldCount++; - } - - ClassDescriptor relatedClassDescriptor = null; - try { - JDOClassDescriptorResolver jdoCDR = - (JDOClassDescriptorResolver) classDescriptorResolver; - relatedClassDescriptor = - jdoCDR.resolve(fieldDescriptor.getFieldType().getName()); - } catch (ResolverException e) { - throw new MappingException("Problem resolving class descriptor for class " - + fieldDescriptor.getClass().getName(), e); - } - - if (relatedClassDescriptor.hasNature(ClassDescriptorJDONature.class.getName())) { - FieldDescriptor[] relatedIdentityDescriptors = - ((ClassDescriptorImpl) relatedClassDescriptor).getIdentities(); - relatedIdSQL = new String[relatedIdentityDescriptors.length]; - relatedIdType = new int[relatedIdentityDescriptors.length]; - relatedIdConvertTo = new TypeConvertor[relatedIdentityDescriptors.length]; - relatedIdConvertFrom = new TypeConvertor[relatedIdentityDescriptors.length]; - int relatedIdentityCount = 0; - for (FieldDescriptor relatedIdentityDescriptor : relatedIdentityDescriptors) { - if (relatedIdentityDescriptor.hasNature( - FieldDescriptorJDONature.class.getName())) { - FieldDescriptorJDONature relatedNature = new FieldDescriptorJDONature( - relatedIdentityDescriptor); - String[] tempId = relatedNature.getSQLName(); - relatedIdSQL[relatedIdentityCount] = - (tempId == null) ? null : tempId[0]; - int[] tempType = relatedNature.getSQLType(); - relatedIdType[relatedIdentityCount] = - (tempType == null) ? 0 : tempType[0]; - FieldHandlerImpl fh = (FieldHandlerImpl) - relatedIdentityDescriptors[relatedIdentityCount].getHandler(); - relatedIdConvertTo[relatedIdentityCount] = fh.getConvertTo(); - relatedIdConvertFrom[relatedIdentityCount] = fh.getConvertFrom(); - } else { - throw new MappingException("Field type is not persistence-capable: " - + relatedIdentityDescriptors[relatedIdentityCount] - .getFieldName()); - } - relatedIdentityCount++; - } - } - - // if many-key exist, idSQL is overridden - String[] manyKey = nature.getManyKey(); - if ((manyKey != null) && (manyKey.length != 0)) { - if (manyKey.length != idSQL.length) { - throw new MappingException( - "The number of many-keys doesn't match referred object: " - + classDescriptor.getJavaClass().getName()); - } - idSQL = manyKey; - } - - // if name="" exist, relatedIdSQL is overridden - String[] manyName = nature.getSQLName(); - if ((manyName != null) && (manyName.length != 0)) { - if (manyName.length != relatedIdSQL.length) { - throw new MappingException( - "The number of many-keys doesn't match referred object: " - + relatedClassDescriptor.getJavaClass().getName()); - } - relatedIdSQL = manyName; - } - SQLRelationLoader loader = _persistence.createSQLRelationLoader( - manyTable, idSQL, idType, idConvertTo, idConvertFrom, - relatedIdSQL, relatedIdType, relatedIdConvertTo, relatedIdConvertFrom); + classDescriptorResolver, classDescriptor, identityDescriptors, + fieldDescriptor); _fhs[fieldMolderCount] = new FieldMolder(ds, this, fieldDescriptor, loader); } else { _fhs[fieldMolderCount] = new FieldMolder(ds, this, fieldDescriptor); Index: cpa/src/main/java/org/exolab/castor/persist/spi/Persistence.java =================================================================== --- cpa/src/main/java/org/exolab/castor/persist/spi/Persistence.java (revision 8890) +++ cpa/src/main/java/org/exolab/castor/persist/spi/Persistence.java (working copy) @@ -50,8 +50,11 @@ import org.exolab.castor.jdo.PersistenceException; import org.exolab.castor.jdo.QueryException; import org.exolab.castor.mapping.AccessMode; -import org.exolab.castor.mapping.TypeConvertor; +import org.exolab.castor.mapping.ClassDescriptor; +import org.exolab.castor.mapping.FieldDescriptor; +import org.exolab.castor.mapping.MappingException; import org.exolab.castor.persist.SQLRelationLoader; +import org.exolab.castor.xml.ClassDescriptorResolver; /** * The persistence engine implements this interface in order to allow @@ -185,10 +188,22 @@ PersistenceQuery createQuery(QueryExpression query, Class[] types, AccessMode accessMode) throws QueryException; - SQLRelationLoader createSQLRelationLoader(String manyTable, - String[] idSQL, int[] idType, - TypeConvertor[] idTo, TypeConvertor[] idFrom, - String[] relatedIdSQL, int[] relatedIdType, - TypeConvertor[] ridTo, TypeConvertor[] ridFrom); + /** + * Creates an instance of SQLRelationLoader for creating and removing + * relation from a many-to-many relation database. + * + * @param classDescriptorResolver {@link ClassDescriptorResolver} instance + * @param classDescriptor the classDescriptor for the base class. + * @param identityDescriptors the {@link FieldDescriptor}s that describe the identities + * as defined for this class. + * @param fieldDescriptor the {@link FieldDescriptor} for non-identity fields, + * including all the fields in base classes. + * @throws MappingException if an error occurred with analyzing the mapping information. + * @return SQLRelationLoader, for creating and removing relation from a + * many-to-many relation database. + */ + SQLRelationLoader createSQLRelationLoader(ClassDescriptorResolver classDescriptorResolver, + ClassDescriptor classDescriptor, FieldDescriptor[] identityDescriptors, + FieldDescriptor fieldDescriptor) throws MappingException; }