@SuppressWarnings({ "unchecked" })
public void doSecondPass(Map persistentClasses) throws MappingException {
PersistentClass referencedPersistentClass = (PersistentClass) persistentClasses.get( referencedEntityName );
// TODO better error names
if ( referencedPersistentClass == null ) {
throw new AnnotationException( "Unknown entity name: " + referencedEntityName );
}
if ( ! ( referencedPersistentClass.getIdentifier() instanceof Component ) ) {
throw new AssertionFailure(
"Unexpected identifier type on the referenced entity when mapping a @MapsId: "
+ referencedEntityName
);
}
Component referencedComponent = (Component) referencedPersistentClass.getIdentifier();
Iterator<Property> properties = referencedComponent.getPropertyIterator();
//prepare column name structure
boolean isExplicitReference = true;
Map<String, Ejb3JoinColumn> columnByReferencedName = new HashMap<String, Ejb3JoinColumn>(joinColumns.length);
for (Ejb3JoinColumn joinColumn : joinColumns) {
final String referencedColumnName = joinColumn.getReferencedColumn();
if ( referencedColumnName == null || BinderHelper.isEmptyAnnotationValue( referencedColumnName ) ) {
break;
}
//JPA 2 requires referencedColumnNames to be case insensitive
columnByReferencedName.put( referencedColumnName.toLowerCase(), joinColumn );
}
//try default column orientation
int index = 0;
if ( columnByReferencedName.isEmpty() ) {
isExplicitReference = false;
for (Ejb3JoinColumn joinColumn : joinColumns) {
columnByReferencedName.put( "" + index, joinColumn );
index++;
}
index = 0;
}
while ( properties.hasNext() ) {
Property referencedProperty = properties.next();
if ( referencedProperty.isComposite() ) {
throw new AssertionFailure( "Unexpected nested component on the referenced entity when mapping a @MapsId: "
+ referencedEntityName);
}
else {
Property property = new Property();
property.setName( referencedProperty.getName() );
property.setNodeName( referencedProperty.getNodeName() );
//FIXME set optional?
//property.setOptional( property.isOptional() );
property.setPersistentClass( component.getOwner() );
property.setPropertyAccessorName( referencedProperty.getPropertyAccessorName() );
SimpleValue value = new SimpleValue( mappings, component.getTable() );
property.setValue( value );
final SimpleValue referencedValue = (SimpleValue) referencedProperty.getValue();
value.setTypeName( referencedValue.getTypeName() );
value.setTypeParameters( referencedValue.getTypeParameters() );
final Iterator<Selectable> columns = referencedValue.getColumnIterator();
if ( joinColumns[0].isNameDeferred() ) {
joinColumns[0].copyReferencedStructureAndCreateDefaultJoinColumns(
referencedPersistentClass,
columns,
value);
}
else {
//FIXME take care of Formula
while ( columns.hasNext() ) {
final Selectable selectable = columns.next();
if ( ! Column.class.isInstance( selectable ) ) {
log.debug( "Encountered formula definition; skipping" );
continue;
}
final Column column = (Column) selectable;
final Ejb3JoinColumn joinColumn;
String logicalColumnName = null;
if ( isExplicitReference ) {
final String columnName = column.getName();
logicalColumnName = mappings.getLogicalColumnName( columnName, referencedPersistentClass.getTable() );
//JPA 2 requires referencedColumnNames to be case insensitive
joinColumn = columnByReferencedName.get( logicalColumnName.toLowerCase() );
}
else {
joinColumn = columnByReferencedName.get( "" + index );
index++;
}
if ( joinColumn == null && ! joinColumns[0].isNameDeferred() ) {
throw new AnnotationException(
isExplicitReference ?
"Unable to find column reference in the @MapsId mapping: " + logicalColumnName :
"Implicit column reference in the @MapsId mapping fails, try to use explicit referenceColumnNames: " + referencedEntityName
);
}