openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ppod...@apache.org
Subject svn commit: r769478 [1/2] - in /openjpa/trunk: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ openjpa-persistence/src/main/java/org/apache/openjpa/persistenc...
Date Tue, 28 Apr 2009 17:50:26 GMT
Author: ppoddar
Date: Tue Apr 28 17:50:25 2009
New Revision: 769478

URL: http://svn.apache.org/viewvc?rev=769478&view=rev
Log:
OPENJPA-1008: Facade OpenJPA metamodel to JPA 2.0 

Added:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java   (with props)
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetadataProcessor.java   (with props)
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetamodelImpl.java   (with props)
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java   (with props)
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Types.java   (with props)
Modified:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java?rev=769478&r1=769477&r2=769478&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java Tue Apr 28 17:50:25 2009
@@ -46,6 +46,7 @@
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.persistence.JPAFacadeHelper;
 import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
 
 /**
  * Base test class providing persistence utilities.
@@ -527,12 +528,13 @@
         }
         
         public int hashCode() {
-            return unit.hashCode() + config.hashCode();
+            return (unit != null ? unit.hashCode() : 0) + config.hashCode();
         }
         
         public boolean equals(Object other) {
             EMFKey that = (EMFKey)other;
-            return unit.equals(that.unit) && config.equals(that.config);
+            return (unit != null ? unit.equals(that.unit) : that.unit == null) 
+                && config.equals(that.config);
         }
     }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?rev=769478&r1=769477&r2=769478&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Tue Apr 28 17:50:25 2009
@@ -46,6 +46,8 @@
 import org.apache.openjpa.lib.conf.Value;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.lib.util.Closeable;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.persistence.meta.MetamodelImpl;
 import org.apache.openjpa.persistence.query.OpenJPAQueryBuilder;
 import org.apache.openjpa.persistence.query.QueryBuilderImpl;
 import org.apache.openjpa.util.OpenJPAException;
@@ -69,7 +71,8 @@
     private transient Constructor<FetchPlan> _plan = null;
     private transient StoreCache _cache = null;
     private transient QueryResultCache _queryCache = null;
-
+    private transient MetamodelImpl _metaModel;
+    
     /**
      * Default constructor provided for auto-instantiation.
      */
@@ -354,8 +357,7 @@
     }
 
     public QueryBuilder getQueryBuilder() {
-        throw new UnsupportedOperationException(
-        "JPA 2.0 - Method not yet implemented");
+        throw new UnsupportedOperationException();
     }
     
     public OpenJPAQueryBuilder getDynamicQueryBuilder() {
@@ -366,8 +368,11 @@
         return _factory.getSupportedProperties();
     }
 
