initProperties();
Class<?> idClass = getCompositeKeyClass();
Object id = idClass.newInstance();
PropertyDescriptor[] idProperties = PropertyUtils.getPropertyDescriptors(idClass);
if (idProperties == null || idProperties.length == 0)
throw new UnexpectedException("Composite id has no properties: " + idClass.getName());
for (PropertyDescriptor idProperty : idProperties) {
// do we have a field for this?
String idPropertyName = idProperty.getName();
// skip the "class" property...
if (idPropertyName.equals("class"))
continue;
Model.Property modelProperty = this.properties.get(idPropertyName);
if (modelProperty == null)
throw new UnexpectedException("Composite id property missing: " + clazz.getName() + "." + idPropertyName
+ " (defined in IdClass " + idClass.getName() + ")");
// sanity check
Object value = modelProperty.field.get(model);
if (modelProperty.isMultiple)
throw new UnexpectedException("Composite id property cannot be multiple: " + clazz.getName() + "." + idPropertyName);
// now is this property a relation? if yes then we must use its ID in the key (as per specs)
if (modelProperty.isRelation) {
// get its id
if (!Model.class.isAssignableFrom(modelProperty.type))
throw new UnexpectedException("Composite id property entity has to be a subclass of Model: "
+ clazz.getName() + "." + idPropertyName);
// we already checked that cast above
@SuppressWarnings("unchecked")
Model.Factory factory = Model.Manager.factoryFor((Class<? extends Model>) modelProperty.type);
if (factory == null)
throw new UnexpectedException("Failed to find factory for Composite id property entity: "
+ clazz.getName() + "." + idPropertyName);
// we already checked that cast above
if (value != null)
value = factory.keyValue((Model) value);
}