Community
Participate
Working Groups
>The get*Declared* functions in '''ManagedType''' will require a recursive search on their superType inheritance tree to correctly determine whether an attribute is declared on the current '''IdentifiableType''' or not. We need to take into account whether the superType is an Entity or MappedSuperclass - as this will affect whether we continue to search up when a current IdentifiableType is missing the attribute. - If superType is entity then inheriting entities will not have copies of the inherited mappings - however, if superType is mappedSuperclass then all inheriting mappedSuperclasses and the first entity will have copies of the inherited mappings - Note: a sub-entity can override a mapping above it - we need to handle this. >The current implementation of the private helper function does not differentiate between mappedSuperclasses, entities or overrides. private boolean hasDeclaredAttribute(String attributeName)
>Use Cases: UC1 Superclass declares attribute UC1.1: Entity (searched) --> Entity --> Entity (declares attribute) UC1.2: Entity (searched) --> Entity (copy of attribute) --> MappedSuperclass (declares attribute) UC1.3: Entity (searched) --> MappedSuperclass --> Entity (declares attribute) UC1.4: Entity (copy of attribute) (searched) --> MappedSuperclass (copy of attribute) (searched) --> MappedSuperclass (declares attribute) (searched) UC2 Nobody declares attribute UC2.1: Entity (searched) --> Entity --> MappedSuperclass (declares attribute) UC2.2: Entity (searched) --> Entity --> Entity (declares attribute) UC2.3: Entity (searched) --> MappedSuperclass (searched) --> MappedSuperclass (declares attribute) UC2.4: Entity (searched) --> MappedSuperclass (searched) --> Entity (declares attribute) UC3 Superclass declares attribute but child overrides it UC3.1: Entity (searched) --> Entity --> MappedSuperclass (declares attribute) UC3.2: Entity (searched) --> Entity --> Entity (declares attribute) UC3.3: Entity (searched) --> MappedSuperclass (override attribute) (searched) --> MappedSuperclass (declares attribute) UC3.4: Entity (searched) --> MappedSuperclass (override attribute) (searched) --> Entity (declares attribute) (searched) UC3.5: Entity (override attribute) (searched) --> MappedSuperclass (searched) --> MappedSuperclass (declares attribute) (searched) UC3.6: Entity (override attribute) (searched) --> MappedSuperclass (searched) --> Entity (declares attribute) >Solution: Results Expected for hasDeclaredAttribute() True = attribute declared only on current type False = attribute not found in superType tree or attribute found in more than one(1) level of the superType tree Base Case attribute found && no superType exists = true attribute not found && no superType exists = false Recursive Case Exit(false) as soon as attribute is found in a superType - without continuing to the root continue as long as we find an attribute in the superType (essentially only MappedSuperclass parents)
Created attachment 142895 [details] ManagedType.hasDeclaredAttribute() unoptimized recursive changes
>See rev# 4754 http://fisheye2.atlassian.com/changelog/eclipselink/?cs=4754
>this change has been in the build for 2 weeks - resolving
http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI:52_Refactor:_20090817 >DI 52: Refactor: 20090817 The base case for the recursive function managedTypeImpl.hasDeclaredAttribute() does not handle use case 1.4 (root-level managedType) when the caller of the function does not do it's own inheritedType check. This occurs only for managedType.getDeclaredAttributes() - here the returned Set is empty. There are two sets of internal references to hasDeclaredAttribute() - the call getDeclaredAttributes() does not do optimization before calling this recursive function - all the other getDeclaredList()|getDeclaredMap etc - check the immediate hierarchy and only call the recursive hasDeclaredAttribute() if needed. Why are we checking the superType tree recursively in the first place? Because a possible MappedSuperclass hierarchy will not declare their own copies of a parent superclass - only the first inheriting entity will get copies of attributes declared at the top of a MappedSuperclass hierarchy tree. A possible time-space optimization would be to store the java members in a separate data structure from the metamodel members. >The fix is to change the following code ManagedTypeImpl.java:897 private boolean hasDeclaredAttribute(String attributeName, Attribute firstLevelAttribute) { // Base Case: If we are at the root, check for the attribute and return results immediately if(null == aSuperType) { if(null == anAttribute && null != firstLevelAttribute) { return true; } else { // UC 1.3 (part of the else condition (anAttribute != null)) is handled by the return false in null != aSuperTypeAttribute --->expand return false; } } else { >To the expanded version below that handles the case where we are checking the root when the type is declared there. ManagedTypeImpl.java:897 private boolean hasDeclaredAttribute(String attributeName, Attribute firstLevelAttribute) { // Base Case: If we are at the root, check for the attribute and return results immediately if(null == aSuperType) { if(null == anAttribute && null != firstLevelAttribute) { return true; } else { // UC 1.3 (part of the else condition (anAttribute != null)) is handled by the return false in null != aSuperTypeAttribute // UC 1.4 (when caller is firstLevel) superType does not contain the attribute - check that the current attribute and the first differ if(null != anAttribute && anAttribute == firstLevelAttribute) { return true; } else { return false; } } } else { >New testing that fails without this fix (no managedTypes were returned for a person.getDeclaredAttributes() call) Set<Attribute<Person, ?>> declaredAttributesSetForPerson = msPerson.getDeclaredAttributes(); assertNotNull(declaredAttributesSetForPerson); // We should see 3 declared out of 3 attributes for Person assertEquals(3, declaredAttributesSetForPerson.size()); // Id is declared at this level assertTrue(declaredAttributesSetForPerson.contains(msPerson.getAttribute("id"))); // // name is declared at this level assertTrue(declaredAttributesSetForPerson.contains(msPerson.getAttribute("name"))); // // historicalEmployers is declared at this level assertTrue(declaredAttributesSetForPerson.contains(msPerson.getAttribute("historicalEmployers"))); //
Created attachment 144716 [details] DI: 52 refactor: ManagedTypeImpl.hasNoDeclaredAttributeInSuperType refactor >The function is renamed hasNoDeclaredAttributeInSuperType from hasDeclaredAttribute to avoid any developer confusion - since I am really returning the opposite boolean of what my function is named - thank you Chris. >New tests for getDeclaredAttributes() on the root MappedSuperclass added around line 870 of MetamodelMetamodelTest.java
>See line 935 of ManagedTypeImpl for the core change above https://bugs.eclipse.org/bugs/attachment.cgi?id=144716&action=diff#jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metamodel/ManagedTypeImpl.java_sec11 Testing LRG before/after SVN update
>See SVN rev# 4883 http://fisheye2.atlassian.com/changelog/eclipselink/?cs=4883
Mass update to change fixed in target.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink