// Set the managedType (X or owning Type) - Note: EmbeddableTypes are only supported as Map keys here
super(managedType, mapping, validationEnabled);
// We need to set the keyType Type that represents the type of the Map key for this mapping
ContainerPolicy policy = mapping.getContainerPolicy();
Class<?> javaClass = null;
MapKeyMapping keyMapping = null;
Object policyKeyType = null;
/**
* Note: the (at) sign for annotations has been replaced by the & sign for javadoc processing.
*
* We have the following policy structure and behavior
* ContainerPolicy (A)
* +=== InterfaceContainerPolicy (A)
* +=== DirectMapContainerPolicy
* +=== MapContainerPolicy (use keyField or PK class)
* +=== MappedKeyMapContainerPolicy (use keyMapping.mapKeyTargetType or attributeClassification)
*
* Use Case segmentation for keyType
A) MapContainerPolicy
A1) keyField set (lazy loaded)
UC2 - name attribute defines mapKey, generics are not required and are secondary
&OneToMany(cascade=ALL, mappedBy="mappedEmployerUC2")
&MapKey(name="name")
private Map<String, HardwareDesigner> hardwareDesignersMapUC2;
UC4 - name attribute defines mapKey, generics are not required
&OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC4")
&MapKey(name="name")
private Map hardwareDesignersMapUC4;
UC8 - mapKey defined via generics
&OneToMany(cascade=ALL, mappedBy="mappedEmployerUC8")
&MapKey // name attribute will default to "id"
private Map<Integer, HardwareDesigner> hardwareDesignersMapUC8;
A2) Use mapPolicy.elementDescriptor.cmppolicy.pkClass (since KeyField == null)
UC10 - mapKey defined via generics and is a java class defined as an IdClass on the element(value) class - here Enclosure
&OneToMany(mappedBy="computer", cascade=ALL, fetch=EAGER)
&MapKey // key defaults to an instance of the composite pk class
private Map<EnclosureIdClassPK, Enclosure> enclosures;
&Entity &IdClass(EnclosureIdClassPK.class) public class Enclosure {}
UC11 - or (get keyClass from mapping if the Id is a get() function)
TBD - use reflection
B) MappedKeyMapContainerPolicy
B1) mapKeyTargetType set on the keyMapping - normal processing
UC9 - mapKey defined by generics in the absence of a MapKey annotation
&OneToMany(cascade=CascadeType.ALL, mappedBy="mappedManufacturerUC9")
private Map<Board, Enclosure> enclosureByBoardMapUC9;
UC13 - mapKey defined by generics in the absence of a MapKey name attribute (unidirectional M:1 becomes M:M)
&MapKey // on Computer inverse
private Map<EmbeddedPK, GalacticPosition> position;
&ManyToOne(fetch=EAGER) // on GalacticPosition owner
private Computer computer;
B2) - secondary processing for Basic (DirectToField) mappings
Use AttributeClassification (since keyMapping.attributeAccessor.attributeClass == null)
UC1a - mapKey defined by generics in the absence of a MapKey annotation
&OneToMany(cascade=ALL, mappedBy="mappedEmployerUC1a")
private Map<String, HardwareDesigner> hardwareDesignersMapUC1a;
UC7 - mapKey defined by generics in the absence of a MapKey annotation
&OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC7")
private Map<String, HardwareDesigner> hardwareDesignersMapUC7;
*/
// Step 1: We check via the ContainerPolicy interface for a mapPolicy for the keyMapping (covers MappedKeyMapContainerPolicy and its superclass MapContainerPolicy
if (policy.isMapPolicy()) {
// check for Either a generic Map (MapContainerPolicy) or specific MappedKeyMapContainerPolicy subclass
if (policy.isMappedKeyMapPolicy()) {
// See UC9
// The cast below is unavoidable because getKeyMapping() is not overridden from the MapContainerPolicy superclass
keyMapping = ((MappedKeyMapContainerPolicy)policy).getKeyMapping();
policyKeyType = keyMapping.getMapKeyTargetType();
} else {
/**
* Assume we have a MapContainerPolicy general superclass with a lazy-loaded keyType
* or a DirectMapContainerPolicy using a &BasicMap
* See UC2, UC4, UC8, UC13 (unidirectional ManyToOne becomes ManyToMany)