From 03d9e24bc6a10c3bea737678606d74f7c6fb86fc Mon Sep 17 00:00:00 2001 From: Michael Dick Date: Tue, 30 Jun 2009 01:05:16 +0000 Subject: [PATCH] OPENJPA-1061 merging patch provided by Jody Grassel to trunk modified: openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java modified: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@789519 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/openjpa/enhance/PCEnhancer.java | 66 ++++++++++------ .../apache/openjpa/meta/ClassMetaData.java | 76 +++++++++++++++++++ 2 files changed, 119 insertions(+), 23 deletions(-) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java index bea542d33..a1c9a90c8 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java @@ -153,12 +153,12 @@ public class PCEnhancer { try { auxEnhancers.add(AccessController.doPrivileged( J2DoPrivHelper.newInstanceAction(classes[i]))); - } catch (Throwable t) { + } catch (Throwable t) { // aux enhancer may rely on non-existant spec classes, etc - } - } - _auxEnhancers = (AuxiliaryEnhancer[]) auxEnhancers.toArray - (new AuxiliaryEnhancer[auxEnhancers.size()]); + } + } + _auxEnhancers = (AuxiliaryEnhancer[]) auxEnhancers.toArray + (new AuxiliaryEnhancer[auxEnhancers.size()]); } private BCClass _pc; @@ -1138,9 +1138,15 @@ public class PCEnhancer { addCopyKeyFieldsToObjectIdMethod(false); addCopyKeyFieldsFromObjectIdMethod(true); addCopyKeyFieldsFromObjectIdMethod(false); + if (_meta.hasAbstractPKField() == true) { + addGetIDOwningClass(); + } addNewObjectIdInstanceMethod(true); addNewObjectIdInstanceMethod(false); } + else if (_meta.hasPKFieldsFromAbstractClass()){ + addGetIDOwningClass(); + } } /** @@ -2536,12 +2542,13 @@ public class PCEnhancer { // new ObjectId (cls, oid) code.anew().setType(ObjectId.class); code.dup(); - if(_meta.isEmbeddedOnly()) { + if(_meta.isEmbeddedOnly() || _meta.hasAbstractPKField() == true) { code.aload().setThis(); - code.invokevirtual().setMethod(Object.class, "getClass", - Class.class, null); - }else + code.invokevirtual().setMethod(PRE + "GetIDOwningClass", + Class.class, null); + } else { code.classconstant().setClass(getType(_meta)); + } } // new (); @@ -2549,12 +2556,13 @@ public class PCEnhancer { code.dup(); if (_meta.isOpenJPAIdentity() || (obj && usesClsString == Boolean.TRUE)) { - if(_meta.isEmbeddedOnly()) { + if(_meta.isEmbeddedOnly() || _meta.hasAbstractPKField() == true ) { code.aload().setThis(); - code.invokevirtual().setMethod(Object.class, "getClass", - Class.class, null); - }else + code.invokevirtual().setMethod(PRE + "GetIDOwningClass", + Class.class, null); + }else { code.classconstant().setClass(getType(_meta)); + } } if (obj) { code.aload().setParam(0); @@ -4613,15 +4621,27 @@ public class PCEnhancer { public File directory = null; public boolean addDefaultConstructor = true; public boolean tmpClassLoader = true; - public boolean enforcePropertyRestrictions = false; - } + public boolean enforcePropertyRestrictions = false; + } - /** - * Plugin interface for additional enhancement. - */ - public static interface AuxiliaryEnhancer - { - public void run (BCClass bc, ClassMetaData meta); - public boolean skipEnhance(BCMethod m); - } + /** + * Plugin interface for additional enhancement. + */ + public static interface AuxiliaryEnhancer + { + public void run (BCClass bc, ClassMetaData meta); + public boolean skipEnhance(BCMethod m); + } + + private void addGetIDOwningClass() throws NoSuchMethodException { + BCMethod method = _pc.declareMethod(PRE + "GetIDOwningClass", + Class.class, null); + Code code = method.getCode(true); + + code.classconstant().setClass(getType(_meta)); + code.areturn(); + + code.calculateMaxStack(); + code.calculateMaxLocals(); + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java index f1e46abcf..28ecd7181 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java @@ -208,6 +208,8 @@ public class ClassMetaData private boolean _intercepting = false; private Boolean _useIdClassFromParent = null; private boolean _abstract = false; + private Boolean _hasAbstractPKField = null; + private Boolean _hasPKFieldsFromAbstractClass = null; /** * Constructor. Supply described type and repository. @@ -2593,4 +2595,78 @@ public class ClassMetaData } return rval; } + + /** + * Convenience method to determine if the pcType modeled by + * this ClassMetaData object is both abstract and declares PKFields. This + * method is used by the PCEnhancer to determine if special handling is + * required. + * + * @return + */ + public boolean hasAbstractPKField() { + if (_hasAbstractPKField != null) { + return _hasAbstractPKField.booleanValue(); + } + + // Default to false, set to true only if this type is abstract and + // declares a PKField. + _hasAbstractPKField = Boolean.FALSE; + + if (isAbstract() == true) { + FieldMetaData[] declaredFields = getDeclaredFields(); + if (declaredFields != null && declaredFields.length != 0) { + for (FieldMetaData fmd : declaredFields) { + if (fmd.isPrimaryKey()) { + _hasAbstractPKField = Boolean.TRUE; + break; + } + } + } + } + + return _hasAbstractPKField.booleanValue(); + } + + /** + * Convenience method to determine if this type is a direct + * decendent of an abstract type declaring PKFields. Returns true if there + * are no pcTypes mapped to a table between this type and an abstract pcType + * declaring PKFields. Returns false if there no such abstract pcTypes in + * the inheritance hierarchy or if there are any pcTypes mapped to tables in + * between the type represented by this ClassMetaData object and the + * abstract pcType declaring PKFields. + * + * @return + */ + public boolean hasPKFieldsFromAbstractClass() { + if (_hasPKFieldsFromAbstractClass != null) { + return _hasPKFieldsFromAbstractClass.booleanValue(); + } + + // Default to FALSE, until proven true. + _hasPKFieldsFromAbstractClass = Boolean.FALSE; + + FieldMetaData[] pkFields = getPrimaryKeyFields(); + for (FieldMetaData fmd : pkFields) { + ClassMetaData fmdDMDA = fmd.getDeclaringMetaData(); + if (fmdDMDA.isAbstract()) { + ClassMetaData cmd = getPCSuperclassMetaData(); + while (cmd != fmdDMDA) { + if (fmdDMDA.isAbstract()) { + cmd = cmd.getPCSuperclassMetaData(); + } else { + break; + } + } + if (cmd == fmdDMDA) { + _hasPKFieldsFromAbstractClass = Boolean.TRUE; + break; + } + } + } + + return _hasPKFieldsFromAbstractClass.booleanValue(); + } + }