// Verify if a duplicate column is valid. A duplicate column name is (currently) valid when :-
// 1. subclasses defining the duplicated column are using "super class table" strategy
//
// Find the MetaData for the existing column
DatastoreIdentifier name = col.getIdentifier();
DatastoreField existingCol = getDatastoreField(name);
MetaData md = existingCol.getColumnMetaData().getParent();
while (!(md instanceof AbstractClassMetaData)) {
if (md == null) {
// ColumnMetaData for existing column has no parent class somehow!
throw new NucleusUserException(MessageFormat.format(
"The property \"{0}\" exists in entity \"{1}\" and has invalid metadata. The existing property is \"{2}\"",
name, this.identifier, colmd.toString()));
}
md = md.getParent();
}
// Find the MetaData for the column to be added
MetaData dupMd = colmd.getParent();
while (!(dupMd instanceof AbstractClassMetaData)) {
dupMd = dupMd.getParent();
if (dupMd == null) {
// ColumnMetaData for required column has no parent class somehow!
throw new NucleusUserException(MessageFormat.format(
"The column \"{0}\" exists in table \"{1}\" and cannot be validated because a duplicated column has been specified and the metadata is invalid. The column is \"{2}\"",
name, this.identifier, colmd.toString()));
}
}
if (((AbstractClassMetaData) md).getFullClassName().equals(
((AbstractClassMetaData) dupMd).getFullClassName())) {
// compare the current column defining class and the duplicated column defining class. if the same class,
// we raise an exception when within one class it is defined a column twice
// in some cases it could still be possible to have these duplicated columns, but does not make too
// much sense in most of the cases. (this whole block of duplicated column check, could be optional, like a pmf property)
throw new DuplicateDatastoreFieldException(this.toString(), existingCol, col);
}
// Make sure the field JavaTypeMappings are compatible
if (mapping != null &&
!mapping.getClass().isAssignableFrom(existingCol.getJavaTypeMapping().getClass()) &&
!existingCol.getJavaTypeMapping().getClass().isAssignableFrom(mapping.getClass())) {
// the mapping class must be the same (not really required, but to avoid user mistakes)
throw new DuplicateDatastoreFieldException(this.toString(), existingCol, col);
}
// Make sure the field java types are compatible