}
if (!duplicate)
{
// Create the relation discriminator column since we dont have this discriminator
ColumnMetaData colmd = new ColumnMetaData(null, colName);
colmd.setAllowsNull(Boolean.TRUE); // Allow for elements not in any discriminated collection
fkDiscrimMapping = dba.getMapping(String.class, storeMgr); // Only support String discriminators currently
ColumnCreator.createIndexColumn(fkDiscrimMapping, storeMgr, clr, this, colmd, false);
}
if (fkDiscrimMapping != null)
{
getExternalFkDiscriminatorMappings().put(ownerFmd, fkDiscrimMapping);
}
}
// Add the order mapping as necessary
addOrderMapping(ownerFmd, orderMapping, clr);
}
else
{
// Unidirectional (element knows nothing about the owner)
String ownerClassName = ownerFmd.getAbstractClassMetaData().getFullClassName();
JavaTypeMapping fkMapping = new PersistenceCapableMapping();
fkMapping.initialize(dba, ownerClassName);
JavaTypeMapping fkDiscrimMapping = null;
JavaTypeMapping orderMapping = null;
boolean duplicate = false;
try
{
// Get the owner id mapping of the "1" end
JavaTypeMapping ownerIdMapping = storeMgr.getDatastoreClass(ownerClassName, clr).getIDMapping();
ColumnMetaDataContainer colmdContainer = null;
if (ownerFmd.hasCollection() || ownerFmd.hasArray())
{
// 1-N Collection/array
colmdContainer = ownerFmd.getElementMetaData();
}
else if (ownerFmd.hasMap() && ownerFmd.getKeyMetaData() != null && ownerFmd.getKeyMetaData().getMappedBy() != null)
{
// 1-N Map with key stored in the value
colmdContainer = ownerFmd.getValueMetaData();
}
else if (ownerFmd.hasMap() && ownerFmd.getValueMetaData() != null && ownerFmd.getValueMetaData().getMappedBy() != null)
{
// 1-N Map with value stored in the key
colmdContainer = ownerFmd.getKeyMetaData();
}
CorrespondentColumnsMapper correspondentColumnsMapping =
new CorrespondentColumnsMapper(colmdContainer, ownerIdMapping, true);
int countIdFields = ownerIdMapping.getNumberOfDatastoreFields();
for (int i=0; i<countIdFields; i++)
{
DatastoreMapping refDatastoreMapping = ownerIdMapping.getDataStoreMapping(i);
JavaTypeMapping mapping = dba.getMapping(refDatastoreMapping.getJavaTypeMapping().getJavaType(), storeMgr);
ColumnMetaData colmd = correspondentColumnsMapping.getColumnMetaDataByIdentifier(((Column)refDatastoreMapping.getDatastoreField()).getIdentifier());
if (colmd == null)
{
throw new JPOXUserException(LOCALISER.msg("057035",
((Column)refDatastoreMapping.getDatastoreField()).getIdentifier(), toString())).setFatal();
}
DatastoreIdentifier identifier = null;
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
if (colmd.getName() == null || colmd.getName().length() < 1)
{
// No user provided name so generate one
identifier = ((RDBMSIdentifierFactory)idFactory).newForeignKeyFieldIdentifier(ownerFmd,
null, refDatastoreMapping.getDatastoreField().getIdentifier(),
storeMgr.getOMFContext().getTypeManager().isDefaultEmbeddedType(mapping.getJavaType()),
FieldRole.ROLE_OWNER);
}
else
{
// User-defined name
identifier = idFactory.newDatastoreFieldIdentifier(colmd.getName());
}
DatastoreField refColumn = addDatastoreField(mapping.getJavaType().getName(), identifier, mapping, colmd);
((Column)refDatastoreMapping.getDatastoreField()).copyConfigurationTo(refColumn);
if (colmd == null || (colmd != null && !colmd.isAllowsNullSet()) ||
(colmd != null && colmd.isAllowsNullSet() && colmd.isAllowsNull()))
{
// User either wants it nullable, or havent specified anything, so make it nullable
refColumn.setNullable();
}
fkMapping.addDataStoreMapping(getStoreManager().getMappingManager().createDatastoreMapping(mapping, storeMgr, refColumn, refDatastoreMapping.getJavaTypeMapping().getJavaType().getName()));
((PersistenceCapableMapping)fkMapping).addJavaTypeMapping(mapping);
}
}
catch (DuplicateColumnNameException dcne)
{
// If the user hasnt specified "relation-discriminator-column" here we dont allow the sharing of columns
if (!ownerFmd.hasExtension("relation-discriminator-column"))
{
throw dcne;
}
// Find the FK using this column and use it instead of creating a new one since we're sharing
Iterator fkIter = getExternalFkMappings().entrySet().iterator();
fkMapping = null;
while (fkIter.hasNext())
{
Map.Entry entry = (Map.Entry)fkIter.next();
JavaTypeMapping existingFkMapping = (JavaTypeMapping)entry.getValue();
for (int j=0;j<existingFkMapping.getNumberOfDatastoreFields();j++)
{
if (existingFkMapping.getDataStoreMapping(j).getDatastoreField().getIdentifier().toString().equals(dcne.getConflictingColumn().getIdentifier().toString()))
{
// The FK is shared (and so if it is a List we also share the index)
fkMapping = existingFkMapping;
fkDiscrimMapping = (JavaTypeMapping)externalFkDiscriminatorMappings.get(entry.getKey());
orderMapping = (JavaTypeMapping)getExternalOrderMappings().get(entry.getKey());
break;
}
}
}
if (fkMapping == null)
{
// Should never happen since we know there is a col duplicating ours
throw dcne;
}
duplicate = true;
}
if (!duplicate && ownerFmd.hasExtension("relation-discriminator-column"))
{
// Create the relation discriminator column
String colName = ownerFmd.getValueForExtension("relation-discriminator-column");
if (colName == null)
{
// No column defined so use a fallback name
colName = "RELATION_DISCRIM";
}
ColumnMetaData colmd = new ColumnMetaData(null, colName);
colmd.setAllowsNull(Boolean.TRUE); // Allow for elements not in any discriminated collection
fkDiscrimMapping = dba.getMapping(String.class, storeMgr); // Only support String discriminators currently
ColumnCreator.createIndexColumn(fkDiscrimMapping, storeMgr, clr, this, colmd, false);
}
// Save the external FK