mirror of https://github.com/apache/openjpa.git
OPENJPA-1010: MetaDataRespository knows about meta-class. The naming and support for meta-class added to MetaDataFactory. Implemented in PersistenceMetaDataFactory. AnnotationProcessor6 aligned with this naming policy interface.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@772820 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
195525392c
commit
9a8246799c
|
@ -2037,7 +2037,7 @@ public class ClassMetaData
|
||||||
try {
|
try {
|
||||||
oid.getConstructor((Class[]) null);
|
oid.getConstructor((Class[]) null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new MetaDataException(_loc.get("null-cons", _type)).
|
throw new MetaDataException(_loc.get("null-cons", oid, _type)).
|
||||||
setCause(e);
|
setCause(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,4 +126,19 @@ public class DelegatingMetaDataFactory
|
||||||
public void loadXMLMetaData(FieldMetaData fmd) {
|
public void loadXMLMetaData(FieldMetaData fmd) {
|
||||||
_delegate.loadXMLMetaData(fmd);
|
_delegate.loadXMLMetaData(fmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMetaModelClassName(String managedClassName) {
|
||||||
|
return _delegate.getMetaModelClassName(managedClassName);
|
||||||
|
}
|
||||||
|
public String getManagedClassName(String metamodelClassName) {
|
||||||
|
return _delegate.getManagedClassName(metamodelClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMetaClass(Class<?> c) {
|
||||||
|
return _delegate.isMetaClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getManagedClass(Class<?> c) {
|
||||||
|
return _delegate.getManagedClass(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.openjpa.lib.meta.ClassArgParser;
|
||||||
*
|
*
|
||||||
* @author Patrick Linskey
|
* @author Patrick Linskey
|
||||||
* @author Abe White
|
* @author Abe White
|
||||||
|
* @author Pinaki Poddar
|
||||||
*/
|
*/
|
||||||
public interface MetaDataFactory
|
public interface MetaDataFactory
|
||||||
extends MetaDataModes {
|
extends MetaDataModes {
|
||||||
|
@ -151,4 +152,37 @@ public interface MetaDataFactory
|
||||||
* metadata should be added directly to the repository.
|
* metadata should be added directly to the repository.
|
||||||
*/
|
*/
|
||||||
public void loadXMLMetaData(FieldMetaData fmd);
|
public void loadXMLMetaData(FieldMetaData fmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the meta-model class for the given fully-qualified
|
||||||
|
* managed class name.
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public String getMetaModelClassName(String managedClassName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the managed class for the given fully-qualified
|
||||||
|
* meta-model class name.
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public String getManagedClassName(String metamodelClassName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affirms if the given class is a meta-class.
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public boolean isMetaClass(Class<?> c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the managed class corresponding to the given meta-class.
|
||||||
|
*
|
||||||
|
* @return null if the given input is not a meta-class.
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public Class<?> getManagedClass(Class<?> c);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,8 @@ public class MetaDataRepository
|
||||||
.synchronizedMap(new HashMap<Class<?>,NonPersistentMetaData>());
|
.synchronizedMap(new HashMap<Class<?>,NonPersistentMetaData>());
|
||||||
private final Map<Class<?>,NonPersistentMetaData> _nonMapped = Collections
|
private final Map<Class<?>,NonPersistentMetaData> _nonMapped = Collections
|
||||||
.synchronizedMap(new HashMap<Class<?>,NonPersistentMetaData>());
|
.synchronizedMap(new HashMap<Class<?>,NonPersistentMetaData>());
|
||||||
|
private final Map<Class<?>, Class<?>> _metamodel = Collections
|
||||||
|
.synchronizedMap(new HashMap<Class<?>, Class<?>>());
|
||||||
|
|
||||||
// map of classes to lists of their subclasses
|
// map of classes to lists of their subclasses
|
||||||
private final Map<Class<?>,List<Class<?>>> _subs =
|
private final Map<Class<?>,List<Class<?>>> _subs =
|
||||||
|
@ -1321,6 +1323,10 @@ public class MetaDataRepository
|
||||||
Class<?> cls;
|
Class<?> cls;
|
||||||
for (String className : names) {
|
for (String className : names) {
|
||||||
cls = classForName(className, clsLoader);
|
cls = classForName(className, clsLoader);
|
||||||
|
if (_factory.isMetaClass(cls)) {
|
||||||
|
setMetaModel(cls);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (cls != null) {
|
if (cls != null) {
|
||||||
classes.add(cls);
|
classes.add(cls);
|
||||||
|
|
||||||
|
@ -1588,6 +1594,53 @@ public class MetaDataRepository
|
||||||
coll.add(value);
|
coll.add(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the meta class corresponding to the given entity class.
|
||||||
|
*/
|
||||||
|
public void setMetaModel(Class<?> m2) {
|
||||||
|
Class<?> cls = _factory.getManagedClass(m2);
|
||||||
|
if (cls != null)
|
||||||
|
_metamodel.put(cls, m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the meta class corresponding to the given persistent class.
|
||||||
|
*/
|
||||||
|
public void setMetaModel(ClassMetaData meta, Class<?> m2) {
|
||||||
|
_metamodel.put(meta.getDescribedType(), m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the meta class corresponding to the given persistent class.
|
||||||
|
*/
|
||||||
|
public Class<?> getMetaModel(ClassMetaData meta, boolean load) {
|
||||||
|
return getMetaModel(meta.getDescribedType(), load);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the meta class corresponding to the given class.
|
||||||
|
* If load is false, returns the meta class if has been set for the given
|
||||||
|
* persistent class earlier.
|
||||||
|
* If the load is true then also attempts to apply the current
|
||||||
|
* naming policy to derive meta class name and attempts to load the meta
|
||||||
|
* class.
|
||||||
|
*/
|
||||||
|
public Class<?> getMetaModel(Class<?> entity, boolean load) {
|
||||||
|
if (_metamodel.containsKey(entity))
|
||||||
|
return _metamodel.get(entity);
|
||||||
|
String m2 = _factory.getMetaModelClassName(entity.getName());
|
||||||
|
try {
|
||||||
|
Class<?> m2cls = J2DoPrivHelper.getForNameAction(m2, true,
|
||||||
|
entity.getClassLoader()).run();
|
||||||
|
_metamodel.put(entity, m2cls);
|
||||||
|
return m2cls;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if (_log.isWarnEnabled())
|
||||||
|
_log.warn(_loc.get("meta-no-model", m2, entity, t));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Configurable implementation
|
// Configurable implementation
|
||||||
|
|
|
@ -142,4 +142,19 @@ public class NoneMetaDataFactory
|
||||||
|
|
||||||
public void loadXMLMetaData(FieldMetaData fmd) {
|
public void loadXMLMetaData(FieldMetaData fmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMetaModelClassName(String managedClassName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public String getManagedClassName(String metamodelClassName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMetaClass(Class<?> c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getManagedClass(Class<?> c) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ invalid-id: The id class specified by type "{0}" does not match the \
|
||||||
primary key fields of the class. Make sure your identity class has the \
|
primary key fields of the class. Make sure your identity class has the \
|
||||||
same primary keys as your persistent type, including pk field types. \
|
same primary keys as your persistent type, including pk field types. \
|
||||||
Mismatched property: "{1}"
|
Mismatched property: "{1}"
|
||||||
null-cons: The id class specified by type "{0}" does not have a public \
|
null-cons: The id class "{0}" specified by type "{1}" does not have a public \
|
||||||
no-args constructor.
|
no-args constructor.
|
||||||
hc-method: The identity class specified by type "{0}" is not valid, as the \
|
hc-method: The identity class specified by type "{0}" is not valid, as the \
|
||||||
hashCode method is not overridden. Implement hashCode so that two \
|
hashCode method is not overridden. Implement hashCode so that two \
|
||||||
|
|
|
@ -19,8 +19,12 @@
|
||||||
|
|
||||||
package org.apache.openjpa.persistence.meta;
|
package org.apache.openjpa.persistence.meta;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import javax.persistence.metamodel.Attribute;
|
import javax.persistence.metamodel.Attribute;
|
||||||
import javax.persistence.metamodel.Collection;
|
import javax.persistence.metamodel.Collection;
|
||||||
|
import javax.persistence.metamodel.Entity;
|
||||||
import javax.persistence.metamodel.List;
|
import javax.persistence.metamodel.List;
|
||||||
import javax.persistence.metamodel.ManagedType;
|
import javax.persistence.metamodel.ManagedType;
|
||||||
import javax.persistence.metamodel.Set;
|
import javax.persistence.metamodel.Set;
|
||||||
|
@ -30,6 +34,9 @@ import javax.persistence.metamodel.Bindable.BindableType;
|
||||||
import javax.persistence.metamodel.Type.PersistenceType;
|
import javax.persistence.metamodel.Type.PersistenceType;
|
||||||
|
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
|
import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
|
import org.apache.openjpa.persistence.criteria.Account;
|
||||||
|
import org.apache.openjpa.persistence.criteria.Account_;
|
||||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,9 +47,11 @@ import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
*/
|
*/
|
||||||
public class TestMetamodel extends SingleEMFTestCase {
|
public class TestMetamodel extends SingleEMFTestCase {
|
||||||
MetamodelImpl model;
|
MetamodelImpl model;
|
||||||
|
MetaDataRepository repos;
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
super.setUp(
|
super.setUp(
|
||||||
|
Account.class,
|
||||||
ImplicitFieldAccessMappedSuperclass.class,
|
ImplicitFieldAccessMappedSuperclass.class,
|
||||||
ImplicitFieldAccessBase.class,
|
ImplicitFieldAccessBase.class,
|
||||||
ImplicitFieldAccessSubclass.class,
|
ImplicitFieldAccessSubclass.class,
|
||||||
|
@ -51,15 +60,31 @@ public class TestMetamodel extends SingleEMFTestCase {
|
||||||
Embed0.class,
|
Embed0.class,
|
||||||
Embed1.class);
|
Embed1.class);
|
||||||
emf.createEntityManager();
|
emf.createEntityManager();
|
||||||
|
repos = emf.getConfiguration().getMetaDataRepositoryInstance();
|
||||||
model = (MetamodelImpl)emf.getMetamodel();
|
model = (MetamodelImpl)emf.getMetamodel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testModelIsPopulated() {
|
public void testModelIsInstantiated() {
|
||||||
assertFalse(model.getEntities().isEmpty());
|
assertFalse(model.getEntities().isEmpty());
|
||||||
assertFalse(model.getEmbeddables().isEmpty());
|
assertFalse(model.getEmbeddables().isEmpty());
|
||||||
assertFalse(model.getManagedTypes().isEmpty());
|
assertFalse(model.getManagedTypes().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testModelIsPopulated() {
|
||||||
|
Entity<Account> m = model.entity(Account.class);
|
||||||
|
Class<?> mCls = m.getJavaType();
|
||||||
|
assertNotNull(m);
|
||||||
|
Class<?> m2Cls = repos.getMetaModel(mCls, true);
|
||||||
|
assertNotNull(m2Cls);
|
||||||
|
try {
|
||||||
|
Field f2 = getStaticField(m2Cls, "balance");
|
||||||
|
assertNotNull(f2);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testPersistentCategory() {
|
public void testPersistentCategory() {
|
||||||
assertCategory(PersistenceType.MAPPED_SUPERCLASS,
|
assertCategory(PersistenceType.MAPPED_SUPERCLASS,
|
||||||
ImplicitFieldAccessMappedSuperclass.class);
|
ImplicitFieldAccessMappedSuperclass.class);
|
||||||
|
@ -199,4 +224,19 @@ public class TestMetamodel extends SingleEMFTestCase {
|
||||||
void assertCategory(PersistenceType category, Class<?> cls) {
|
void assertCategory(PersistenceType category, Class<?> cls) {
|
||||||
assertEquals(category, categorize(cls));
|
assertEquals(category, categorize(cls));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Field getStaticField(Class<?> cls, String name) {
|
||||||
|
try {
|
||||||
|
System.err.println("Fields of " + cls);
|
||||||
|
Field[] fds = cls.getDeclaredFields();
|
||||||
|
for (Field f : fds) {
|
||||||
|
System.err.println(f);
|
||||||
|
int mods = f.getModifiers();
|
||||||
|
if (f.getName().equals(name) && Modifier.isStatic(mods))
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.SqlResultSetMapping;
|
import javax.persistence.SqlResultSetMapping;
|
||||||
import javax.persistence.SqlResultSetMappings;
|
import javax.persistence.SqlResultSetMappings;
|
||||||
|
import javax.persistence.metamodel.TypesafeMetamodel;
|
||||||
|
|
||||||
import org.apache.openjpa.lib.conf.Configurable;
|
import org.apache.openjpa.lib.conf.Configurable;
|
||||||
import org.apache.openjpa.lib.conf.Configuration;
|
import org.apache.openjpa.lib.conf.Configuration;
|
||||||
|
@ -538,4 +539,31 @@ public class PersistenceMetaDataFactory
|
||||||
= getXMLAnnotationParser();
|
= getXMLAnnotationParser();
|
||||||
parser.parse(fmd);
|
parser.parse(fmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String UNDERSCORE = "_";
|
||||||
|
|
||||||
|
public String getManagedClassName(String mmClassName) {
|
||||||
|
if (mmClassName == null || mmClassName.length() == 0)
|
||||||
|
return null;
|
||||||
|
if (mmClassName.endsWith(UNDERSCORE))
|
||||||
|
return mmClassName.substring(0, mmClassName.length()-1);
|
||||||
|
return mmClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMetaModelClassName(String managedClassName) {
|
||||||
|
if (managedClassName == null || managedClassName.length() == 0)
|
||||||
|
return null;
|
||||||
|
return managedClassName + UNDERSCORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMetaClass(Class<?> c) {
|
||||||
|
return c != null && c.getAnnotation(TypesafeMetamodel.class) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getManagedClass(Class<?> c) {
|
||||||
|
if (isMetaClass(c)) {
|
||||||
|
return c.getAnnotation(TypesafeMetamodel.class).value();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
package org.apache.openjpa.persistence.meta;
|
||||||
|
|
||||||
import static javax.lang.model.SourceVersion.RELEASE_6;
|
import static javax.lang.model.SourceVersion.RELEASE_6;
|
||||||
|
@ -14,7 +32,6 @@ import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Generated;
|
import javax.annotation.Generated;
|
||||||
import javax.annotation.processing.AbstractProcessor;
|
import javax.annotation.processing.AbstractProcessor;
|
||||||
import javax.annotation.processing.Filer;
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.annotation.processing.RoundEnvironment;
|
import javax.annotation.processing.RoundEnvironment;
|
||||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||||
|
@ -25,7 +42,6 @@ import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.persistence.metamodel.TypesafeMetamodel;
|
import javax.persistence.metamodel.TypesafeMetamodel;
|
||||||
import javax.tools.Diagnostic;
|
|
||||||
import javax.tools.JavaCompiler;
|
import javax.tools.JavaCompiler;
|
||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
import javax.tools.StandardJavaFileManager;
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
@ -33,6 +49,8 @@ import javax.tools.StandardLocation;
|
||||||
import javax.tools.ToolProvider;
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.meta.MetaDataFactory;
|
||||||
|
import org.apache.openjpa.persistence.PersistenceMetaDataFactory;
|
||||||
import org.apache.openjpa.persistence.util.SourceCode;
|
import org.apache.openjpa.persistence.util.SourceCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +60,8 @@ import org.apache.openjpa.persistence.util.SourceCode;
|
||||||
* This tool is invoked during compilation for JDK6 compiler if OpenJPA and JPA
|
* This tool is invoked during compilation for JDK6 compiler if OpenJPA and JPA
|
||||||
* libraries are specified in the compiler <code>-processorpath</code> option.
|
* libraries are specified in the compiler <code>-processorpath</code> option.
|
||||||
* <br>
|
* <br>
|
||||||
|
* Supported options
|
||||||
|
* <LI>
|
||||||
* For example,<br>
|
* For example,<br>
|
||||||
* <center><code>$ javac -processorpath path/to/openjpa;/path/to/jpa
|
* <center><code>$ javac -processorpath path/to/openjpa;/path/to/jpa
|
||||||
* -s src -Alog mypackage/MyClass.java</code></center>
|
* -s src -Alog mypackage/MyClass.java</code></center>
|
||||||
|
@ -65,15 +85,17 @@ import org.apache.openjpa.persistence.util.SourceCode;
|
||||||
"javax.persistence.Entity",
|
"javax.persistence.Entity",
|
||||||
"javax.persistence.Embeddable",
|
"javax.persistence.Embeddable",
|
||||||
"javax.persistence.MappedSuperclass" })
|
"javax.persistence.MappedSuperclass" })
|
||||||
@SupportedOptions( { "log", "out", "source" })
|
@SupportedOptions( { "log", "out", "source", "naming" })
|
||||||
@SupportedSourceVersion(RELEASE_6)
|
@SupportedSourceVersion(RELEASE_6)
|
||||||
|
|
||||||
public class AnnotationProcessor6 extends AbstractProcessor {
|
public class AnnotationProcessor6 extends AbstractProcessor {
|
||||||
private SourceAnnotationHandler handler;
|
private SourceAnnotationHandler handler;
|
||||||
|
private StandardJavaFileManager fileManager;
|
||||||
|
private MetaDataFactory factory;
|
||||||
|
private int generatedSourceVersion = 6;
|
||||||
private CompileTimeLogger logger;
|
private CompileTimeLogger logger;
|
||||||
private static Localizer _loc =
|
private static Localizer _loc =
|
||||||
Localizer.forPackage(AnnotationProcessor6.class);
|
Localizer.forPackage(AnnotationProcessor6.class);
|
||||||
private static final String UNDERSCORE = "_";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Category of members as per JPA 2.0 type system.
|
* Category of members as per JPA 2.0 type system.
|
||||||
|
@ -147,10 +169,12 @@ public class AnnotationProcessor6 extends AbstractProcessor {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||||
super.init(processingEnv);
|
super.init(processingEnv);
|
||||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
|
|
||||||
_loc.get("mmg-tool-banner").getMessage());
|
|
||||||
logger = new CompileTimeLogger(processingEnv);
|
logger = new CompileTimeLogger(processingEnv);
|
||||||
handler = new SourceAnnotationHandler(processingEnv);
|
logger.info(_loc.get("mmg-tool-banner"));
|
||||||
|
setSourceVersion();
|
||||||
|
setFileManager();
|
||||||
|
setNamingPolicy();
|
||||||
|
handler = new SourceAnnotationHandler(processingEnv, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,14 +205,17 @@ public class AnnotationProcessor6 extends AbstractProcessor {
|
||||||
Elements eUtils = processingEnv.getElementUtils();
|
Elements eUtils = processingEnv.getElementUtils();
|
||||||
String originalClass = eUtils.getBinaryName((TypeElement) e).toString();
|
String originalClass = eUtils.getBinaryName((TypeElement) e).toString();
|
||||||
String originalSimpleClass = e.getSimpleName().toString();
|
String originalSimpleClass = e.getSimpleName().toString();
|
||||||
String metaClass = originalClass + UNDERSCORE;
|
String metaClass = factory.getMetaModelClassName(originalClass);
|
||||||
|
|
||||||
SourceCode source = new SourceCode(metaClass);
|
SourceCode source = new SourceCode(metaClass);
|
||||||
comment(source);
|
comment(source);
|
||||||
annotate(source, originalClass);
|
annotate(source, originalClass);
|
||||||
TypeElement supCls = handler.getPersistentSupertype(e);
|
TypeElement supCls = handler.getPersistentSupertype(e);
|
||||||
if (supCls != null)
|
if (supCls != null) {
|
||||||
source.getTopLevelClass().setSuper(supCls.toString() + UNDERSCORE);
|
String superName = factory.getMetaModelClassName(
|
||||||
|
supCls.toString());
|
||||||
|
source.getTopLevelClass().setSuper(superName);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
PrintWriter writer = createSourceFile(metaClass, e);
|
PrintWriter writer = createSourceFile(metaClass, e);
|
||||||
SourceCode.Class modelClass = source.getTopLevelClass();
|
SourceCode.Class modelClass = source.getTopLevelClass();
|
||||||
|
@ -244,7 +271,7 @@ public class AnnotationProcessor6 extends AbstractProcessor {
|
||||||
SourceCode.Class cls = source.getTopLevelClass();
|
SourceCode.Class cls = source.getTopLevelClass();
|
||||||
cls.addAnnotation(TypesafeMetamodel.class.getName())
|
cls.addAnnotation(TypesafeMetamodel.class.getName())
|
||||||
.addArgument("value", originalClass + ".class", false);
|
.addArgument("value", originalClass + ".class", false);
|
||||||
if (getSourceVersion() >= 6) {
|
if (generatedSourceVersion >= 6) {
|
||||||
cls.addAnnotation(Generated.class.getName())
|
cls.addAnnotation(Generated.class.getName())
|
||||||
.addArgument("value", this.getClass().getName())
|
.addArgument("value", this.getClass().getName())
|
||||||
.addArgument("date", new Date().toString());
|
.addArgument("date", new Date().toString());
|
||||||
|
@ -260,33 +287,57 @@ public class AnnotationProcessor6 extends AbstractProcessor {
|
||||||
* the source version for the generated classes.
|
* the source version for the generated classes.
|
||||||
* n must be a integer. Default or wrong specification returns 6.
|
* n must be a integer. Default or wrong specification returns 6.
|
||||||
*/
|
*/
|
||||||
private int getSourceVersion() {
|
private void setSourceVersion() {
|
||||||
String version = processingEnv.getOptions().get("source");
|
String version = processingEnv.getOptions().get("source");
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(version);
|
generatedSourceVersion = Integer.parseInt(version);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
logger.warn(_loc.get("mmg-bad-source", version, 6));
|
||||||
|
generatedSourceVersion = 6;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
generatedSourceVersion = 6;
|
||||||
}
|
}
|
||||||
return 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PrintWriter createSourceFile(String metaClass, TypeElement e)
|
private void setNamingPolicy() {
|
||||||
throws IOException {
|
String policy = processingEnv.getOptions().get("naming");
|
||||||
|
if (policy != null) {
|
||||||
|
try {
|
||||||
|
factory = (MetaDataFactory)Class.forName(policy).newInstance();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.warn(_loc.get("mmg-bad-naming", policy, e));
|
||||||
|
factory = new PersistenceMetaDataFactory();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
factory = new PersistenceMetaDataFactory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFileManager() {
|
||||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
StandardJavaFileManager mgr = compiler.getStandardFileManager(null,
|
fileManager = compiler.getStandardFileManager(null,
|
||||||
null, null);
|
null, null);
|
||||||
String srcOutput = processingEnv.getOptions().get("out");
|
String srcOutput = processingEnv.getOptions().get("out");
|
||||||
if (srcOutput != null) {
|
if (srcOutput != null) {
|
||||||
mgr.setLocation(StandardLocation.SOURCE_OUTPUT,
|
try {
|
||||||
|
fileManager.setLocation(StandardLocation.SOURCE_OUTPUT,
|
||||||
Collections.singletonList(new File(srcOutput)));
|
Collections.singletonList(new File(srcOutput)));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
logger.warn(_loc.get("mmg-bad-out", srcOutput,
|
||||||
|
StandardLocation.SOURCE_OUTPUT));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrintWriter createSourceFile(String metaClass, TypeElement e)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
JavaFileObject javaFile = mgr.getJavaFileForOutput(
|
JavaFileObject javaFile = fileManager.getJavaFileForOutput(
|
||||||
StandardLocation.SOURCE_OUTPUT,
|
StandardLocation.SOURCE_OUTPUT,
|
||||||
metaClass, JavaFileObject.Kind.SOURCE, null);
|
metaClass, JavaFileObject.Kind.SOURCE, null);
|
||||||
logger.info(_loc.get("mmg-process", javaFile.toUri()).getMessage());
|
logger.info(_loc.get("mmg-process", javaFile.toUri()));
|
||||||
OutputStream out = javaFile.openOutputStream();
|
OutputStream out = javaFile.openOutputStream();
|
||||||
PrintWriter writer = new PrintWriter(out);
|
PrintWriter writer = new PrintWriter(out);
|
||||||
return writer;
|
return writer;
|
||||||
|
|
|
@ -22,6 +22,8 @@ import javax.annotation.processing.Messager;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple logger sets log level from javac compilers annotation processing
|
* Simple logger sets log level from javac compilers annotation processing
|
||||||
* options <code>-Alog=TRACE|INFO|WARN|ERROR</code> and uses the processing
|
* options <code>-Alog=TRACE|INFO|WARN|ERROR</code> and uses the processing
|
||||||
|
@ -32,10 +34,20 @@ import javax.tools.Diagnostic;
|
||||||
*/
|
*/
|
||||||
public class CompileTimeLogger {
|
public class CompileTimeLogger {
|
||||||
private static enum Level {TRACE, INFO, WARN, ERROR};
|
private static enum Level {TRACE, INFO, WARN, ERROR};
|
||||||
|
private static Localizer _loc = Localizer.forPackage(
|
||||||
|
CompileTimeLogger.class);
|
||||||
|
private static Level DEFAULT_LEVEL = Level.WARN;
|
||||||
private int logLevel;
|
private int logLevel;
|
||||||
private Messager messager;
|
private Messager messager;
|
||||||
|
|
||||||
public CompileTimeLogger(ProcessingEnvironment env) {
|
public CompileTimeLogger(ProcessingEnvironment env) {
|
||||||
|
messager = env.getMessager();
|
||||||
|
|
||||||
String level = env.getOptions().get("log");
|
String level = env.getOptions().get("log");
|
||||||
|
if (level == null) {
|
||||||
|
logLevel = DEFAULT_LEVEL.ordinal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ("trace".equalsIgnoreCase(level))
|
if ("trace".equalsIgnoreCase(level))
|
||||||
logLevel = Level.TRACE.ordinal();
|
logLevel = Level.TRACE.ordinal();
|
||||||
else if ("info".equalsIgnoreCase(level))
|
else if ("info".equalsIgnoreCase(level))
|
||||||
|
@ -45,32 +57,31 @@ public class CompileTimeLogger {
|
||||||
else if ("error".equalsIgnoreCase(level))
|
else if ("error".equalsIgnoreCase(level))
|
||||||
logLevel = Level.ERROR.ordinal();
|
logLevel = Level.ERROR.ordinal();
|
||||||
else {
|
else {
|
||||||
logLevel = Level.INFO.ordinal();
|
logLevel = DEFAULT_LEVEL.ordinal();
|
||||||
warn("mmg-bad-log");
|
warn(_loc.get("mmg-bad-log", level, DEFAULT_LEVEL));
|
||||||
}
|
}
|
||||||
messager = env.getMessager();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void info(String message) {
|
public void info(Localizer.Message message) {
|
||||||
log(Level.INFO, message, Diagnostic.Kind.NOTE);
|
log(Level.INFO, message, Diagnostic.Kind.NOTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trace(String message) {
|
public void trace(Localizer.Message message) {
|
||||||
log(Level.TRACE, message, Diagnostic.Kind.NOTE);
|
log(Level.TRACE, message, Diagnostic.Kind.NOTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void warn(String message) {
|
public void warn(Localizer.Message message) {
|
||||||
log(Level.WARN, message, Diagnostic.Kind.MANDATORY_WARNING);
|
log(Level.WARN, message, Diagnostic.Kind.MANDATORY_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void error(String message) {
|
public void error(Localizer.Message message) {
|
||||||
log(Level.ERROR, message, Diagnostic.Kind.ERROR);
|
log(Level.ERROR, message, Diagnostic.Kind.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(Level level, String message, Diagnostic.Kind kind) {
|
private void log(Level level, Localizer.Message message,
|
||||||
|
Diagnostic.Kind kind) {
|
||||||
if (logLevel <= level.ordinal()) {
|
if (logLevel <= level.ordinal()) {
|
||||||
messager.printMessage(kind, message);
|
messager.printMessage(kind, message.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,8 +187,7 @@ public class MetamodelImpl implements Metamodel {
|
||||||
public <X> void populate(Types.Managed<X> type) {
|
public <X> void populate(Types.Managed<X> type) {
|
||||||
try {
|
try {
|
||||||
Class<X> cls = type.getJavaType();
|
Class<X> cls = type.getJavaType();
|
||||||
Class<?> mcls = J2DoPrivHelper.getForNameAction(cls.getName()+"_",
|
Class<?> mcls = repos.getMetaModel(cls, true);
|
||||||
true, cls.getClassLoader()).run();
|
|
||||||
Field[] fields = mcls.getFields();
|
Field[] fields = mcls.getFields();
|
||||||
for (Field f : fields) {
|
for (Field f : fields) {
|
||||||
f.set(null, type.getMember(f.getName()));
|
f.set(null, type.getMember(f.getName()));
|
||||||
|
|
|
@ -88,10 +88,11 @@ public class SourceAnnotationHandler
|
||||||
* Construct with JDK6 annotation processing environment.
|
* Construct with JDK6 annotation processing environment.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public SourceAnnotationHandler(ProcessingEnvironment processingEnv) {
|
public SourceAnnotationHandler(ProcessingEnvironment processingEnv,
|
||||||
|
CompileTimeLogger logger) {
|
||||||
super();
|
super();
|
||||||
this.processingEnv = processingEnv;
|
this.processingEnv = processingEnv;
|
||||||
this.logger = new CompileTimeLogger(processingEnv);
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int determineTypeAccess(TypeElement type) {
|
public int determineTypeAccess(TypeElement type) {
|
||||||
|
@ -262,7 +263,7 @@ public class SourceAnnotationHandler
|
||||||
}
|
}
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
logger.warn(_loc.get("getter-unmatched", getter,
|
logger.warn(_loc.get("getter-unmatched", getter,
|
||||||
getter.getEnclosingElement()).toString());
|
getter.getEnclosingElement()));
|
||||||
unmatched.add(getter);
|
unmatched.add(getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,11 @@ field-key-type-mismatch: Actual key type of map field "{0}" "{1}" does not \
|
||||||
getter-unmatched: Getter method "{0}" in "{1}" has no matching setter method.
|
getter-unmatched: Getter method "{0}" in "{1}" has no matching setter method.
|
||||||
mmg-tool-banner: Starting OpenJPA Annotation Processor for Metamodel Generation
|
mmg-tool-banner: Starting OpenJPA Annotation Processor for Metamodel Generation
|
||||||
mmg-process: Generating canonical metamodel source code "{0}"
|
mmg-process: Generating canonical metamodel source code "{0}"
|
||||||
mmg-tool-sign: Generated by OpenJPA MetaModel Generator Tool.
|
mmg-tool-sign: Generated by OpenJPA MetaModel Generator Tool.
|
||||||
|
mmg-bad-source: Wrong value "{0}" of -Asource option to specify the target \
|
||||||
|
Java compiler version for the generated meta-model files. Expected a \
|
||||||
|
positive number. Setting default value as Java {1} compiler.
|
||||||
|
mmg-bad-naming: Naming policy for meta-model classes specified in -Anaming \
|
||||||
|
option "{0}" can not be used due to "{1}". Using default naming policy.
|
||||||
|
mmg-bad-log: Log level specified is -Alog option "{0}" is not recognized. \
|
||||||
|
Logging at default "{1}" level.
|
Loading…
Reference in New Issue