-    public Metamodel getMetamodel() {
-        throw new UnsupportedOperationException(
-        "JPA 2.0 - Method not yet implemented");
+    public MetamodelImpl getMetamodel() {
+        if (_metaModel == null) {
+            _metaModel = new MetamodelImpl(getConfiguration()
+                .getMetaDataRepositoryInstance());
+        }
+        return _metaModel;
     }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java?rev=769478&r1=769477&r2=769478&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java Tue Apr 28 17:50:25 2009
@@ -5,14 +5,9 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.Generated;
@@ -23,52 +18,37 @@
 import javax.annotation.processing.SupportedAnnotationTypes;
 import javax.annotation.processing.SupportedOptions;
 import javax.annotation.processing.SupportedSourceVersion;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
-import javax.persistence.Access;
-import javax.persistence.AccessType;
-import javax.persistence.Transient;
 import javax.persistence.metamodel.TypesafeMetamodel;
 import javax.tools.Diagnostic;
 import javax.tools.JavaFileObject;
 
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.persistence.util.SourceCode;
-import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.UserException;
 
 /**
- * Annotation processing tool to generate/instantiate a meta-model given the
- * annotated source code of persistent domain model.
+ * Annotation processing tool generates souce code for a meta-model class given 
+ * the annotated source code of persistent entity.
  * <p>
- * This tool is invoked as part of compilation phase for JDK6 compiler provided
- * OpenJPA and JPA class libraries are specified in the compiler 
- * <code>-processorpath</code> option. <br>
- * For example<br>
- * <code>$ javac -processorpath path/to/openjpa.jar;/path/to/jpa.jar 
- * src/mypackage/MyClass.java</code>
- * <br> 
- * will generate source code for canonical meta-model for 
- * <code>mypackage.MyClass</code> (if it is annotated with persistence 
- * annotation <code>Entity or Embedded or MappedSuperclass</code>) to produce a 
- * file <code>mypackage/MyClass_.java</code>.
+ * This tool is invoked during compilation for JDK6 compiler if OpenJPA and JPA 
+ * libraries are specified in the compiler <code>-processorpath</code> option.
+ * <br>
+ * For example,<br>
+ * <center><code>$ javac -processorpath path/to/openjpa;/path/to/jpa 
+ * -s src -Alog mypackage/MyClass.java</code></center>
+ * <p> 
+ * will generate source code for canonical meta-model class  at
+ * <code>src/mypackage/MyClass_.java</code>.
  * <p>
  * The generated source code is written relative to the source path root which
  * is, by default, the current directory or as specified by -s option to 
  * <code>javac</code> compiler. 
+ * <p>
+ * Currently the only recognized option is <code>-Alog</code> specified as shown
+ * in the <code>javac</code> command above.
  * 
  * @author Pinaki Poddar
  * 
@@ -83,31 +63,11 @@
 @SupportedSourceVersion(RELEASE_6)
 
 public class AnnotationProcessor6 extends AbstractProcessor {
-    private static final String UNDERSCORE = "_";
+    private SourceAnnotationHandler handler;
 
-
-    /**
-     * Set of Inclusion Filters based on member type, access type or transient
-     * annotations. Used to determine the subset of available field/method that 
-     * are persistent.   
-     */
-    static AccessFilter propertyAccessFilter =
-        new AccessFilter(AccessType.PROPERTY);
-    static AccessFilter fieldAccessFilter = 
-        new AccessFilter(AccessType.FIELD);
-    
-    static KindFilter fieldFilter = new KindFilter(ElementKind.FIELD);
-    static KindFilter methodFilter = new KindFilter(ElementKind.METHOD);
-    
-    static GetterFilter getterFilter = new GetterFilter();
-    static SetterFilter setterFilter = new SetterFilter();
-    
-    static NonTransientMemberFilter nonTransientFilter = 
-    	new NonTransientMemberFilter();
-    static AnnotatedMemberFilter annotatedFilter = new AnnotatedMemberFilter();
-    
     private static Localizer _loc =
         Localizer.forPackage(AnnotationProcessor6.class);
+    private static final String UNDERSCORE = "_";
 
     /**
      * Category of members as per JPA 2.0 type system.
@@ -129,7 +89,6 @@
         public String getMetaModelType() {
             return type;
         }
-        
     }
     
     /**
@@ -184,6 +143,7 @@
         super.init(processingEnv);
         processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, 
             _loc.get("mmg-tool-banner").getMessage());
+        handler = new SourceAnnotationHandler(processingEnv);
     }
     
     /**
@@ -207,7 +167,7 @@
      * @return true if code is generated for the given element. false otherwise.
      */
     private boolean process(TypeElement e) {
-        if (!isAnnotatedAsEntity(e)) {
+    	if (!handler.isAnnotatedAsEntity(e)) {
             return false;
         }
 
@@ -219,18 +179,18 @@
         SourceCode source = new SourceCode(metaClass);
         comment(source);
         annotate(source, originalClass);
-        TypeElement supCls = getPCSuperclass(e);
+        TypeElement supCls = handler.getPersistentSupertype(e);
         if (supCls != null)
             source.getTopLevelClass().setSuper(supCls.toString() + UNDERSCORE);
         try {
             PrintWriter writer = createSourceFile(metaClass, e);
             SourceCode.Class modelClass = source.getTopLevelClass();
-            List<? extends Element> members = getPersistentMembers(e);
+            Set<? extends Element> members = handler.getPersistentMembers(e);
             
             for (Element m : members) {
-                TypeMirror decl = getDeclaredType(m);
-                String fieldName = getPersistentMemberName(m);
-                String fieldType = getDeclaredTypeName(decl, true);
+                TypeMirror decl = handler.getDeclaredType(m);
+                String fieldName = handler.getPersistentMemberName(m);
+                String fieldType = handler.getDeclaredTypeName(decl);
                 TypeCategory typeCategory = toMetaModelTypeCategory(fieldType);
                 String metaModelType = typeCategory.getMetaModelType();
                 SourceCode.Field modelField = null;
@@ -243,17 +203,17 @@
                 case COLLECTION:
                 case LIST:
                 case SET:
-                    TypeMirror param = getTypeParameter(decl, 0);
-                    String elementType = getDeclaredTypeName(param, true);
+                    TypeMirror param = handler.getTypeParameter(decl, 0);
+                    String elementType = handler.getDeclaredTypeName(param);
                     modelField = modelClass.addField(fieldName, metaModelType);
                     modelField.addParameter(originalSimpleClass)
                               .addParameter(elementType);
                     break;
                 case MAP:
-                    TypeMirror key = getTypeParameter(decl, 0);
-                    TypeMirror value = getTypeParameter(decl, 1);
-                    String keyType = getDeclaredTypeName(key, true);
-                    String valueType = getDeclaredTypeName(value, true);
+                    TypeMirror key = handler.getTypeParameter(decl, 0);
+                    TypeMirror value = handler.getTypeParameter(decl, 1);
+                    String keyType = handler.getDeclaredTypeName(key);
+                    String valueType = handler.getDeclaredTypeName(value);
                     modelField = modelClass.addField(fieldName, metaModelType);
                     modelField.addParameter(originalSimpleClass)
                               .addParameter(keyType)
@@ -295,602 +255,10 @@
         PrintWriter writer = new PrintWriter(out);
         return writer;
     }
-    
-    /**
-     * Get  access type of the given class, if specified explicitly. 
-     * null otherwise.
-     * 
-     * @param type
-     * @return FIELD or PROPERTY 
-     */
-    AccessType getExplicitAccessType(TypeElement type) {
-        Object access = getAnnotationValue(type, Access.class);
-        if (equalsByValue(AccessType.FIELD, access))
-            return AccessType.FIELD;
-        if (equalsByValue(AccessType.PROPERTY, access))
-            return AccessType.PROPERTY;
-        return null;
-    }
-    
-    String getPersistentMemberName(Element e) {
-    	return isMethod(e) ? extractFieldName((ExecutableElement)e) 
-    			: e.getSimpleName().toString();
-    }
-    
-    String extractFieldName(ExecutableElement method) {
-    	String name = method.getSimpleName().toString();
-		String head = isNormalGetter(method) ? "get" : "is";
-		name = name.substring(head.length());
-        return Character.toLowerCase(name.charAt(0)) + name.substring(1);
-    }
-    
-    /**
-     * Gets the list of persistent fields and/or methods for the given type.
-     * 
-     * Scans relevant @AccessType annotation and field/method as per JPA
-     * specification to determine the candidate set of field/methods.
-     */
-    private List<Element> getPersistentMembers(TypeElement type) {
-        AccessType access = getExplicitAccessType(type);
-        boolean isExplicit = access != null;
-        
-        return isExplicit ? access == AccessType.FIELD 
-        		? getFieldAccessPersistentMembers(type) 
-        		: getPropertyAccessPersistentMembers(type)
-        		: getDefaultAccessPersistentMembers(type);
-    }
-    
-    /**
-     * Collect members for the given type which uses explicit field access.
-     */
-    private List<Element> getFieldAccessPersistentMembers(TypeElement type) {   
-        List<? extends Element> allMembers = type.getEnclosedElements();       
-        Set<VariableElement> allFields = (Set<VariableElement>) 
-           filter(allMembers, fieldFilter, nonTransientFilter);
-        Set<ExecutableElement> allMethods = (Set<ExecutableElement>) 
-            filter(allMembers, methodFilter, nonTransientFilter);
-        Set<ExecutableElement> getters = filter(allMethods, getterFilter, 
-        		propertyAccessFilter, annotatedFilter);
-        Set<ExecutableElement> setters = filter(allMethods, setterFilter);
-        getters = matchGetterAndSetter(getters, setters);
-        
-        return merge(getters, allFields);
-    }
-    
-    /**
-     * Collect members for the given type which uses explicit field access.
-     */
-     private List<Element> getPropertyAccessPersistentMembers(TypeElement type)
-     {
-        List<? extends Element> allMembers = type.getEnclosedElements();
-        Set<ExecutableElement> allMethods = (Set<ExecutableElement>) 
-            filter(allMembers, methodFilter, nonTransientFilter);
-
-        Set<ExecutableElement> getters = filter(allMethods, getterFilter);
-        Set<ExecutableElement> setters = filter(allMethods, setterFilter);
-        getters = matchGetterAndSetter(getters, setters);
-        
-        return merge(filter(allMembers, fieldFilter, nonTransientFilter, 
-        	fieldAccessFilter), getters);
-    }
-
-    
-    private List<Element> getDefaultAccessPersistentMembers(TypeElement type) {
-        List<Element> result = new ArrayList<Element>();
-        List<? extends Element> allMembers = type.getEnclosedElements();
-        Set<VariableElement> allFields = (Set<VariableElement>) 
-           filter(allMembers, fieldFilter, nonTransientFilter);
-        Set<ExecutableElement> allMethods = (Set<ExecutableElement>) 
-          filter(allMembers, methodFilter, nonTransientFilter);
-
-        Set<VariableElement> annotatedFields = filter(allFields, 
-        	annotatedFilter);
-        Set<ExecutableElement> getters = filter(allMethods, getterFilter, 
-        	annotatedFilter);
-        Set<ExecutableElement> setters = filter(allMethods, setterFilter);
-        getters = matchGetterAndSetter(getters, setters);
-        
-        boolean isFieldAccess = !annotatedFields.isEmpty();
-        boolean isPropertyAccess = !getters.isEmpty();
-
-        if (isFieldAccess && isPropertyAccess) {
-            throw new UserException(_loc.get("access-mixed", type,
-                    toString(annotatedFields), toString(getters)));
-    	}    
-        if (isFieldAccess) {
-            result.addAll(annotatedFields);
-        } else if (isPropertyAccess) {
-            result.addAll(getters);
-        } else {
-            warn(_loc.get("access-none", type).toString());
-        }
-        return result;
-    }
-    
-    List<Element> merge(Set<? extends Element> a, Set<? extends Element> b) {
-    	List<Element> result = new ArrayList<Element>();
-    	result.addAll(a);
-    	for (Element e1 : b) {
-    		boolean hide = false;
-    		String key = getPersistentMemberName(e1);
-    		for (Element e2 : a) {
-    			if (getPersistentMemberName(e2).equals(key)) {
-    				hide = true;
-    				break;
-    			}
-    		}
-    		if (!hide) {
-    			result.add(e1);
-    		}
-    	}
-    	return result;
-    }
-
-
-    // =========================================================================
-    // Annotation processing utilities
-    // =========================================================================
-    
-    /**
-     * Affirms if the given element is annotated with <em>any</em> 
-     * <code>javax.persistence.*</code> or <code>org.apache.openjpa.*</code>
-     * annotation.
-     */
-    private static boolean isAnnotated(Element e) {
-    	return isAnnotatedWith(e, (Set<String>)null);
-    }
-    
-    /**
-     * Affirms if the given declaration has the given annotation.
-     */
-    private static boolean isAnnotatedWith(Element e,
-        Class<? extends Annotation> anno) {
-        return e != null && e.getAnnotation(anno) != null;
-    }
-    
-    /**
-     * Affirms if the given element is annotated with any of the given 
-     * annotations.
-     * 
-     * @param annos null checks for any annotation that starts with 
-     *            'javax.persistence.' or 'openjpa.*'.
-     * 
-     */
-    private static boolean isAnnotatedWith(Element e, Set<String> annos) {
-        if (e == null)
-            return false;
-        List<? extends AnnotationMirror> mirrors = e.getAnnotationMirrors();
-        if (annos == null) {
-            for (AnnotationMirror mirror : mirrors) {
-                String name = mirror.getAnnotationType().toString();
-                if (startsWith(name, "javax.persistence.")
-                 || startsWith(name, "openjpa."))
-                    return true;
-            }
-            return false;
-        } else {
-            for (AnnotationMirror mirror : mirrors) {
-                String name = mirror.getAnnotationType().toString();
-                if (annos.contains(name))
-                    return true;
-            }
-            return false;
-        }
-    }
-    
-    /**
-     * Affirms if the given list contains one of the registered annotation that
-     * designates an entity type.
-     */
-    private boolean isAnnotatedAsEntity(TypeElement e) {
-        return isAnnotatedWith(e, getSupportedAnnotationTypes());
-    }
-    
-     /**
-     * Get the element name of the class the given mirror represents. If the
-     * mirror is primitive then returns the corresponding boxed class name.
-     * If the mirror is parameterized returns only the generic type i.e.
-     * if the given declared type is 
-     * <code>java.util.Set&lt;java.lang.String&gt;</code> this method will 
-     * return <code>java.util.Set</code>.
-     */
-    private String getDeclaredTypeName(TypeMirror mirror, boolean box) {
-    	if (mirror.getKind() == TypeKind.ARRAY) {
-    		TypeMirror comp = ((ArrayType)mirror).getComponentType();
-    		return getDeclaredTypeName(comp, false)+"[]";
-    	}
-    	mirror = box? box(mirror) : mirror;
-    	if (isPrimitive(mirror))
-    		return ((PrimitiveType)mirror).toString();
-        return processingEnv.getTypeUtils().asElement(mirror).toString();
-    }
-
-    /**
-     * Gets the declared type of the given member. For fields, returns the 
-     * declared type while for method returns the return type. 
-     * 
-     * @param e a field or method.
-     * @exception if given member is neither a field nor a method.
-     */
-    private TypeMirror getDeclaredType(Element e) {
-        TypeMirror result = null;
-        switch (e.getKind()) {
-        case FIELD:
-            result = e.asType();
-            break;
-        case METHOD:
-            result = ((ExecutableElement) e).getReturnType();
-            break;
-        default:
-            throw new IllegalArgumentException(toDetails(e));
-        }
-        return result;
-    }
-    
-    /**
-     * Affirms if the given type mirrors a primitive.
-     */
-    private boolean isPrimitive(TypeMirror mirror) {
-        TypeKind kind = mirror.getKind();
-        return kind == TypeKind.BOOLEAN 
-            || kind == TypeKind.BYTE
-            || kind == TypeKind.CHAR
-            || kind == TypeKind.DOUBLE
-            || kind == TypeKind.FLOAT
-            || kind == TypeKind.INT
-            || kind == TypeKind.LONG
-            || kind == TypeKind.SHORT;
-    }
-    
-    TypeMirror box(TypeMirror t) {
-        if (isPrimitive(t))
-            return processingEnv.getTypeUtils()
-            .boxedClass((PrimitiveType)t).asType();
-        return t;
-    }
-
-    /**
-     * Gets the parameter type argument at the given index of the given type.
-     * 
-     * @return if the given type represents a parameterized type, then the
-     *         indexed parameter type argument. Otherwise null.
-     */
-    private TypeMirror getTypeParameter(TypeMirror mirror, int index) {
-    	if (mirror.getKind() != TypeKind.DECLARED)
-    		return null;
-        List<? extends TypeMirror> params = ((DeclaredType)mirror)
-        	.getTypeArguments();
-        return (params == null || params.size() < index+1) 
-            ? null : params.get(index);
-    }
-
-    /**
-     * Gets the nearest super class of the given class which is persistent.
-     * 
-     * @return null if no such super class exists.
-     */
-    private TypeElement getPCSuperclass(TypeElement cls) {
-        TypeMirror sup = cls.getSuperclass();
-        if (sup == null || isRootObject(sup))
-            return null;
-        TypeElement supe =
-            (TypeElement) processingEnv.getTypeUtils().asElement(sup);
-        if (isAnnotatedAsEntity(supe)) 
-            return supe;
-        return getPCSuperclass(supe);
-    }
-
-
-    /**
-     * Gets the value of the given annotation, if present, in the given
-     * declaration. Otherwise, null.
-     */
-    private static Object getAnnotationValue(Element decl,
-        Class<? extends Annotation> anno) {
-        return getAnnotationValue(decl, anno, "value");
-    }
-
-    /**
-     * Gets the value of the given attribute of the given annotation, if
-     * present, in the given declaration. Otherwise, null.
-     */
-    private static Object getAnnotationValue(Element e,
-        Class<? extends Annotation> anno, String attr) {
-        if (e == null || e.getAnnotation(anno) == null)
-            return null;
-        List<? extends AnnotationMirror> annos = e.getAnnotationMirrors();
-        for (AnnotationMirror mirror : annos) {
-            if (mirror.getAnnotationType().toString().equals(anno.getName())) {
-                Map<? extends ExecutableElement, ? extends AnnotationValue> 
-                values = mirror.getElementValues();
-                for (ExecutableElement ex : values.keySet()) {
-                    if (ex.getSimpleName().toString().equals(attr))
-                        return values.get(ex).getValue();
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Matches the given getters with the given setters. Removes the getters
-     * that do not have a corresponding setter.
-     */
-    private Set<ExecutableElement> matchGetterAndSetter(
-        Set<ExecutableElement> getters,  Set<ExecutableElement> setters) {
-        Collection<ExecutableElement> unmatched =
-            new ArrayList<ExecutableElement>();
-        Types typeUtils = processingEnv.getTypeUtils();
-        
-        for (ExecutableElement getter : getters) {
-            String getterName = getter.getSimpleName().toString();
-            TypeMirror getterReturnType = getter.getReturnType();
-            String expectedSetterName = "set" + getterName.substring(
-                (isBooleanGetter(getter) ? "is" : "get").length());
-            boolean matched = false;
-            for (ExecutableElement setter : setters) {
-                TypeMirror setterArgType = setter.getParameters()
-                                     .iterator().next().asType();
-                String actualSetterName = setter.getSimpleName().toString();
-                matched = actualSetterName.equals(expectedSetterName)
-                    && typeUtils.isSameType(setterArgType, getterReturnType);
-                if (matched)
-                    break;
-            }
-            if (!matched) {
-                warn(_loc.get("getter-unmatched", getter, 
-                    getter.getEnclosingElement()).toString());
-                unmatched.add(getter);
-            }
-
-        }
-        getters.removeAll(unmatched);
-        return getters;
-    }
-
-    // ========================================================================
-    //  Selection Filters select specific elements from a collection.
-    // ========================================================================
-    
-    /**
-     * Inclusive element filtering predicate.
-     *
-     */
-    private static interface InclusiveFilter<T extends Element> {
-        /**
-         * Return true to include the given element.
-         */
-        boolean includes(T e);
-    }
-
-    /**
-     * Filter the given collection with the conjunction of filters. The given
-     * collection itself is not modified.
-     */
-    private <T extends Element> Set<T> filter(Collection<T> coll, 
-        InclusiveFilter... filters) {
-        Set<T> result = new HashSet<T>();
-        for (T e : coll) {
-            boolean include = true;
-            for (InclusiveFilter f : filters) {
-                if (!f.includes(e)) {
-                    include = false;
-                    break;
-                }
-            }
-            if (include)
-                result.add(e);
-        }
-        return result;
-    }
-
-    /**
-     * Selects getter method. A getter method name starts with 'get', returns a
-     * non-void type and has no argument. Or starts with 'is', returns a boolean
-     * and has no argument.
-     * 
-     */
-    static class GetterFilter implements InclusiveFilter<ExecutableElement> {
-        public boolean includes(ExecutableElement method) {
-            return isGetter(method);
-        }
-    }
-
-    /**
-     * Selects setter method. A setter method name starts with 'set', returns a
-     * void and has single argument.
-     * 
-     */
-    static class SetterFilter implements InclusiveFilter<ExecutableElement> {
-        public boolean includes(ExecutableElement method) {
-            return isSetter(method);
-        }
-    }
-
-    /**
-     * Selects elements which is annotated with @Access annotation and that 
-     * annotation has the given AccessType value.
-     * 
-     */
-    static class AccessFilter implements InclusiveFilter<Element> {
-        final AccessType target;
-
-        public AccessFilter(AccessType target) {
-            this.target = target;
-        }
-
-        public boolean includes(Element obj) {
-            Object value = getAnnotationValue(obj, Access.class);
-            return equalsByValue(target, value);
-        }
-    }
-
-    /**
-     * Selects elements of given kind.
-     * 
-     */
-    static class KindFilter implements InclusiveFilter<Element> {
-        final ElementKind target;
-
-        public KindFilter(ElementKind target) {
-            this.target = target;
-        }
-
-        public boolean includes(Element obj) {
-            return obj.getKind() == target;
-        }
-    }
-
-    /**
-     * Selects all non-transient element.
-     */
-    static class NonTransientMemberFilter implements InclusiveFilter<Element> {
-        public boolean includes(Element obj) {
-            boolean isTransient = isAnnotatedWith(obj, Transient.class)
-                            || obj.getModifiers().contains(Modifier.TRANSIENT);
-            return !isTransient;
-        }
-    }
-    
-    /**
-     * Selects all annotated element.
-     */
-    static class AnnotatedMemberFilter implements InclusiveFilter<Element> {
-        public boolean includes(Element obj) {
-            return isAnnotated(obj);
-        }
-    }
-
-    
-    
-    // ========================================================================
-    //  Utilities
-    // ========================================================================
-
-    /**
-     * Affirms if the given mirror represents a primitive or non-primitive
-     * boolean.
-     */
-    private static boolean isBoolean(TypeMirror type) {
-        return (type != null && (type.getKind() == TypeKind.BOOLEAN 
-            || "java.lang.Boolean".equals(type.toString())));
-    }
-
-    /**
-     * Affirms if the given mirror represents a void.
-     */
-    private static boolean isVoid(TypeMirror type) {
-        return (type != null && type.getKind() == TypeKind.VOID);
-    }
-
-    /**
-     * Affirms if the given element represents a method.
-     */
-    private static boolean isMethod(Element e) {
-        return e != null && ExecutableElement.class.isInstance(e)
-            && e.getKind() == ElementKind.METHOD;
-    }
-    
-    /**
-     * Affirms if the given method matches the following signature
-     * <code> public T getXXX() </code>
-     * where T is any non-void type.
-     */
-    private static boolean isNormalGetter(ExecutableElement method) {
-    	String methodName = method.getSimpleName().toString();
-    	return method.getKind() == ElementKind.METHOD
-    	    && startsWith(methodName, "get") 
-    	    && method.getParameters().isEmpty()
-    	    && !isVoid(method.getReturnType());
-    }
-    
-    /**
-     * Affirms if the given method matches the following signature
-     * <code> public boolean isXXX() </code>
-     * <code> public Boolean isXXX() </code>
-     */
-    private static boolean isBooleanGetter(ExecutableElement method) {
-    	String methodName = method.getSimpleName().toString();
-    	return method.getKind() == ElementKind.METHOD
-    	    && startsWith(methodName, "is") 
-    	    && method.getParameters().isEmpty()
-    	    && isBoolean(method.getReturnType());
-    }
-
-    private static boolean isGetter(ExecutableElement method) {
-    	return isNormalGetter(method) || isBooleanGetter(method);
-    }
-    
-    /**
-     * Affirms if the given method matches the following signature
-     * <code> public void setXXX(T t) </code>
-     */
-    private static boolean isSetter(ExecutableElement method) {
-    	String methodName = method.getSimpleName().toString();
-    	return method.getKind() == ElementKind.METHOD
-    	    && startsWith(methodName, "set") 
-    	    && method.getParameters().size() == 1
-    	    && isVoid(method.getReturnType());
-    }
-    
-    /**
-     * Affirms if the given mirror represents root java.lang.Object.
-     */
-    private static boolean isRootObject(TypeMirror type) {
-        return type != null && "java.lang.Object".equals(type.toString());
-    }
-    
-    /**
-     * Affirms if the given full string starts with the given head.
-     */
-    private static boolean startsWith(String full, String head) {
-        return full != null && full.startsWith(head) 
-            && full.length() > head.length();
-    }
-
-    /**
-     * Affirms if the given enum equals the given value.
-     */
-    private static boolean equalsByValue(Enum<?> e, Object v) {
-        if (v == null)
-            return false;
-        return e.toString().equals(v.toString());
-    }
-    
-    // =========================================================================
-    // Access rules
-    // =========================================================================
-    
-    
-    // =========================================================================
-    // Logging
-    // =========================================================================
 
     private void log(String msg) {
         if (!processingEnv.getOptions().containsKey("log"))
             return;
         processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
     }
-
-    private void warn(String msg) {
-        processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg);
-    }
-    
-    private static String toString(Collection<? extends Element> elements) {
-        StringBuilder tmp = new StringBuilder();
-        int i = 0;
-        for (Element e : elements) {
-            tmp.append(e.getSimpleName() + (++i == elements.size() ? "" : ","));
-        }
-        return tmp.toString();
-    }
-    
-    String toDetails(Element e) {
-        TypeMirror mirror = e.asType();
-        return new StringBuffer(e.getKind().toString()).append(" ")
-                           .append(e.toString())
-                           .append("Mirror ")
-                           .append(mirror.getKind().toString())
-                           .append(mirror.toString()).toString();
-    }
 }

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java?rev=769478&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java Tue Apr 28 17:50:25 2009
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.openjpa.persistence.meta;
+
+import javax.persistence.metamodel.AbstractCollection;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.Type;
+
+import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.JavaTypes;
+
+/**
+ * Member according to JPA 2.0 metamodel.
+ * 
+ * Implemented as a thin adapter to OpenJPA FieldMetadata.
+ * Mostly immutable.
+ * 
+ * @author Pinaki Poddar
+ * 
+ * @since 2.0.0
+ *
+ */
+public class Members {
+	/**
+	 * Root of implementation hierarchy.
+	 *
+	 * @param <X> the class that owns this member
+	 * @param <Y> the class of the value held by this member
+	 */
+    public static abstract class Member<X, Y> 
+       implements javax.persistence.metamodel.Member<X, Y> {
+
+        public final Types.Managed<X> owner;
+        public final FieldMetaData fmd;
+
+        protected Member(Types.Managed<X> owner, FieldMetaData fmd) {
+            this.owner = owner;
+            this.fmd = fmd;
+        }
+
+        public final ManagedType<X> getDeclaringType() {
+            return owner.model.type((Class<X>) fmd.getDeclaringType());
+        }
+
+        public final java.lang.reflect.Member getJavaMember() {
+            return fmd.getBackingMember();
+        }
+
+        public final Class<Y> getMemberJavaType() {
+            return (Class<Y>) fmd.getDeclaredType();
+        }
+
+        public final String getName() {
+            return fmd.getName();
+        }
+
+        public final boolean isAssociation() {
+            return fmd.isDeclaredTypePC();
+        }
+
+        public final boolean isCollection() {
+            return fmd.getDeclaredTypeCode() == JavaTypes.COLLECTION
+                || fmd.getDeclaredTypeCode() == JavaTypes.MAP;
+        }
+
+        public String toString() {
+            return fmd.getName();
+        }
+    }
+
+    /**
+     * Attributes are non-collection members.
+     *
+	 * @param <X> the class that owns this member
+	 * @param <T> the class of the value held by this member
+     */
+    public static final class Attribute<X, T> extends Member<X, T> implements
+        javax.persistence.metamodel.Attribute<X, T> {
+
+        public Attribute(Types.Managed<X> owner, FieldMetaData fmd) {
+            super(owner, fmd);
+        }
+
+        public Multiplicity getMultiplicity() {
+            throw new AbstractMethodError();
+        }
+
+        public boolean isId() {
+            return fmd.isPrimaryKey();
+        }
+
+        public boolean isVersion() {
+            return fmd.isVersion();
+        }
+
+        public boolean isOptional() {
+            return fmd.getNullValue() != FieldMetaData.NULL_EXCEPTION;
+        }
+
+        public Type<T> getAttributeType() {
+            return owner.model.type(fmd.getDeclaredType());
+        }
+
+        public BindableType getBindableType() {
+            return fmd.isDeclaredTypePC() ? BindableType.MANAGED_TYPE
+                : BindableType.ATTRIBUTE;
+        }
+
+        public Class<T> getJavaType() {
+            return super.getMemberJavaType();
+        }
+    }
+
+    /**
+     * Root of collection members.
+     *
+	 * @param <X> the class that owns this member
+	 * @param <C> the container class that holds this member 
+	 *            (e.g. java.util.Set)
+     * @param <E> the class of the element held by this member 
+     */
+    public static abstract class BaseCollection<X, C, E> extends Member<X, C>
+        implements AbstractCollection<X, C, E> {
+
+        public BaseCollection(Types.Managed<X> owner, FieldMetaData fmd) {
+            super(owner, fmd);
+        }
+
+        public final Type<E> getElementType() {
+            return owner.model.getType(fmd.getElement().getDeclaredType());
+        }
+
+        public final BindableType getBindableType() {
+            return BindableType.COLLECTION;
+        }
+
+        public final Class<E> getJavaType() {
+            return fmd.getElement().getDeclaredType();
+        }
+    }
+
+    /**
+     * Members declared as java.util.Collection<E>.
+     */
+    public static class Collection<X, E> extends
+        BaseCollection<X, java.util.Collection<E>, E> implements
+        javax.persistence.metamodel.Collection<X, E> {
+
+        public Collection(Types.Managed<X> owner, FieldMetaData fmd) {
+            super(owner, fmd);
+        }
+
+        public Multiplicity getMultiplicity() {
+            return Multiplicity.ONE_TO_MANY;
+        }
+
+        public CollectionType getCollectionType() {
+            return CollectionType.COLLECTION;
+        }
+    }
+
+    /**
+     * Members declared as java.util.List<E>.
+     */
+    public static class List<X, E> extends
+        BaseCollection<X, java.util.List<E>, E> implements
+        javax.persistence.metamodel.List<X, E> {
+
+        public List(Types.Managed<X> owner, FieldMetaData fmd) {
+            super(owner, fmd);
+        }
+
+        public Multiplicity getMultiplicity() {
+            return Multiplicity.ONE_TO_MANY;
+        }
+
+        public CollectionType getCollectionType() {
+            return CollectionType.LIST;
+        }
+    }
+
+    /**
+     * Members declared as java.util.Set<E>.
+     */
+    public static class Set<X, E> extends
+        BaseCollection<X, java.util.Set<E>, E> implements
+        javax.persistence.metamodel.Set<X, E> {
+
+        public Set(Types.Managed<X> owner, FieldMetaData fmd) {
+            super(owner, fmd);
+        }
+
+        public Multiplicity getMultiplicity() {
+            return Multiplicity.ONE_TO_MANY;
+        }
+
+        public CollectionType getCollectionType() {
+            return CollectionType.SET;
+        }
+    }
+
+    /**
+     * Members declared as java.util.Map<K,V>.
+     */
+    public static class Map<X, K, V> extends
+        BaseCollection<X, java.util.Map<K, V>, V> implements
+        javax.persistence.metamodel.Map<X, K, V> {
+
+        public Map(Types.Managed<X> owner, FieldMetaData fmd) {
+            super(owner, fmd);
+        }
+
+        public CollectionType getCollectionType() {
+            return CollectionType.MAP;
+        }
+
+        public Multiplicity getMultiplicity() {
+            return Multiplicity.MANY_TO_MANY;
+        }
+
+        public Class<K> getKeyJavaType() {
+            return (Class<K>) fmd.getKey().getDeclaredType();
+        }
+
+        public Type<K> getKeyType() {
+            return owner.model.getType(getKeyJavaType());
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/Members.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetadataProcessor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetadataProcessor.java?rev=769478&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetadataProcessor.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetadataProcessor.java Tue Apr 28 17:50:25 2009
@@ -0,0 +1,65 @@
+package org.apache.openjpa.persistence.meta;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Collection of generic utility functions for extracting persistence related
+ * metadata from user specified metadata available in various source 
+ * environment.  
+ * <br>
+ * Persistence metadata needs to be acquired from different sources such as
+ * annotated source code, compiled class files, XML descriptors or combinations
+ * thereof under different invocation and configuration context. 
+ * <br> 
+ * Specific implementation of this interface is distinguished by the nature of 
+ * the source and the representation available for type system in the source.
+ *  
+ * @param T the M2 representation of type based on the nature of the source 
+ * e.g. {@linkplain TypeElement} for annotation processing of *.java files or 
+ * {@link Class} for compiled bytecode. 
+ * 
+ * @param M the corresponding M2 representation for member of type T
+ *
+ * @author Pinaki Poddar
+ * 
+ * @since 2.0.0
+ */
+public interface MetadataProcessor<T,M> {
+	/**
+	 * Determine the access type of the given type. 
+	 * 
+	 * @return an integer denoting the type of access. The integer value 
+	 * corresponds to {@linkplain ClassMetaData#getAccessType()}.
+	 */
+	public int determineTypeAccess(T t);
+	
+	/**
+	 * Determine the access type of the given member. 
+	 * 
+	 * @return an integer denoting the type of access. The integer value 
+	 * corresponds to {@linkplain FieldMetaData#getAccessType()}.
+	 */
+	public int determineMemberAccess(M m);
+	
+	/**
+	 * Get the persistent members of the given type.
+	 * 
+	 */
+	public Set<M> getPersistentMembers(T t);
+	
+	/**
+	 * Gets the violations, if any.
+	 * 
+	 * @return null or empty list if no exceptions.
+	 */
+	public List<Exception> validateAccess(T t);
+	
+	/**
+     * Affirms if the members of given type are using both field and property
+	 * based access. 
+	 */
+	public boolean isMixedAccess(T t);
+	
+	public T getPersistentSupertype(T t);
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetadataProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetamodelImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetamodelImpl.java?rev=769478&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetamodelImpl.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetamodelImpl.java Tue Apr 28 17:50:25 2009
@@ -0,0 +1,200 @@
+package org.apache.openjpa.persistence.meta;
+
+import static javax.persistence.metamodel.Type.PersistenceType.BASIC;
+import static javax.persistence.metamodel.Type.PersistenceType.EMBEDDABLE;
+import static javax.persistence.metamodel.Type.PersistenceType.ENTITY;
+import static 
+ javax.persistence.metamodel.Type.PersistenceType.MAPPED_SUPERCLASS;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.metamodel.Embeddable;
+import javax.persistence.metamodel.Entity;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.MappedSuperclass;
+import javax.persistence.metamodel.Metamodel;
+import javax.persistence.metamodel.Type;
+import javax.persistence.metamodel.AbstractCollection.CollectionType;
+import javax.persistence.metamodel.Type.PersistenceType;
+
+import org.apache.openjpa.lib.util.J2DoPrivHelper;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.util.InternalException;
+
+/**
+ * Adapts JPA Metamodel to OpenJPA meta-data repository.
+ * 
+ * @author Pinaki Poddar
+ * 
+ */
+public class MetamodelImpl implements Metamodel {
+    public final MetaDataRepository repos;
+    Map<Class<?>, Entity<?>> _entities = new HashMap<Class<?>, Entity<?>>();
+    Map<Class<?>, Embeddable<?>> _embeddables =
+        new HashMap<Class<?>, Embeddable<?>>();
+    Map<Class<?>, MappedSuperclass<?>> _mappedsupers =
+        new HashMap<Class<?>, MappedSuperclass<?>>();
+    Map<Class<?>, Type<?>> _basics = new HashMap<Class<?>, Type<?>>();
+
+    private static Localizer _loc = Localizer.forPackage(MetamodelImpl.class);
+
+    public MetamodelImpl(MetaDataRepository repos) {
+        this.repos = repos;
+        ClassMetaData[] metas = repos.getMetaDatas();
+        for (ClassMetaData meta : metas) {
+            PersistenceType type = getPersistenceType(meta);
+            Class<?> cls = meta.getDescribedType();
+            switch (type) {
+            case ENTITY:
+                find(cls, _entities, ENTITY);
+                break;
+            case EMBEDDABLE:
+                find(cls, _embeddables, EMBEDDABLE);
+                break;
+            case MAPPED_SUPERCLASS:
+                find(cls, _mappedsupers, MAPPED_SUPERCLASS);
+                break;
+            default:
+            }
+        }
+    }
+
+    public <X> Embeddable<X> embeddable(Class<X> clazz) {
+        return (Embeddable<X>)find(clazz, _embeddables, EMBEDDABLE);
+    }
+
+    public <X> Entity<X> entity(Class<X> clazz) {
+        return (Entity<X>) find(clazz, _entities, ENTITY);
+    }
+
+    public Set<Embeddable<?>> getEmbeddables() {
+        return unmodifiableSet(_embeddables.values());
+    }
+
+    public Set<Entity<?>> getEntities() {
+        return unmodifiableSet(_entities.values());
+    }
+
+    public Set<ManagedType<?>> getManagedTypes() {
+        Set<ManagedType<?>> result = new HashSet<ManagedType<?>>();
+        result.addAll(_entities.values());
+        result.addAll(_embeddables.values());
+        result.addAll(_mappedsupers.values());
+        return result;
+    }
+
+    public <X> ManagedType<X> type(Class<X> clazz) {
+        if (_entities.containsKey(clazz))
+            return (Entity<X>) _entities.get(clazz);
+        if (_embeddables.containsKey(clazz))
+            return (Embeddable<X>) _embeddables.get(clazz);
+        if (_mappedsupers.containsKey(clazz))
+            return (MappedSuperclass<X>) _mappedsupers.get(clazz);
+        throw new IllegalArgumentException(_loc.get("type-not-managed", clazz)
+            .getMessage());
+    }
+
+    public <X> Type<X> getType(Class<X> cls) {
+        try {
+            return type(cls);
+        } catch (IllegalArgumentException ex) {
+            if (_basics.containsKey(cls))
+                return (Type<X>)_basics.get(cls);
+            Type<X> basic = new Types.Basic<X>(cls);
+            _basics.put(cls, basic);
+            return basic;
+        }
+    }
+
+    public static PersistenceType getPersistenceType(ClassMetaData meta) {
+        if (meta == null)
+            return BASIC;
+        if (meta.isEmbeddedOnly())
+            return meta.isAbstract() ? MAPPED_SUPERCLASS : EMBEDDABLE;
+        return ENTITY;
+    }
+
+    private <V extends ManagedType<?>> V find(Class<?> cls, 
+        Map<Class<?>,V> container,  PersistenceType expected) {
+        if (container.containsKey(cls))
+            return container.get(cls);
+        ClassMetaData meta = repos.getMetaData(cls, null, false);
+        if (meta != null) {
+            instantiate(cls, container, expected);
+        }
+        return container.get(cls);
+    }
+
+    private <X,V extends ManagedType<?>> void instantiate(Class<X> cls, 
+        Map<Class<?>,V> container, PersistenceType expected) {
+        ClassMetaData meta = repos.getMetaData(cls, null, true);
+        PersistenceType actual = getPersistenceType(meta);
+        if (actual != expected)
+            throw new IllegalArgumentException(_loc.get("type-wrong-category",
+                cls, actual, expected).getMessage());
+
+        switch (actual) {
+        case EMBEDDABLE:
+            Types.Embeddable<X> embedded = new Types.Embeddable<X>(meta, this);
+            _embeddables.put(cls, embedded);
+            populate(embedded);
+            break;
+        case ENTITY:
+        	Types.Entity<X> entity = new Types.Entity<X>(meta, this);
+            _entities.put(cls, entity);
+            populate(entity);
+            break;
+        case MAPPED_SUPERCLASS:
+            Types.MappedSuper<X> mapped = new Types.MappedSuper<X>(meta, this);
+            _mappedsupers.put(cls, mapped);
+            populate(mapped);
+            break;
+        default:
+            throw new InternalException(cls.getName());
+        }
+    }
+
+    public <T> Set<T> unmodifiableSet(Collection<T> coll) {
+        HashSet<T> result = new HashSet<T>();
+        for (T t : coll)
+            result.add(t);
+        return result;
+    }
+
+    public static CollectionType getCollectionType(Class<?> cls) {
+        if (Set.class.isAssignableFrom(cls))
+            return CollectionType.SET;
+        if (List.class.isAssignableFrom(cls))
+            return CollectionType.LIST;
+        if (Collection.class.isAssignableFrom(cls))
+            return CollectionType.COLLECTION;
+        if (Map.class.isAssignableFrom(cls))
+            return CollectionType.MAP;
+        return null;
+    }
+    
+    /**
+     * Populate the static fields of the canonical type.
+     */
+    public <X> void populate(Types.Managed<X> type) {
+    	try {
+    		Class<X> cls = type.getJavaType();
+            Class<?> mcls = J2DoPrivHelper.getForNameAction(cls.getName()+"_", 
+	    	    true, cls.getClassLoader()).run();
+	    	Field[] fields = mcls.getFields();
+	    	for (Field f : fields) {
+	    		f.set(null, type.getMember(f.getName()));
+	    	}
+    	} catch (Exception e) {
+    		
+    	}
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/MetamodelImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java?rev=769478&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java Tue Apr 28 17:50:25 2009
@@ -0,0 +1,701 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.meta;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+import javax.persistence.Access;
+import javax.persistence.AccessType;
+import static javax.persistence.AccessType.*;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
+import javax.tools.Diagnostic;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * Extracts persistent metadata information by analyzing available annotation
+ * in *.java source files. Requires JDK6 Annotation Processing environment
+ * available.
+ *   
+ * @author Pinaki Poddar
+ * @since 2.0.0
+ */
+public class SourceAnnotationHandler 
+    implements MetadataProcessor<TypeElement, Element> {
+	
+	private final ProcessingEnvironment processingEnv;
+	
+	/**
+     * Set of Inclusion Filters based on member type, access type or transient
+     * annotations. Used to determine the subset of available field/method that 
+     * are persistent.   
+     */
+    protected AccessFilter propertyAccessFilter = new AccessFilter(PROPERTY);
+    protected AccessFilter fieldAccessFilter = new AccessFilter(FIELD);
+
+    protected KindFilter fieldFilter  = new KindFilter(ElementKind.FIELD);
+    protected KindFilter methodFilter = new KindFilter(ElementKind.METHOD);
+    protected TransientFilter nonTransientFilter = new TransientFilter();
+    protected AnnotatedFilter annotatedFilter = new AnnotatedFilter();
+    protected GetterFilter getterFilter = new GetterFilter();
+    protected SetterFilter setterFilter = new SetterFilter();
+    
+    private static Localizer _loc = Localizer.forPackage(
+    		SourceAnnotationHandler.class);
+    
+	/**
+	 * Construct with JDK6 annotation processing environment.
+	 * 
+	 */
+    public SourceAnnotationHandler(ProcessingEnvironment processingEnv) {
+		super();
+		this.processingEnv = processingEnv;
+	}
+
+	@Override
+	public int determineTypeAccess(TypeElement t) {
+		return 0;
+	}
+
+	@Override
+	public int determineMemberAccess(Element m) {
+		return 0;
+	}
+
+	@Override
+	public List<Exception> validateAccess(TypeElement t) {
+		return null;
+	}
+	
+	public boolean isMixedAccess(TypeElement t) {
+		return false;
+	}
+    /**
+     * Gets the list of persistent fields and/or methods for the given type.
+     * 
+     * Scans relevant @AccessType annotation and field/method as per JPA
+     * specification to determine the candidate set of field/methods.
+     */
+	@Override
+    public Set<Element> getPersistentMembers(TypeElement type) {
+        AccessType access = getExplicitAccessType(type);
+        boolean isExplicit = access != null;
+        
+        return isExplicit ? access == AccessType.FIELD 
+        		? getFieldAccessPersistentMembers(type) 
+        		: getPropertyAccessPersistentMembers(type)
+        		: getDefaultAccessPersistentMembers(type);
+    }
+    
+    /**
+     * Collect members for the given type which uses explicit field access.
+     */
+    private Set<Element> getFieldAccessPersistentMembers(TypeElement type) {   
+        List<? extends Element> allMembers = type.getEnclosedElements();       
+        Set<VariableElement> allFields = (Set<VariableElement>) 
+           filter(allMembers, fieldFilter, nonTransientFilter);
+        Set<ExecutableElement> allMethods = (Set<ExecutableElement>) 
+            filter(allMembers, methodFilter, nonTransientFilter);
+        Set<ExecutableElement> getters = filter(allMethods, getterFilter, 
+        		propertyAccessFilter, annotatedFilter);
+        Set<ExecutableElement> setters = filter(allMethods, setterFilter);
+        getters = matchGetterAndSetter(getters, setters);
+        
+        return merge(getters, allFields);
+    }
+    
+    /**
+     * Collect members for the given type which uses explicit field access.
+     */
+     private Set<Element> getPropertyAccessPersistentMembers(TypeElement type)
+     {
+        List<? extends Element> allMembers = type.getEnclosedElements();
+        Set<ExecutableElement> allMethods = (Set<ExecutableElement>) 
+            filter(allMembers, methodFilter, nonTransientFilter);
+
+        Set<ExecutableElement> getters = filter(allMethods, getterFilter);
+        Set<ExecutableElement> setters = filter(allMethods, setterFilter);
+        getters = matchGetterAndSetter(getters, setters);
+        
+        return merge(filter(allMembers, fieldFilter, nonTransientFilter, 
+        	fieldAccessFilter), getters);
+    }
+
+    
+    private Set<Element> getDefaultAccessPersistentMembers(TypeElement type) {
+        Set<Element> result = new HashSet<Element>();
+        List<? extends Element> allMembers = type.getEnclosedElements();
+        Set<VariableElement> allFields = (Set<VariableElement>) 
+           filter(allMembers, fieldFilter, nonTransientFilter);
+        Set<ExecutableElement> allMethods = (Set<ExecutableElement>) 
+          filter(allMembers, methodFilter, nonTransientFilter);
+
+        Set<VariableElement> annotatedFields = filter(allFields, 
+        	annotatedFilter);
+        Set<ExecutableElement> getters = filter(allMethods, getterFilter, 
+        	annotatedFilter);
+        Set<ExecutableElement> setters = filter(allMethods, setterFilter);
+        getters = matchGetterAndSetter(getters, setters);
+        
+        boolean isFieldAccess = !annotatedFields.isEmpty();
+        boolean isPropertyAccess = !getters.isEmpty();
+
+        if (isFieldAccess && isPropertyAccess) {
+            throw new UserException(_loc.get("access-mixed", type,
+                    toString(annotatedFields), toString(getters)));
+    	}    
+        if (isFieldAccess) {
+            result.addAll(annotatedFields);
+        } else if (isPropertyAccess) {
+            result.addAll(getters);
+        } else {
+            warn(_loc.get("access-none", type).toString());
+        }
+        return result;
+    }
+    
+    Set<Element> merge(Set<? extends Element> a, Set<? extends Element> b) {
+    	Set<Element> result = new HashSet<Element>();
+    	result.addAll(a);
+    	for (Element e1 : b) {
+    		boolean hide = false;
+    		String key = getPersistentMemberName(e1);
+    		for (Element e2 : a) {
+    			if (getPersistentMemberName(e2).equals(key)) {
+    				hide = true;
+    				break;
+    			}
+    		}
+    		if (!hide) {
+    			result.add(e1);
+    		}
+    	}
+    	return result;
+    }
+
+    /**
+     * Matches the given getters with the given setters. Removes the getters
+     * that do not have a corresponding setter.
+     */
+    private Set<ExecutableElement> matchGetterAndSetter(
+        Set<ExecutableElement> getters,  Set<ExecutableElement> setters) {
+        Collection<ExecutableElement> unmatched =
+            new ArrayList<ExecutableElement>();
+        Types typeUtils = processingEnv.getTypeUtils();
+        
+        for (ExecutableElement getter : getters) {
+            String getterName = getter.getSimpleName().toString();
+            TypeMirror getterReturnType = getter.getReturnType();
+            String expectedSetterName = "set" + getterName.substring(
+                (isBooleanGetter(getter) ? "is" : "get").length());
+            boolean matched = false;
+            for (ExecutableElement setter : setters) {
+                TypeMirror setterArgType = setter.getParameters()
+                                     .iterator().next().asType();
+                String actualSetterName = setter.getSimpleName().toString();
+                matched = actualSetterName.equals(expectedSetterName)
+                    && typeUtils.isSameType(setterArgType, getterReturnType);
+                if (matched)
+                    break;
+            }
+            if (!matched) {
+                warn(_loc.get("getter-unmatched", getter, 
+                    getter.getEnclosingElement()).toString());
+                unmatched.add(getter);
+            }
+
+        }
+        getters.removeAll(unmatched);
+        return getters;
+    }
+
+    // ========================================================================
+    //  Selection Filters select specific elements from a collection.
+    // ========================================================================
+    
+    /**
+     * Inclusive element filtering predicate.
+     *
+     */
+    private static interface InclusiveFilter<T extends Element> {
+        /**
+         * Return true to include the given element.
+         */
+        boolean includes(T e);
+    }
+
+    /**
+     * Filter the given collection with the conjunction of filters. The given
+     * collection itself is not modified.
+     */
+    <T extends Element> Set<T> filter(Collection<T> coll, 
+        InclusiveFilter... filters) {
+        Set<T> result = new HashSet<T>();
+        for (T e : coll) {
+            boolean include = true;
+            for (InclusiveFilter f : filters) {
+                if (!f.includes(e)) {
+                    include = false;
+                    break;
+                }
+            }
+            if (include)
+                result.add(e);
+        }
+        return result;
+    }
+
+    /**
+     * Selects getter method. A getter method name starts with 'get', returns a
+     * non-void type and has no argument. Or starts with 'is', returns a boolean
+     * and has no argument.
+     * 
+     */
+    static class GetterFilter implements InclusiveFilter<ExecutableElement> {
+        public boolean includes(ExecutableElement method) {
+            return isGetter(method);
+        }
+    }
+
+    /**
+     * Selects setter method. A setter method name starts with 'set', returns a
+     * void and has single argument.
+     * 
+     */
+    static class SetterFilter implements InclusiveFilter<ExecutableElement> {
+        public boolean includes(ExecutableElement method) {
+            return isSetter(method);
+        }
+    }
+
+    /**
+     * Selects elements which is annotated with @Access annotation and that 
+     * annotation has the given AccessType value.
+     * 
+     */
+    static class AccessFilter implements InclusiveFilter<Element> {
+        final AccessType target;
+
+        public AccessFilter(AccessType target) {
+            this.target = target;
+        }
+
+        public boolean includes(Element obj) {
+            Object value = getAnnotationValue(obj, Access.class);
+            return equalsByValue(target, value);
+        }
+    }
+
+    /**
+     * Selects elements of given kind.
+     * 
+     */
+    static class KindFilter implements InclusiveFilter<Element> {
+        final ElementKind target;
+
+        public KindFilter(ElementKind target) {
+            this.target = target;
+        }
+
+        public boolean includes(Element obj) {
+            return obj.getKind() == target;
+        }
+    }
+
+    /**
+     * Selects all non-transient element.
+     */
+    static class TransientFilter implements InclusiveFilter<Element> {
+        public boolean includes(Element obj) {
+            boolean isTransient = isAnnotatedWith(obj, Transient.class)
+                            || obj.getModifiers().contains(Modifier.TRANSIENT);
+            return !isTransient;
+        }
+    }
+    
+    /**
+     * Selects all annotated element.
+     */
+    static class AnnotatedFilter implements InclusiveFilter<Element> {
+        public boolean includes(Element obj) {
+            return isAnnotated(obj);
+        }
+    }
+
+    /**
+     * Get  access type of the given class, if specified explicitly. 
+     * null otherwise.
+     * 
+     * @param type
+     * @return FIELD or PROPERTY 
+     */
+    AccessType getExplicitAccessType(TypeElement type) {
+        Object access = getAnnotationValue(type, Access.class);
+        if (equalsByValue(AccessType.FIELD, access))
+            return AccessType.FIELD;
+        if (equalsByValue(AccessType.PROPERTY, access))
+            return AccessType.PROPERTY;
+        return null;
+    }
+    
+    /**
+     * Gets the value of the given annotation, if present, in the given
+     * declaration. Otherwise, null.
+     */
+    public static Object getAnnotationValue(Element decl,
+        Class<? extends Annotation> anno) {
+        return getAnnotationValue(decl, anno, "value");
+    }
+
+    /**
+     * Gets the value of the given attribute of the given annotation, if
+     * present, in the given declaration. Otherwise, null.
+     */
+    public static Object getAnnotationValue(Element e,
+        Class<? extends Annotation> anno, String attr) {
+        if (e == null || e.getAnnotation(anno) == null)
+            return null;
+        List<? extends AnnotationMirror> annos = e.getAnnotationMirrors();
+        for (AnnotationMirror mirror : annos) {
+            if (mirror.getAnnotationType().toString().equals(anno.getName())) {
+                Map<? extends ExecutableElement, ? extends AnnotationValue> 
+                values = mirror.getElementValues();
+                for (ExecutableElement ex : values.keySet()) {
+                    if (ex.getSimpleName().toString().equals(attr))
+                        return values.get(ex).getValue();
+                }
+            }
+        }
+        return null;
+    }
+
+    public static String toString(Collection<? extends Element> elements) {
+        StringBuilder tmp = new StringBuilder();
+        int i = 0;
+        for (Element e : elements) {
+            tmp.append(e.getSimpleName() + (++i == elements.size() ? "" : ","));
+        }
+        return tmp.toString();
+    }
+    
+    String toDetails(Element e) {
+        TypeMirror mirror = e.asType();
+        return new StringBuffer(e.getKind().toString()).append(" ")
+                           .append(e.toString())
+                           .append("Mirror ")
+                           .append(mirror.getKind().toString())
+                           .append(mirror.toString()).toString();
+    }
+
+    private void log(String msg) {
+        if (!processingEnv.getOptions().containsKey("log"))
+            return;
+        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
+    }
+
+    private void warn(String msg) {
+        processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg);
+    }
+
+    String getPersistentMemberName(Element e) {
+    	return isMethod(e) ? extractFieldName((ExecutableElement)e) 
+    			: e.getSimpleName().toString();
+    }
+    
+    public String extractFieldName(ExecutableElement method) {
+    	String name = method.getSimpleName().toString();
+		String head = isNormalGetter(method) ? "get" : "is";
+		name = name.substring(head.length());
+        return Character.toLowerCase(name.charAt(0)) + name.substring(1);
+    }
+    
+
+    // =========================================================================
+    // Annotation processing utilities
+    // =========================================================================
+    
+    /**
+     * Affirms if the given element is annotated with <em>any</em> 
+     * <code>javax.persistence.*</code> or <code>org.apache.openjpa.*</code>
+     * annotation.
+     */
+    public static boolean isAnnotated(Element e) {
+    	return isAnnotatedWith(e, (Set<String>)null);
+    }
+    
+    /**
+     * Affirms if the given declaration has the given annotation.
+     */
+    boolean isAnnotatedAsEntity(Element e) {
+        return isAnnotatedWith(e, Entity.class)
+            || isAnnotatedWith(e, Embeddable.class)
+            || isAnnotatedWith(e, MappedSuperclass.class);
+    }
+
+    /**
+     * Affirms if the given declaration has the given annotation.
+     */
+    public static boolean isAnnotatedWith(Element e,
+        Class<? extends Annotation> anno) {
+        return e != null && e.getAnnotation(anno) != null;
+    }
+    
+    /**
+     * Affirms if the given element is annotated with any of the given 
+     * annotations.
+     * 
+     * @param annos null checks for any annotation that starts with 
+     *            'javax.persistence.' or 'openjpa.*'.
+     * 
+     */
+    public static boolean isAnnotatedWith(Element e, Set<String> annos) {
+        if (e == null)
+            return false;
+        List<? extends AnnotationMirror> mirrors = e.getAnnotationMirrors();
+        if (annos == null) {
+            for (AnnotationMirror mirror : mirrors) {
+                String name = mirror.getAnnotationType().toString();
+                if (startsWith(name, "javax.persistence.")
+                 || startsWith(name, "openjpa."))
+                    return true;
+            }
+            return false;
+        } else {
+            for (AnnotationMirror mirror : mirrors) {
+                String name = mirror.getAnnotationType().toString();
+                if (annos.contains(name))
+                    return true;
+            }
+            return false;
+        }
+    }
+    
+    String getDeclaredTypeName(TypeMirror mirror) {
+    	return getDeclaredTypeName(mirror, true);
+    }
+    
+     /**
+     * Get the element name of the class the given mirror represents. If the
+     * mirror is primitive then returns the corresponding boxed class name.
+     * If the mirror is parameterized returns only the generic type i.e.
+     * if the given declared type is 
+     * <code>java.util.Set&lt;java.lang.String&gt;</code> this method will 
+     * return <code>java.util.Set</code>.
+     */
+    String getDeclaredTypeName(TypeMirror mirror, boolean box) {
+    	if (mirror.getKind() == TypeKind.ARRAY) {
+    		TypeMirror comp = ((ArrayType)mirror).getComponentType();
+    		return getDeclaredTypeName(comp, false)+"[]";
+    	}
+    	mirror = box? box(mirror) : mirror;
+    	if (isPrimitive(mirror))
+    		return ((PrimitiveType)mirror).toString();
+        return processingEnv.getTypeUtils().asElement(mirror).toString();
+    }
+
+    /**
+     * Gets the declared type of the given member. For fields, returns the 
+     * declared type while for method returns the return type. 
+     * 
+     * @param e a field or method.
+     * @exception if given member is neither a field nor a method.
+     */
+    TypeMirror getDeclaredType(Element e) {
+        TypeMirror result = null;
+        switch (e.getKind()) {
+        case FIELD:
+            result = e.asType();
+            break;
+        case METHOD:
+            result = ((ExecutableElement) e).getReturnType();
+            break;
+        default:
+            throw new IllegalArgumentException(toDetails(e));
+        }
+        return result;
+    }
+    
+    /**
+     * Affirms if the given type mirrors a primitive.
+     */
+    private boolean isPrimitive(TypeMirror mirror) {
+        TypeKind kind = mirror.getKind();
+        return kind == TypeKind.BOOLEAN 
+            || kind == TypeKind.BYTE
+            || kind == TypeKind.CHAR
+            || kind == TypeKind.DOUBLE
+            || kind == TypeKind.FLOAT
+            || kind == TypeKind.INT
+            || kind == TypeKind.LONG
+            || kind == TypeKind.SHORT;
+    }
+    
+    public TypeMirror box(TypeMirror t) {
+        if (isPrimitive(t))
+            return processingEnv.getTypeUtils()
+            .boxedClass((PrimitiveType)t).asType();
+        return t;
+    }
+
+    /**
+     * Gets the parameter type argument at the given index of the given type.
+     * 
+     * @return if the given type represents a parameterized type, then the
+     *         indexed parameter type argument. Otherwise null.
+     */
+    TypeMirror getTypeParameter(TypeMirror mirror, int index) {
+    	if (mirror.getKind() != TypeKind.DECLARED)
+    		return null;
+        List<? extends TypeMirror> params = ((DeclaredType)mirror)
+        	.getTypeArguments();
+        return (params == null || params.size() < index+1) 
+            ? null : params.get(index);
+    }
+
+    @Override
+    public TypeElement getPersistentSupertype(TypeElement cls) {
+        TypeMirror sup = cls.getSuperclass();
+        if (sup == null || isRootObject(sup))
+            return null;
+        TypeElement supe =
+            (TypeElement) processingEnv.getTypeUtils().asElement(sup);
+        if (isAnnotatedAsEntity(supe)) 
+            return supe;
+        return getPersistentSupertype(supe);
+    }
+
+
+    // ========================================================================
+    //  Utilities
+    // ========================================================================
+
+    /**
+     * Affirms if the given mirror represents a primitive or non-primitive
+     * boolean.
+     */
+    public static boolean isBoolean(TypeMirror type) {
+        return (type != null && (type.getKind() == TypeKind.BOOLEAN 
+            || "java.lang.Boolean".equals(type.toString())));
+    }
+
+    /**
+     * Affirms if the given mirror represents a void.
+     */
+    public static boolean isVoid(TypeMirror type) {
+        return (type != null && type.getKind() == TypeKind.VOID);
+    }
+
+    /**
+     * Affirms if the given element represents a method.
+     */
+    public static boolean isMethod(Element e) {
+        return e != null && ExecutableElement.class.isInstance(e)
+            && e.getKind() == ElementKind.METHOD;
+    }
+    
+    /**
+     * Affirms if the given method matches the following signature
+     * <code> public T getXXX() </code>
+     * where T is any non-void type.
+     */
+    public static boolean isNormalGetter(ExecutableElement method) {
+    	String methodName = method.getSimpleName().toString();
+    	return method.getKind() == ElementKind.METHOD
+    	    && startsWith(methodName, "get") 
+    	    && method.getParameters().isEmpty()
+    	    && !isVoid(method.getReturnType());
+    }
+    
+    /**
+     * Affirms if the given method matches the following signature
+     * <code> public boolean isXXX() </code>
+     * <code> public Boolean isXXX() </code>
+     */
+    public static boolean isBooleanGetter(ExecutableElement method) {
+    	String methodName = method.getSimpleName().toString();
+    	return method.getKind() == ElementKind.METHOD
+    	    && startsWith(methodName, "is") 
+    	    && method.getParameters().isEmpty()
+    	    && isBoolean(method.getReturnType());
+    }
+
+    public static boolean isGetter(ExecutableElement method) {
+    	return isNormalGetter(method) || isBooleanGetter(method);
+    }
+    
+    /**
+     * Affirms if the given method matches the following signature
+     * <code> public void setXXX(T t) </code>
+     */
+    public static boolean isSetter(ExecutableElement method) {
+    	String methodName = method.getSimpleName().toString();
+    	return method.getKind() == ElementKind.METHOD
+    	    && startsWith(methodName, "set") 
+    	    && method.getParameters().size() == 1
+    	    && isVoid(method.getReturnType());
+    }
+    
+    /**
+     * Affirms if the given mirror represents root java.lang.Object.
+     */
+    public static boolean isRootObject(TypeMirror type) {
+        return type != null && "java.lang.Object".equals(type.toString());
+    }
+    
+    /**
+     * Affirms if the given full string starts with the given head.
+     */
+    public static boolean startsWith(String full, String head) {
+        return full != null && head != null && full.startsWith(head) 
+            && full.length() > head.length();
+    }
+
+    /**
+     * Affirms if the given enum equals the given value.
+     */
+    public static boolean equalsByValue(Enum<?> e, Object v) {
+        return e == v 
+             || (v != null && e != null && e.toString().equals(v.toString()));
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message