|
Lines 28-39
Link Here
|
| 28 |
* 07/28/2009-2.0 mobrien - 284877: implement recursive functionality for hasDeclaredAttribute() |
28 |
* 07/28/2009-2.0 mobrien - 284877: implement recursive functionality for hasDeclaredAttribute() |
| 29 |
* - see design issue #52 |
29 |
* - see design issue #52 |
| 30 |
* http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_52:_20090728:_JPA_2:_Implement_recursive_ManagedType.getDeclared.2A_algorithm_to_differentiate_by_IdentifiableType |
30 |
* http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_52:_20090728:_JPA_2:_Implement_recursive_ManagedType.getDeclared.2A_algorithm_to_differentiate_by_IdentifiableType |
|
|
31 |
* 08/08/2009-2.0 mobrien - 266912: implement Collection and List separation during attribute initialization |
| 32 |
* - see design issue #58 |
| 33 |
* http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_58:_20090807:_ManagedType_Attribute_Initialization_must_differentiate_between_Collection_and_List |
| 31 |
******************************************************************************/ |
34 |
******************************************************************************/ |
| 32 |
package org.eclipse.persistence.internal.jpa.metamodel; |
35 |
package org.eclipse.persistence.internal.jpa.metamodel; |
| 33 |
|
36 |
|
|
|
37 |
import java.lang.reflect.Field; |
| 38 |
import java.lang.reflect.Method; |
| 39 |
import java.util.Collection; |
| 34 |
import java.util.HashMap; |
40 |
import java.util.HashMap; |
| 35 |
import java.util.HashSet; |
41 |
import java.util.HashSet; |
| 36 |
import java.util.Iterator; |
42 |
import java.util.Iterator; |
|
|
43 |
import java.util.List; |
| 37 |
import java.util.Map; |
44 |
import java.util.Map; |
| 38 |
import java.util.Set; |
45 |
import java.util.Set; |
| 39 |
|
46 |
|
|
Lines 49-56
Link Here
|
| 49 |
|
56 |
|
| 50 |
import org.eclipse.persistence.descriptors.RelationalDescriptor; |
57 |
import org.eclipse.persistence.descriptors.RelationalDescriptor; |
| 51 |
import org.eclipse.persistence.indirection.IndirectSet; |
58 |
import org.eclipse.persistence.indirection.IndirectSet; |
|
|
59 |
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor; |
| 60 |
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor; |
| 52 |
import org.eclipse.persistence.internal.helper.ClassConstants; |
61 |
import org.eclipse.persistence.internal.helper.ClassConstants; |
| 53 |
import org.eclipse.persistence.internal.localization.ExceptionLocalization; |
62 |
import org.eclipse.persistence.internal.localization.ExceptionLocalization; |
|
|
63 |
import org.eclipse.persistence.internal.queries.ContainerPolicy; |
| 54 |
import org.eclipse.persistence.mappings.CollectionMapping; |
64 |
import org.eclipse.persistence.mappings.CollectionMapping; |
| 55 |
import org.eclipse.persistence.mappings.DatabaseMapping; |
65 |
import org.eclipse.persistence.mappings.DatabaseMapping; |
| 56 |
|
66 |
|
|
Lines 959-977
Link Here
|
| 959 |
|
969 |
|
| 960 |
/** |
970 |
/** |
| 961 |
* INTERNAL: |
971 |
* INTERNAL: |
| 962 |
* Initialize the members of this ManagedType based on the mappings defined on the descriptor. |
972 |
* Initialise the members of this ManagedType based on the mappings defined on the descriptor. |
| 963 |
* We process the appropriate Map, List, Set, Collection or Object/primitive types.<p> |
973 |
* We process the appropriate Map, List, Set, Collection or Object/primitive types.<p> |
| 964 |
* Initialization should occur after all types in the metamodel have been created already. |
974 |
* Initialisation should occur after all types in the metamodel have been created already. |
| 965 |
* |
975 |
* |
| 966 |
*/ |
976 |
*/ |
| 967 |
protected void initialize() { // TODO: Check all is*Policy() calls |
977 |
protected void initialize() { // TODO: Check all is*Policy() calls |
| 968 |
/* |
978 |
/* |
| 969 |
* Design Issue 37: |
979 |
* Design Issue 37 and 58: |
| 970 |
* http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_37:_20090708:_CollectionAttribute_acts_as_a_peer_of_Map.2C_Set.2C_List_but_should_be_a_super_interface |
980 |
* http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_37:_20090708:_CollectionAttribute_acts_as_a_peer_of_Map.2C_Set.2C_List_but_should_be_a_super_interface |
|
|
981 |
* http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_58:_20090807:_ManagedType_Attribute_Initialization_must_differentiate_between_Collection_and_List |
| 982 |
* |
| 971 |
* The hierarchy of the Metamodel API has Collection alongside List, Set and Map. |
983 |
* The hierarchy of the Metamodel API has Collection alongside List, Set and Map. |
| 972 |
* However, in a normal Java collections framework Collection is an |
984 |
* However, in a normal Java collections framework Collection is an |
| 973 |
* abstract superclass of List, Set and Map (with Map not really a Collection). |
985 |
* abstract superclass of List, Set and Map (with Map not really a Collection). |
| 974 |
* We therefore need to treat Collection here as a peer of the other "collections". |
986 |
* We therefore need to treat Collection here as a peer of the other "collections" while also treating it as a non-instantiated superclass. |
| 975 |
*/ |
987 |
*/ |
| 976 |
this.members = new HashMap<String, Attribute<X, ?>>(); |
988 |
this.members = new HashMap<String, Attribute<X, ?>>(); |
| 977 |
|
989 |
|
|
Lines 984-1004
Link Here
|
| 984 |
if (mapping.isCollectionMapping()) { |
996 |
if (mapping.isCollectionMapping()) { |
| 985 |
// Handle 1:m, n:m collection mappings |
997 |
// Handle 1:m, n:m collection mappings |
| 986 |
CollectionMapping colMapping = (CollectionMapping) mapping; |
998 |
CollectionMapping colMapping = (CollectionMapping) mapping; |
| 987 |
if (colMapping.getContainerPolicy().isMapPolicy()) { |
999 |
ContainerPolicy collectionContainerPolicy = colMapping.getContainerPolicy(); |
|
|
1000 |
if (collectionContainerPolicy.isMapPolicy()) { |
| 988 |
// Handle Map type mappings |
1001 |
// Handle Map type mappings |
| 989 |
member = new MapAttributeImpl(this, colMapping, true); |
1002 |
member = new MapAttributeImpl(this, colMapping, true); |
| 990 |
// check mapping.attributeAcessor.attributeField.type=Collection |
1003 |
// check mapping.attributeAcessor.attributeField.type=Collection |
| 991 |
} else if (colMapping.getContainerPolicy().isListPolicy()) { // TODO: isListPolicy() will return true for IndirectList (a lazy Collection) |
1004 |
} else if (collectionContainerPolicy.isListPolicy()) { |
| 992 |
// Handle List type mappings |
1005 |
/** |
| 993 |
member = new ListAttributeImpl(this, colMapping, true); |
1006 |
* Handle lazy Collections and Lists and the fact that both return an IndirectList policy. |
|
|
1007 |
* We check the type on the attributeField of the attributeAccessor on the mapping |
| 1008 |
*/ |
| 1009 |
Class aType = null; |
| 1010 |
if(colMapping.getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) { |
| 1011 |
Field aField = ((InstanceVariableAttributeAccessor)colMapping.getAttributeAccessor()).getAttributeField(); |
| 1012 |
// MappedSuperclasses need special handling to get their type from an inheriting subclass |
| 1013 |
if(null == aField) { // MappedSuperclass field will not be set |
| 1014 |
if(this.isMappedSuperclass()) { |
| 1015 |
// get inheriting subtype member (without handling @override annotations) |
| 1016 |
MappedSuperclassTypeImpl aMappedSuperclass = ((MappedSuperclassTypeImpl)this); |
| 1017 |
AttributeImpl inheritingTypeMember = aMappedSuperclass.getMemberFromInheritingType(colMapping.getAttributeName()); |
| 1018 |
aField = ((InstanceVariableAttributeAccessor)inheritingTypeMember.getMapping().getAttributeAccessor()).getAttributeField(); |
| 1019 |
if(null == aField) { |
| 1020 |
aType = Collection.class; |
| 1021 |
} else { |
| 1022 |
aType = aField.getType(); |
| 1023 |
} |
| 1024 |
} else { |
| 1025 |
aType = List.class; |
| 1026 |
} |
| 1027 |
} else { |
| 1028 |
aType = aField.getType(); |
| 1029 |
} |
| 1030 |
// This attribute is declared as List |
| 1031 |
if(aType == List.class) { |
| 1032 |
member = new ListAttributeImpl(this, colMapping, true); |
| 1033 |
} else { |
| 1034 |
if(aType == Collection.class) { |
| 1035 |
// This attribute is therefore declared as Collection |
| 1036 |
member = new CollectionAttributeImpl(this, colMapping, true); |
| 1037 |
} else { |
| 1038 |
// TODO: System.out.println("_Warning: type is null on " + colMapping); |
| 1039 |
member = new CollectionAttributeImpl(this, colMapping, true); |
| 1040 |
} |
| 1041 |
} |
| 1042 |
} else { |
| 1043 |
// handle variations of missing get/set methods - only for Collection vs List |
| 1044 |
if(colMapping.getAttributeAccessor() instanceof MethodAttributeAccessor) { |
| 1045 |
aType = ((MethodAttributeAccessor)colMapping.getAttributeAccessor()).getAttributeClass(); |
| 1046 |
if(aType == Collection.class) { |
| 1047 |
member = new CollectionAttributeImpl(this, colMapping, true); |
| 1048 |
} else if(aType == List.class) { |
| 1049 |
member = new ListAttributeImpl(this, colMapping, true); |
| 1050 |
} else { |
| 1051 |
// Type may be null when no getMethod exists for the class such as an embeddable |
| 1052 |
// Here we check the returnType on the declared method on the class directly |
| 1053 |
String getMethodName = ((MethodAttributeAccessor)colMapping.getAttributeAccessor()).getGetMethodName(); |
| 1054 |
if(null == getMethodName) { |
| 1055 |
// default to List |
| 1056 |
member = new ListAttributeImpl(this, colMapping, true); |
| 1057 |
} else { |
| 1058 |
try { |
| 1059 |
Method aMethod = this.getJavaType().getDeclaredMethod(getMethodName); |
| 1060 |
aType = aMethod.getReturnType(); |
| 1061 |
if(aType == Collection.class) { |
| 1062 |
member = new CollectionAttributeImpl(this, colMapping, true); |
| 1063 |
} else if(aType == List.class) { |
| 1064 |
member = new ListAttributeImpl(this, colMapping, true); |
| 1065 |
} else { |
| 1066 |
// default to List |
| 1067 |
// TODO: System.out.println("_Warning: type is null on " + colMapping); |
| 1068 |
member = new ListAttributeImpl(this, colMapping, true); |
| 1069 |
} |
| 1070 |
} catch (Exception e) { |
| 1071 |
// TODO: System.out.println("_Warning: type is null on " + colMapping); |
| 1072 |
// default to List |
| 1073 |
member = new ListAttributeImpl(this, colMapping, true); |
| 1074 |
} |
| 1075 |
} |
| 1076 |
} |
| 1077 |
} |
| 1078 |
} |
| 994 |
} else { |
1079 |
} else { |
| 995 |
// Handle Set type mappings (IndirectSet.isAssignableFrom(Set.class) == false) |
1080 |
// Handle Set type mappings (IndirectSet.isAssignableFrom(Set.class) == false) |
| 996 |
if (colMapping.getContainerPolicy().getContainerClass().isAssignableFrom(Set.class) || |
1081 |
if (collectionContainerPolicy.getContainerClass().isAssignableFrom(Set.class) || |
| 997 |
colMapping.getContainerPolicy().getContainerClass().isAssignableFrom(IndirectSet.class)) { |
1082 |
collectionContainerPolicy.getContainerClass().isAssignableFrom(IndirectSet.class)) { |
| 998 |
member = new SetAttributeImpl(this, colMapping, true); |
1083 |
member = new SetAttributeImpl(this, colMapping, true); |
| 999 |
} else { |
1084 |
} else { |
| 1000 |
// Handle Collection type mappings as a default |
1085 |
// Check for non-lazy Collection policy |
| 1001 |
member = new CollectionAttributeImpl(this, colMapping, true); |
1086 |
if(collectionContainerPolicy.isCollectionPolicy()) { |
|
|
1087 |
member = new CollectionAttributeImpl(this, colMapping, true); |
| 1088 |
} else { |
| 1089 |
// Handle Collection type mappings as a default |
| 1090 |
// TODO: System.out.println("_Warning: defaulting to non-Set specific Collection type on " + colMapping); |
| 1091 |
member = new CollectionAttributeImpl(this, colMapping, true); |
| 1092 |
} |
| 1002 |
} |
1093 |
} |
| 1003 |
} |
1094 |
} |
| 1004 |
} else { |
1095 |
} else { |