diff --git a/tooling/metamodel-generator/pom.xml b/tooling/metamodel-generator/pom.xml
index 8d0ade3040..4dac279a2d 100644
--- a/tooling/metamodel-generator/pom.xml
+++ b/tooling/metamodel-generator/pom.xml
@@ -24,6 +24,17 @@
jdk15
test
+
+ org.slf4j
+ slf4j-api
+ 1.5.6
+
+
+ org.slf4j
+ slf4j-log4j12
+ test
+ 1.5.6
+
@@ -150,6 +161,7 @@
maven-surefire-plugin
2.4.3
+ true
sourceBaseDir
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/AccessTypeInformation.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/AccessTypeInformation.java
new file mode 100644
index 0000000000..1ea408f75c
--- /dev/null
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/AccessTypeInformation.java
@@ -0,0 +1,90 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen;
+
+import javax.persistence.AccessType;
+
+/**
+ * Encapsulates the access type information for a single class.
+ *
+ * @author Hardy Ferentschik
+ */
+public class AccessTypeInformation {
+ private final String fqcn;
+
+ /**
+ * Access type explicitly specified in xml or on an entity.
+ */
+ private AccessType explicitAccessType;
+
+ /**
+ * The default type for en entity. This type might change during the parsing/discovering process. The reason
+ * for that is the ability to mix and match xml and annotation configuration.
+ */
+ private AccessType defaultAccessType;
+
+ private static final AccessType DEFAULT_ACCESS_TYPE = AccessType.PROPERTY;
+
+ public AccessTypeInformation(String fqcn, AccessType explicitAccessType, AccessType defaultAccessType) {
+ this.fqcn = fqcn;
+ this.explicitAccessType = explicitAccessType;
+ this.defaultAccessType = defaultAccessType;
+ }
+
+ public boolean isAccessTypeResolved() {
+ return explicitAccessType != null || defaultAccessType != null;
+ }
+
+ public AccessType getAccessType() {
+ if ( explicitAccessType != null ) {
+ return explicitAccessType;
+ }
+ else if ( defaultAccessType != null ) {
+ return defaultAccessType;
+
+ }
+ else {
+ return DEFAULT_ACCESS_TYPE;
+ }
+ }
+
+ public void setDefaultAccessType(AccessType defaultAccessType) {
+ this.defaultAccessType = defaultAccessType;
+ }
+
+ public void setExplicitAccessType(AccessType explicitAccessType) {
+ this.explicitAccessType = explicitAccessType;
+ }
+
+ public AccessType getDefaultAccessType() {
+ return defaultAccessType;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "AccessTypeInformation" );
+ sb.append( "{fqcn='" ).append( fqcn ).append( '\'' );
+ sb.append( ", explicitAccessType=" ).append( explicitAccessType );
+ sb.append( ", defaultAccessType=" ).append( defaultAccessType );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
+
+
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java
index 0376cc1edb..01d668db12 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java
@@ -31,6 +31,9 @@ import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
+import org.hibernate.jpamodelgen.model.MetaEntity;
+
/**
* @author Emmanuel Bernard
*/
@@ -112,8 +115,8 @@ public class ClassWriter {
//F..king Ch...t Have those people used their horrible APIs even once?
final Element superClassElement = ( ( DeclaredType ) superClass ).asElement();
String superClassName = ( ( TypeElement ) superClassElement ).getQualifiedName().toString();
- if ( context.getMetaEntitiesToProcess().containsKey( superClassName )
- || context.getMetaSuperclassAndEmbeddableToProcess().containsKey( superClassName ) ) {
+ if ( context.containsMetaEntity( superClassName )
+ || context.containsMetaSuperclassOrEmbeddable( superClassName ) ) {
pw.print( " extends " + superClassName + "_" );
}
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java
index 3190c05a4c..4181dd76e1 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java
@@ -17,17 +17,20 @@
*/
package org.hibernate.jpamodelgen;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
-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.TypeElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
import javax.persistence.AccessType;
import javax.tools.Diagnostic;
-import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
-import org.hibernate.jpamodelgen.util.TypeUtils;
+import org.hibernate.jpamodelgen.model.MetaEntity;
/**
* @author Max Andersen
@@ -35,84 +38,115 @@ import org.hibernate.jpamodelgen.util.TypeUtils;
* @author Emmanuel Bernard
*/
public class Context {
+ private static final String PATH_SEPARATOR = System.getProperty( "file.separator" );
+ private static final String DEFAULT_PERSISTENCE_XML_LOCATION = "/META-INF/persistence.xml";
+ private final Map metaEntities = new HashMap();
+ private final Map metaSuperclassAndEmbeddable = new HashMap();
+ private final Map accessTypeInformation = new HashMap();
- private final Map metaEntitiesToProcess = new HashMap();
- private final Map metaSuperclassAndEmbeddableToProcess = new HashMap();
+ private final ProcessingEnvironment pe;
+ private final boolean logDebug;
+ private final String persistenceXmlLocation;
- private ProcessingEnvironment pe;
- private boolean logDebug = false;
-
- //used to cache access types
- private Map accessTypes = new HashMap();
- private Set elementsAlreadyProcessed = new HashSet();
-
- private static class AccessTypeHolder {
- public AccessType elementAccessType;
- public AccessType hierarchyAccessType;
- }
+ private final List ormXmlFiles;
+ private boolean isPersistenceUnitCompletelyXmlConfigured;
+ private AccessType persistenceUnitDefaultAccessType;
public Context(ProcessingEnvironment pe) {
this.pe = pe;
- String debugParam = pe.getOptions().get( JPAMetaModelEntityProcessor.DEBUG_OPTION );
- if ( debugParam != null && "true".equals( debugParam ) ) {
- logDebug = true;
+
+ if ( pe.getOptions().get( JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION ) != null ) {
+ String tmp = pe.getOptions().get( JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION );
+ if ( !tmp.startsWith( PATH_SEPARATOR ) ) {
+ tmp = PATH_SEPARATOR + tmp;
+ }
+ persistenceXmlLocation = tmp;
}
+ else {
+ persistenceXmlLocation = DEFAULT_PERSISTENCE_XML_LOCATION;
+ }
+
+ if ( pe.getOptions().get( JPAMetaModelEntityProcessor.ORM_XML_OPTION ) != null ) {
+ String tmp = pe.getOptions().get( JPAMetaModelEntityProcessor.ORM_XML_OPTION );
+ ormXmlFiles = new ArrayList();
+ for ( String ormFile : tmp.split( "," ) ) {
+ if ( !ormFile.startsWith( PATH_SEPARATOR ) ) {
+ ormFile = PATH_SEPARATOR + ormFile;
+ }
+ ormXmlFiles.add( ormFile );
+ }
+ }
+ else {
+ ormXmlFiles = Collections.emptyList();
+ }
+
+ logDebug = Boolean.parseBoolean( pe.getOptions().get( JPAMetaModelEntityProcessor.DEBUG_OPTION ) );
+
}
public ProcessingEnvironment getProcessingEnvironment() {
return pe;
}
- public Map getMetaEntitiesToProcess() {
- return metaEntitiesToProcess;
+ public Elements getElementUtils() {
+ return pe.getElementUtils();
}
- public Map getMetaSuperclassAndEmbeddableToProcess() {
- return metaSuperclassAndEmbeddableToProcess;
+ public Types getTypeUtils() {
+ return pe.getTypeUtils();
}
- public void addAccessType(TypeElement element, AccessType accessType) {
- AccessTypeHolder typeHolder = accessTypes.get( element );
- if ( typeHolder == null ) {
- typeHolder = new AccessTypeHolder();
- accessTypes.put( element, typeHolder );
- }
- typeHolder.elementAccessType = accessType;
+ public String getPersistenceXmlLocation() {
+ return persistenceXmlLocation;
}
- public void addAccessTypeForHierarchy(TypeElement element, AccessType accessType) {
- AccessTypeHolder typeHolder = accessTypes.get( element );
- if ( typeHolder == null ) {
- typeHolder = new AccessTypeHolder();
- accessTypes.put( element, typeHolder );
- }
- typeHolder.hierarchyAccessType = accessType;
+ public List getOrmXmlFiles() {
+ return ormXmlFiles;
}
- public AccessType getAccessType(TypeElement element) {
- final AccessTypeHolder typeHolder = accessTypes.get( element );
- return typeHolder != null ? typeHolder.elementAccessType : null;
+ public boolean containsMetaEntity(String fqcn) {
+ return metaEntities.containsKey( fqcn );
}
- public AccessType getDefaultAccessTypeForHerarchy(TypeElement element) {
- final AccessTypeHolder typeHolder = accessTypes.get( element );
- return typeHolder != null ? typeHolder.hierarchyAccessType : null;
+ public MetaEntity getMetaEntity(String fqcn) {
+ return metaEntities.get( fqcn );
}
- public Set getElementsAlreadyProcessed() {
- return elementsAlreadyProcessed;
+ public Collection getMetaEntities() {
+ return metaEntities.values();
}
- //only process Embeddable or Superclass
- //does not work for Entity (risk of circularity)
- public void processElement(TypeElement element, AccessType defaultAccessTypeForHierarchy) {
- if ( elementsAlreadyProcessed.contains( element.getQualifiedName().toString() ) ) {
- logMessage( Diagnostic.Kind.OTHER, "Element already processed (ignoring): " + element );
- return;
- }
- ClassWriter.writeFile( new AnnotationMetaEntity( element, this, defaultAccessTypeForHierarchy ), this );
- TypeUtils.extractClosestRealTypeAsString( element.asType(), this );
- elementsAlreadyProcessed.add( element.getQualifiedName().toString() );
+ public void addMetaEntity(String fcqn, MetaEntity metaEntity) {
+ metaEntities.put( fcqn, metaEntity );
+ }
+
+ public boolean containsMetaSuperclassOrEmbeddable(String fqcn) {
+ return metaSuperclassAndEmbeddable.containsKey( fqcn );
+ }
+
+ public MetaEntity getMetaSuperclassOrEmbeddable(String fqcn) {
+ return metaSuperclassAndEmbeddable.get( fqcn );
+ }
+
+ public void addMetaSuperclassOrEmbeddable(String fcqn, MetaEntity metaEntity) {
+ metaSuperclassAndEmbeddable.put( fcqn, metaEntity );
+ }
+
+ public Collection getMetaSuperclassOrEmbeddable() {
+ return metaSuperclassAndEmbeddable.values();
+ }
+
+ public void addAccessTypeInformation(String fqcn, AccessTypeInformation info) {
+ accessTypeInformation.put( fqcn, info );
+ }
+
+ public AccessTypeInformation getAccessTypeInfo(String fqcn) {
+ return accessTypeInformation.get( fqcn );
+ }
+
+ public TypeElement getTypeElementForFullyQualifiedName(String fqcn) {
+ Elements elementUtils = pe.getElementUtils();
+ return elementUtils.getTypeElement( fqcn );
}
public void logMessage(Diagnostic.Kind type, String message) {
@@ -121,4 +155,33 @@ public class Context {
}
pe.getMessager().printMessage( type, message );
}
+
+ public boolean isPersistenceUnitCompletelyXmlConfigured() {
+ return isPersistenceUnitCompletelyXmlConfigured;
+ }
+
+ public void setPersistenceUnitCompletelyXmlConfigured(boolean persistenceUnitCompletelyXmlConfigured) {
+ isPersistenceUnitCompletelyXmlConfigured = persistenceUnitCompletelyXmlConfigured;
+ }
+
+ public AccessType getPersistenceUnitDefaultAccessType() {
+ return persistenceUnitDefaultAccessType;
+ }
+
+ public void setPersistenceUnitDefaultAccessType(AccessType persistenceUnitDefaultAccessType) {
+ this.persistenceUnitDefaultAccessType = persistenceUnitDefaultAccessType;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "Context" );
+ sb.append( "{accessTypeInformation=" ).append( accessTypeInformation );
+ sb.append( ", logDebug=" ).append( logDebug );
+ sb.append( ", isPersistenceUnitCompletelyXmlConfigured=" ).append( isPersistenceUnitCompletelyXmlConfigured );
+ sb.append( ", ormXmlFiles=" ).append( ormXmlFiles );
+ sb.append( ", persistenceXmlLocation='" ).append( persistenceXmlLocation ).append( '\'' );
+ sb.append( '}' );
+ return sb.toString();
+ }
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java
index 0a705a193c..5c5511de8a 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContextImpl.java
@@ -18,14 +18,14 @@
package org.hibernate.jpamodelgen;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import org.hibernate.jpamodelgen.model.ImportContext;
+
/**
- *
* @author Max Andersen
* @author Hardy Ferentschik
* @author Emmanuel Bernard
@@ -35,10 +35,11 @@ public class ImportContextImpl implements ImportContext {
Set imports = new TreeSet();
Set staticImports = new TreeSet();
Map simpleNames = new HashMap();
-
+
String basePackage = "";
private static final Map PRIMITIVES = new HashMap();
+
static {
PRIMITIVES.put( "char", "Character" );
@@ -61,77 +62,81 @@ public class ImportContextImpl implements ImportContext {
/**
* Add fqcn to the import list. Returns fqcn as needed in source code.
* Attempts to handle fqcn with array and generics references.
- *
+ *
* e.g.
* java.util.Collection imports java.util.Collection and returns Collection
* org.marvel.Hulk[] imports org.marvel.Hulk and returns Hulk
- *
- *
- * @param fqcn
+ *
+ * @param fqcn Fully qualified class name
+ *
* @return import string
*/
public String importType(String fqcn) {
- String result = fqcn;
-
+ String result = fqcn;
+
//if(fqcn==null) return "/** (null) **/";
-
+
String additionalTypePart = null;
- if(fqcn.indexOf('<')>=0) {
- additionalTypePart = result.substring(fqcn.indexOf('<'));
- result = result.substring(0,fqcn.indexOf('<'));
- fqcn = result;
- } else if(fqcn.indexOf('[')>=0) {
- additionalTypePart = result.substring(fqcn.indexOf('['));
- result = result.substring(0,fqcn.indexOf('['));
+ if ( fqcn.indexOf( '<' ) >= 0 ) {
+ additionalTypePart = result.substring( fqcn.indexOf( '<' ) );
+ result = result.substring( 0, fqcn.indexOf( '<' ) );
fqcn = result;
}
-
+ else if ( fqcn.indexOf( '[' ) >= 0 ) {
+ additionalTypePart = result.substring( fqcn.indexOf( '[' ) );
+ result = result.substring( 0, fqcn.indexOf( '[' ) );
+ fqcn = result;
+ }
+
String pureFqcn = fqcn.replace( '$', '.' );
-
- boolean canBeSimple = true;
-
-
- String simpleName = unqualify(fqcn);
- if(simpleNames.containsKey(simpleName)) {
- String existingFqcn = simpleNames.get(simpleName);
- if(existingFqcn.equals(pureFqcn)) {
+
+ boolean canBeSimple;
+
+ String simpleName = unqualify( fqcn );
+ if ( simpleNames.containsKey( simpleName ) ) {
+ String existingFqcn = simpleNames.get( simpleName );
+ if ( existingFqcn.equals( pureFqcn ) ) {
canBeSimple = true;
- } else {
+ }
+ else {
canBeSimple = false;
}
- } else {
+ }
+ else {
canBeSimple = true;
- simpleNames.put(simpleName, pureFqcn);
+ simpleNames.put( simpleName, pureFqcn );
imports.add( pureFqcn );
}
-
-
- if ( inSamePackage(fqcn) || (imports.contains( pureFqcn ) && canBeSimple) ) {
- result = unqualify( result ); // dequalify
- } else if ( inJavaLang( fqcn ) ) {
+
+
+ if ( inSamePackage( fqcn ) || ( imports.contains( pureFqcn ) && canBeSimple ) ) {
+ result = unqualify( result ); // de-qualify
+ }
+ else if ( inJavaLang( fqcn ) ) {
result = result.substring( "java.lang.".length() );
}
- if(additionalTypePart!=null) {
+ if ( additionalTypePart != null ) {
result = result + additionalTypePart;
- }
-
+ }
+
result = result.replace( '$', '.' );
- return result;
+ return result;
}
-
+
public String staticImport(String fqcn, String member) {
String local = fqcn + "." + member;
- imports.add(local);
- staticImports.add(local);
-
- if(member.equals("*")) {
+ imports.add( local );
+ staticImports.add( local );
+
+ if ( member.equals( "*" ) ) {
return "";
- } else {
+ }
+ else {
return member;
}
}
-
+
private boolean inDefaultPackage(String className) {
return className.indexOf( "." ) < 0;
}
@@ -143,7 +148,7 @@ public class ImportContextImpl implements ImportContext {
private boolean inSamePackage(String className) {
String other = qualifier( className );
return other == basePackage
- || (other != null && other.equals( basePackage ) );
+ || ( other != null && other.equals( basePackage ) );
}
private boolean inJavaLang(String className) {
@@ -152,33 +157,34 @@ public class ImportContextImpl implements ImportContext {
public String generateImports() {
StringBuffer buf = new StringBuffer();
-
- for ( Iterator imps = imports.iterator(); imps.hasNext(); ) {
- String next = imps.next();
- if(isPrimitive(next) || inDefaultPackage(next) || inJavaLang(next) || inSamePackage(next)) {
- // dont add automatically "imported" stuff
- } else {
- if(staticImports.contains(next)) {
- buf.append("import static " + next + ";\r\n");
- } else {
- buf.append("import " + next + ";\r\n");
- }
+
+ for ( String next : imports ) {
+ if ( isPrimitive( next ) || inDefaultPackage( next ) || inJavaLang( next ) || inSamePackage( next ) ) {
+ // dont add automatically "imported" stuff
+ }
+ else {
+ if ( staticImports.contains( next ) ) {
+ buf.append( "import static " + next + ";\r\n" );
}
+ else {
+ buf.append( "import " + next + ";\r\n" );
+ }
+ }
}
-
- if(buf.indexOf( "$" )>=0) {
+
+ if ( buf.indexOf( "$" ) >= 0 ) {
return buf.toString();
}
- return buf.toString();
+ return buf.toString();
}
-
+
public static String unqualify(String qualifiedName) {
- int loc = qualifiedName.lastIndexOf(".");
- return ( loc < 0 ) ? qualifiedName : qualifiedName.substring( qualifiedName.lastIndexOf(".") + 1 );
+ int loc = qualifiedName.lastIndexOf( "." );
+ return ( loc < 0 ) ? qualifiedName : qualifiedName.substring( qualifiedName.lastIndexOf( "." ) + 1 );
}
public static String qualifier(String qualifiedName) {
- int loc = qualifiedName.lastIndexOf(".");
+ int loc = qualifiedName.lastIndexOf( "." );
return ( loc < 0 ) ? "" : qualifiedName.substring( 0, loc );
}
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java
index 6c62769fe6..f8c19fb2da 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java
@@ -17,6 +17,8 @@
*/
package org.hibernate.jpamodelgen;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
@@ -29,12 +31,22 @@ import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.SimpleTypeVisitor6;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import javax.tools.Diagnostic;
+import org.hibernate.jpamodelgen.annotation.AnnotationEmbeddable;
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
+import org.hibernate.jpamodelgen.model.MetaEntity;
+import org.hibernate.jpamodelgen.util.Constants;
+import org.hibernate.jpamodelgen.util.StringUtil;
import org.hibernate.jpamodelgen.util.TypeUtils;
import org.hibernate.jpamodelgen.xml.XmlParser;
@@ -49,9 +61,15 @@ import static javax.lang.model.SourceVersion.RELEASE_6;
*/
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(RELEASE_6)
-@SupportedOptions({ JPAMetaModelEntityProcessor.DEBUG_OPTION })
+@SupportedOptions({
+ JPAMetaModelEntityProcessor.DEBUG_OPTION,
+ JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION,
+ JPAMetaModelEntityProcessor.ORM_XML_OPTION
+})
public class JPAMetaModelEntityProcessor extends AbstractProcessor {
public static final String DEBUG_OPTION = "debug";
+ public static final String PERSISTENCE_XML_OPTION = "persistenceXml";
+ public static final String ORM_XML_OPTION = "ormXmlList";
private static final Boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = Boolean.FALSE;
private boolean xmlProcessed = false;
@@ -78,75 +96,190 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
if ( !xmlProcessed ) {
XmlParser parser = new XmlParser( context );
- parser.parsePersistenceXml();
+ parser.parseXml();
xmlProcessed = true;
}
- if ( !hostJPAAnnotations( annotations ) ) {
- context.logMessage( Diagnostic.Kind.OTHER, "Current processing round does not contain entities" );
+ if ( context.isPersistenceUnitCompletelyXmlConfigured() ) {
+ context.logMessage(
+ Diagnostic.Kind.OTHER,
+ "Skipping the processing of annotations since persistence unit is purely xml configured."
+ );
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
}
Set extends Element> elements = roundEnvironment.getRootElements();
for ( Element element : elements ) {
- context.logMessage( Diagnostic.Kind.OTHER, "Processing " + element.toString() );
- handleRootElementAnnotationMirrors( element );
+ if ( isJPAEntity( element ) ) {
+ context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class " + element.toString() );
+ handleRootElementAnnotationMirrors( element );
+ }
}
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
}
private void createMetaModelClasses() {
- for ( MetaEntity entity : context.getMetaEntitiesToProcess().values() ) {
- context.logMessage( Diagnostic.Kind.OTHER, "Writing meta model for " + entity );
+ for ( MetaEntity entity : context.getMetaEntities() ) {
+ context.logMessage( Diagnostic.Kind.OTHER, "Writing meta model for entity " + entity );
ClassWriter.writeFile( entity, context );
}
- //process left over, in most cases is empty
- for ( String className : context.getElementsAlreadyProcessed() ) {
- context.getMetaSuperclassAndEmbeddableToProcess().remove( className );
- }
-
- for ( MetaEntity entity : context.getMetaSuperclassAndEmbeddableToProcess().values() ) {
- context.logMessage( Diagnostic.Kind.OTHER, "Writing meta model for " + entity );
- ClassWriter.writeFile( entity, context );
+ // we cannot process the delayed entities in any order. There might be dependencies between them.
+ // we need to process the top level entities first
+ // TODO make sure that we don't run into circular dependencies here
+ Collection toProcessEntities = context.getMetaSuperclassOrEmbeddable();
+ while ( !toProcessEntities.isEmpty() ) {
+ Set processedEntities = new HashSet();
+ for ( MetaEntity entity : toProcessEntities ) {
+ if ( containedInEntity( toProcessEntities, entity ) ) {
+ continue;
+ }
+ context.logMessage(
+ Diagnostic.Kind.OTHER, "Writing meta model for embeddable/mapped superclass" + entity
+ );
+ ClassWriter.writeFile( entity, context );
+ processedEntities.add( entity );
+ }
+ toProcessEntities.removeAll( processedEntities );
}
}
- private boolean hostJPAAnnotations(Set extends TypeElement> annotations) {
- for ( TypeElement type : annotations ) {
- if ( TypeUtils.isTypeElementOfType( type, Entity.class ) ) {
- return true;
+ private boolean containedInEntity(Collection entities, MetaEntity containedEntity) {
+ ContainsAttributeTypeVisitor visitor = new ContainsAttributeTypeVisitor(
+ containedEntity.getTypeElement(), context
+ );
+ for ( MetaEntity entity : entities ) {
+ if ( entity.equals( containedEntity ) ) {
+ continue;
}
- else if ( TypeUtils.isTypeElementOfType( type, Embeddable.class ) ) {
- return true;
+ for ( Element subElement : ElementFilter.fieldsIn( entity.getTypeElement().getEnclosedElements() ) ) {
+ TypeMirror mirror = subElement.asType();
+ if ( !TypeKind.DECLARED.equals( mirror.getKind() ) ) {
+ continue;
+ }
+ boolean contains = mirror.accept( visitor, subElement );
+ if ( contains ) {
+ return true;
+ }
}
- else if ( TypeUtils.isTypeElementOfType( type, MappedSuperclass.class ) ) {
- return true;
+ for ( Element subElement : ElementFilter.methodsIn( entity.getTypeElement().getEnclosedElements() ) ) {
+ TypeMirror mirror = subElement.asType();
+ if ( !TypeKind.DECLARED.equals( mirror.getKind() ) ) {
+ continue;
+ }
+ boolean contains = mirror.accept( visitor, subElement );
+ if ( contains ) {
+ return true;
+ }
}
}
return false;
}
+ private boolean isJPAEntity(Element element) {
+ return TypeUtils.containsAnnotation( element, Entity.class, MappedSuperclass.class, Embeddable.class );
+ }
+
private void handleRootElementAnnotationMirrors(final Element element) {
-
List extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
-
for ( AnnotationMirror mirror : annotationMirrors ) {
- if ( element.getKind() == ElementKind.CLASS ) {
- if ( TypeUtils.isAnnotationMirrorOfType( mirror, Entity.class ) ) {
- AnnotationMetaEntity metaEntity = new AnnotationMetaEntity( ( TypeElement ) element, context );
- // TODO instead of just adding the entity we have to do some merging.
- context.getMetaEntitiesToProcess().put( metaEntity.getQualifiedName(), metaEntity );
- }
- else if ( TypeUtils.isAnnotationMirrorOfType( mirror, MappedSuperclass.class )
- || TypeUtils.isAnnotationMirrorOfType( mirror, Embeddable.class ) ) {
- AnnotationMetaEntity metaEntity = new AnnotationMetaEntity( ( TypeElement ) element, context );
-
- // TODO instead of just adding the entity we have to do some merging.
- context.getMetaSuperclassAndEmbeddableToProcess().put( metaEntity.getQualifiedName(), metaEntity );
- }
+ if ( !ElementKind.CLASS.equals( element.getKind() ) ) {
+ continue;
}
+
+ String fqn = ( ( TypeElement ) element ).getQualifiedName().toString();
+ MetaEntity alreadyExistingMetaEntity = tryGettingExistingEntityFromContext( mirror, fqn );
+ if ( alreadyExistingMetaEntity != null && alreadyExistingMetaEntity.isMetaComplete() ) {
+ String msg = "Skipping processing of annotations for " + fqn + " since xml configuration is metadata complete.";
+ context.logMessage( Diagnostic.Kind.OTHER, msg );
+ continue;
+ }
+
+ AnnotationMetaEntity metaEntity;
+ if ( TypeUtils.containsAnnotation( element, Embeddable.class ) ) {
+ metaEntity = new AnnotationEmbeddable( ( TypeElement ) element, context );
+ }
+ else {
+ metaEntity = new AnnotationMetaEntity( ( TypeElement ) element, context );
+ }
+
+ if ( alreadyExistingMetaEntity != null ) {
+ metaEntity.mergeInMembers( alreadyExistingMetaEntity.getMembers() );
+ }
+ addMetaEntityToContext( mirror, metaEntity );
+ }
+ }
+
+ private MetaEntity tryGettingExistingEntityFromContext(AnnotationMirror mirror, String fqn) {
+ MetaEntity alreadyExistingMetaEntity = null;
+ if ( TypeUtils.isAnnotationMirrorOfType( mirror, Entity.class ) ) {
+ alreadyExistingMetaEntity = context.getMetaEntity( fqn );
+ }
+ else if ( TypeUtils.isAnnotationMirrorOfType( mirror, MappedSuperclass.class )
+ || TypeUtils.isAnnotationMirrorOfType( mirror, Embeddable.class ) ) {
+ alreadyExistingMetaEntity = context.getMetaSuperclassOrEmbeddable( fqn );
+ }
+ return alreadyExistingMetaEntity;
+ }
+
+ private void addMetaEntityToContext(AnnotationMirror mirror, AnnotationMetaEntity metaEntity) {
+ if ( TypeUtils.isAnnotationMirrorOfType( mirror, Entity.class ) ) {
+ context.addMetaEntity( metaEntity.getQualifiedName(), metaEntity );
+ }
+ else if ( TypeUtils.isAnnotationMirrorOfType( mirror, MappedSuperclass.class ) ) {
+ context.addMetaSuperclassOrEmbeddable( metaEntity.getQualifiedName(), metaEntity );
+ }
+ else if ( TypeUtils.isAnnotationMirrorOfType( mirror, Embeddable.class ) ) {
+ context.addMetaSuperclassOrEmbeddable( metaEntity.getQualifiedName(), metaEntity );
+ }
+ }
+
+
+ class ContainsAttributeTypeVisitor extends SimpleTypeVisitor6 {
+
+ private Context context;
+ private TypeElement type;
+
+ ContainsAttributeTypeVisitor(TypeElement elem, Context context) {
+ this.context = context;
+ this.type = elem;
+ }
+
+ @Override
+ public Boolean visitDeclared(DeclaredType declaredType, Element element) {
+ TypeElement returnedElement = ( TypeElement ) context.getTypeUtils().asElement( declaredType );
+
+ String fqNameOfReturnType = returnedElement.getQualifiedName().toString();
+ String collection = Constants.COLLECTIONS.get( fqNameOfReturnType );
+ if ( collection != null ) {
+ TypeMirror collectionElementType = TypeUtils.getCollectionElementType(
+ declaredType, fqNameOfReturnType, null, context
+ );
+ returnedElement = ( TypeElement ) context.getTypeUtils().asElement( collectionElementType );
+ }
+
+ if ( type.getQualifiedName().toString().equals( returnedElement.getQualifiedName().toString() ) ) {
+ return Boolean.TRUE;
+ }
+ else {
+ return Boolean.FALSE;
+ }
+ }
+
+ @Override
+ public Boolean visitExecutable(ExecutableType t, Element element) {
+ if ( !element.getKind().equals( ElementKind.METHOD ) ) {
+ return Boolean.FALSE;
+ }
+
+ String string = element.getSimpleName().toString();
+ if ( !StringUtil.isPropertyName( string ) ) {
+ return Boolean.FALSE;
+ }
+
+ TypeMirror returnType = t.getReturnType();
+ return returnType.accept( this, element );
}
}
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationEmbeddable.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationEmbeddable.java
new file mode 100644
index 0000000000..074d14e814
--- /dev/null
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationEmbeddable.java
@@ -0,0 +1,69 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.annotation;
+
+import java.util.List;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+import org.hibernate.jpamodelgen.Context;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
+
+/**
+ * @author Max Andersen
+ * @author Hardy Ferentschik
+ * @author Emmanuel Bernard
+ */
+public class AnnotationEmbeddable extends AnnotationMetaEntity {
+
+ // Embeddables needs to be lazily initialized since the access type be determined by the class which is embedding
+ // the entity. This might not be known until annotations are processed.
+ // Also note, that if two different classes with different access types embed this entity the access type of the
+ // embeddable will be the one of the last embedding entity processed. The result is not determined (that's ok
+ // according to the spec)
+ private boolean initialized;
+
+ public AnnotationEmbeddable(TypeElement element, Context context) {
+ super( element, context, true );
+ }
+
+ public List getMembers() {
+ if ( !initialized ) {
+ context.logMessage( Diagnostic.Kind.OTHER, "Entity " + getQualifiedName() + "was lazily initialised." );
+ init();
+ initialized = true;
+ }
+ return super.getMembers();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "AnnotationEmbeddable" );
+ sb.append( "{element=" ).append( element );
+ sb.append( ", members=" );
+ if ( initialized ) {
+ sb.append( members );
+ }
+ else {
+ sb.append( "[un-initalized]" );
+ }
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java
index 648ee6f565..04562bca6e 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java
@@ -22,7 +22,7 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.util.Elements;
-import org.hibernate.jpamodelgen.MetaAttribute;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
/**
* @author Max Andersen
@@ -47,7 +47,7 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute {
}
public String getPropertyName() {
- Elements elementsUtil = parent.getContext().getProcessingEnvironment().getElementUtils();
+ Elements elementsUtil = parent.getContext().getElementUtils();
if ( element.getKind() == ElementKind.FIELD ) {
return element.getSimpleName().toString();
}
@@ -71,4 +71,14 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute {
public String getTypeDeclaration() {
return type;
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "AnnotationMetaAttribute" );
+ sb.append( "{element=" ).append( element );
+ sb.append( ", type='" ).append( type ).append( '\'' );
+ sb.append( '}' );
+ return sb.toString();
+ }
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaCollection.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaCollection.java
index 326caae0ef..c1764e35cc 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaCollection.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaCollection.java
@@ -19,7 +19,7 @@ package org.hibernate.jpamodelgen.annotation;
import javax.lang.model.element.Element;
-import org.hibernate.jpamodelgen.MetaCollection;
+import org.hibernate.jpamodelgen.model.MetaCollection;
/**
* @author Max Andersen
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java
index 0db7c62941..3d69c394d3 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java
@@ -18,6 +18,7 @@
package org.hibernate.jpamodelgen.annotation;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -35,31 +36,27 @@ import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleTypeVisitor6;
-import javax.persistence.Access;
import javax.persistence.AccessType;
+import javax.persistence.Basic;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
-import javax.persistence.Embedded;
-import javax.persistence.EmbeddedId;
-import javax.persistence.Entity;
-import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyClass;
-import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.tools.Diagnostic;
+import org.hibernate.jpamodelgen.AccessTypeInformation;
import org.hibernate.jpamodelgen.Context;
-import org.hibernate.jpamodelgen.ImportContext;
import org.hibernate.jpamodelgen.ImportContextImpl;
-import org.hibernate.jpamodelgen.MetaAttribute;
-import org.hibernate.jpamodelgen.MetaEntity;
-import org.hibernate.jpamodelgen.MetaModelGenerationException;
+import org.hibernate.jpamodelgen.model.ImportContext;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
+import org.hibernate.jpamodelgen.model.MetaEntity;
+import org.hibernate.jpamodelgen.util.Constants;
+import org.hibernate.jpamodelgen.util.StringUtil;
import org.hibernate.jpamodelgen.util.TypeUtils;
/**
@@ -69,32 +66,25 @@ import org.hibernate.jpamodelgen.util.TypeUtils;
*/
public class AnnotationMetaEntity implements MetaEntity {
- private static final String DEFAULT_ANNOTATION_PARAMETER_NAME = "value";
- static Map COLLECTIONS = new HashMap();
+ protected final ImportContext importContext;
+ protected final TypeElement element;
+ protected final Map members;
+ protected Context context;
- static {
- COLLECTIONS.put( "java.util.Collection", "javax.persistence.metamodel.CollectionAttribute" );
- COLLECTIONS.put( "java.util.Set", "javax.persistence.metamodel.SetAttribute" );
- COLLECTIONS.put( "java.util.List", "javax.persistence.metamodel.ListAttribute" );
- COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" );
- }
-
- private final TypeElement element;
- private final ImportContext importContext;
- private Context context;
- //used to propagate the access type of the root entity over to subclasses, superclasses and embeddable
- private AccessType defaultAccessTypeForHierarchy;
- private AccessType defaultAccessTypeForElement;
+ private AccessTypeInformation entityAccessTypeInfo;
public AnnotationMetaEntity(TypeElement element, Context context) {
- this.element = element;
- this.context = context;
- importContext = new ImportContextImpl( getPackageName() );
+ this( element, context, false );
}
- public AnnotationMetaEntity(TypeElement element, Context context, AccessType accessType) {
- this( element, context );
- this.defaultAccessTypeForHierarchy = accessType;
+ protected AnnotationMetaEntity(TypeElement element, Context context, boolean lazilyInitialised) {
+ this.element = element;
+ this.context = context;
+ this.members = new HashMap();
+ this.importContext = new ImportContextImpl( getPackageName() );
+ if ( !lazilyInitialised ) {
+ init();
+ }
}
public Context getContext() {
@@ -110,413 +100,65 @@ public class AnnotationMetaEntity implements MetaEntity {
}
public String getPackageName() {
- PackageElement packageOf = context.getProcessingEnvironment().getElementUtils().getPackageOf( element );
- return context.getProcessingEnvironment().getElementUtils().getName( packageOf.getQualifiedName() ).toString();
+ PackageElement packageOf = context.getElementUtils().getPackageOf( element );
+ return context.getElementUtils().getName( packageOf.getQualifiedName() ).toString();
}
public List getMembers() {
- List membersFound = new ArrayList();
- final AccessType elementAccessType = getAccessTypeForElement();
-
- List extends Element> fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() );
- addPersistentMembers( membersFound, elementAccessType, fieldsOfClass, AccessType.FIELD );
-
- List extends Element> methodsOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
- addPersistentMembers( membersFound, elementAccessType, methodsOfClass, AccessType.PROPERTY );
-
- //process superclasses
- for ( TypeElement superclass = TypeUtils.getSuperclassTypeElement( element );
- superclass != null;
- superclass = TypeUtils.getSuperclassTypeElement( superclass ) ) {
- if ( TypeUtils.containsAnnotation( superclass, Entity.class ) ) {
- break; //will be handled or has been handled already
- }
- else if ( TypeUtils.containsAnnotation( superclass, MappedSuperclass.class ) ) {
- //FIXME use the class default access type
- context.processElement( superclass, defaultAccessTypeForHierarchy );
- }
- }
- return membersFound;
+ return new ArrayList( members.values() );
}
- private void addPersistentMembers(
- List membersFound,
- AccessType elementAccessType,
- List extends Element> membersOfClass,
- AccessType membersKind) {
- AccessType explicitAccessType;
- if ( elementAccessType == membersKind ) {
- //all membersKind considered
- explicitAccessType = null;
- }
- else {
- //use membersKind only if marked with @Access(membersKind)
- explicitAccessType = membersKind;
- }
- for ( Element memberOfClass : membersOfClass ) {
-
- TypeVisitor visitor = new TypeVisitor( this, explicitAccessType );
- AnnotationMetaAttribute result = memberOfClass.asType().accept( visitor, memberOfClass );
- if ( result != null ) {
- membersFound.add( result );
- }
- }
+ @Override
+ public boolean isMetaComplete() {
+ return false;
}
- private AccessType getAccessTypeForElement() {
-
- //get local strategy
- AccessType accessType = getAccessTypeForClass( element );
- if ( accessType == null ) {
- accessType = this.defaultAccessTypeForHierarchy;
+ public void mergeInMembers(Collection attributes) {
+ for ( MetaAttribute attribute : attributes ) {
+ members.put( attribute.getPropertyName(), attribute );
}
- if ( accessType == null ) {
- //we don't know if an entity go up
- //
- //superclasses are always treated after their entities
- //and their access type are discovered
- //FIXME is it really true if only the superclass is changed
- TypeElement superClass = element;
- do {
- superClass = TypeUtils.getSuperclassTypeElement( superClass );
- if ( superClass != null ) {
- if ( TypeUtils.containsAnnotation( superClass, Entity.class, MappedSuperclass.class ) ) {
- //FIXME make it work for XML
- AccessType superClassAccessType = getAccessTypeForClass( superClass );
- //we've reach the root entity and resolved Ids
- if ( superClassAccessType != null && defaultAccessTypeForHierarchy != null ) {
- break; //we've found it
- }
- }
- else {
- break; //neither @Entity nor @MappedSuperclass
- }
- }
- }
- while ( superClass != null );
- }
-
- if ( accessType == null ) {
- accessType = AccessType.PROPERTY; //default to property
- this.defaultAccessTypeForElement = accessType;
- }
- //this is a subclass so caching is OK
- //this.defaultAccessTypeForHierarchy = accessType;
- context.addAccessType( this.element, accessType );
- this.defaultAccessTypeForElement = accessType;
- return accessType;
- }
-
- private AccessType getAccessTypeForClass(TypeElement searchedElement) {
- context.logMessage( Diagnostic.Kind.OTHER, "check class " + searchedElement );
- AccessType accessType = context.getAccessType( searchedElement );
-
- if ( defaultAccessTypeForHierarchy == null ) {
- this.defaultAccessTypeForHierarchy = context.getDefaultAccessTypeForHerarchy( searchedElement );
- }
- if ( accessType != null ) {
- context.logMessage( Diagnostic.Kind.OTHER, "Found in cache" + searchedElement + ":" + accessType );
- return accessType;
- }
-
- /**
- * when forcing access type, we can only override the defaultAccessTypeForHierarchy
- * if we are the entity root (identified by having @Id or @EmbeddedId
- */
- AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( searchedElement );
- if ( forcedAccessType != null ) {
- context.logMessage( Diagnostic.Kind.OTHER, "access type " + searchedElement + ":" + forcedAccessType );
- context.addAccessType( searchedElement, forcedAccessType );
- }
-
- //continue nevertheless to check if we are root and if defaultAccessTypeForHierarchy
- //should be overridden
- if ( forcedAccessType == null || defaultAccessTypeForHierarchy == null ) {
- List extends Element> myMembers = searchedElement.getEnclosedElements();
- for ( Element subElement : myMembers ) {
- List extends AnnotationMirror> entityAnnotations =
- context.getProcessingEnvironment().getElementUtils().getAllAnnotationMirrors( subElement );
-
- for ( Object entityAnnotation : entityAnnotations ) {
- AnnotationMirror annotationMirror = ( AnnotationMirror ) entityAnnotation;
-
- //FIXME consider XML
- if ( TypeUtils.isAnnotationMirrorOfType( annotationMirror, Id.class )
- || TypeUtils.isAnnotationMirrorOfType( annotationMirror, EmbeddedId.class ) ) {
- context.logMessage( Diagnostic.Kind.OTHER, "Found id on" + searchedElement );
- final ElementKind kind = subElement.getKind();
- if ( kind == ElementKind.FIELD || kind == ElementKind.METHOD ) {
- accessType = kind == ElementKind.FIELD ? AccessType.FIELD : AccessType.PROPERTY;
- //FIXME enlever in niveau
- if ( defaultAccessTypeForHierarchy == null ) {
- this.defaultAccessTypeForHierarchy = context.getDefaultAccessTypeForHerarchy(
- searchedElement
- );
- //we've discovered the class hierarchy, let's cache it
- if ( defaultAccessTypeForHierarchy == null ) {
- this.defaultAccessTypeForHierarchy = accessType;
- context.addAccessTypeForHierarchy( searchedElement, defaultAccessTypeForHierarchy );
- //FIXME should we add
- //context.addAccessTypeForHierarchy( element, defaultAccessTypeForHierarchy );
- }
- }
- if ( forcedAccessType == null ) {
- context.addAccessType( searchedElement, accessType );
- context.logMessage(
- Diagnostic.Kind.OTHER, "access type " + searchedElement + ":" + accessType
- );
- return accessType;
- }
- else {
- return forcedAccessType;
- }
- }
- }
- }
- }
- }
- return forcedAccessType;
- }
-
- private AccessType determineAnnotationSpecifiedAccessType(Element element) {
- final AnnotationMirror accessAnnotationMirror = TypeUtils.getAnnotationMirror( element, Access.class );
- AccessType forcedAccessType = null;
- if ( accessAnnotationMirror != null ) {
- Element accessElement = ( Element ) TypeUtils.getAnnotationValue(
- accessAnnotationMirror,
- DEFAULT_ANNOTATION_PARAMETER_NAME
- );
- if ( accessElement.getKind().equals( ElementKind.ENUM_CONSTANT ) ) {
- if ( accessElement.getSimpleName().toString().equals( AccessType.PROPERTY.toString() ) ) {
- forcedAccessType = AccessType.PROPERTY;
- }
- else if ( accessElement.getSimpleName().toString().equals( AccessType.FIELD.toString() ) ) {
- forcedAccessType = AccessType.FIELD;
-
- }
- else {
- context.logMessage( Diagnostic.Kind.ERROR, "Unexpected type for access type" );
- }
- }
- }
- return forcedAccessType;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
- sb.append( "MetaEntity" );
+ sb.append( "AnnotationMetaEntity" );
sb.append( "{element=" ).append( element );
+ sb.append( ", members=" ).append( members );
sb.append( '}' );
return sb.toString();
}
- class TypeVisitor extends SimpleTypeVisitor6 {
-
- AnnotationMetaEntity parent;
-
- /*
- * If {@code explicitAccessType == null}, process all members as implicit. If {@code explicitAccessType != null}
- * only process members marked as {@code @Access(explicitAccessType)}.
- */
- private AccessType explicitAccessType;
-
- TypeVisitor(AnnotationMetaEntity parent, AccessType explicitAccessType) {
- this.parent = parent;
- this.explicitAccessType = explicitAccessType;
- }
-
- @Override
- protected AnnotationMetaAttribute defaultAction(TypeMirror e, Element p) {
- return super.defaultAction( e, p );
- }
-
- @Override
- public AnnotationMetaAttribute visitPrimitive(PrimitiveType t, Element element) {
- if ( isPersistent( element ) ) {
- return new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
- }
- else {
- return null;
- }
- }
-
- @Override
- public AnnotationMetaAttribute visitArray(ArrayType t, Element element) {
- if ( isPersistent( element ) ) {
- return new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
- }
- else {
- return null;
- }
- }
-
- private boolean isPersistent(Element element) {
- //FIXME consider XML
- boolean correctAccessType = false;
- if ( this.explicitAccessType == null ) {
- correctAccessType = true;
- }
- else {
- AccessType annotationAccessType = determineAnnotationSpecifiedAccessType( element );
- if ( explicitAccessType.equals( annotationAccessType ) ) {
- correctAccessType = true;
- }
- }
- return correctAccessType
- && !TypeUtils.containsAnnotation( element, Transient.class )
- && !element.getModifiers().contains( Modifier.TRANSIENT )
- && !element.getModifiers().contains( Modifier.STATIC );
-
- }
-
- @Override
- public AnnotationMetaAttribute visitDeclared(DeclaredType declaredType, Element element) {
- if ( isPersistent( element ) ) {
- TypeElement returnedElement = ( TypeElement ) context.getProcessingEnvironment()
- .getTypeUtils()
- .asElement( declaredType );
- // WARNING: .toString() is necessary here since Name equals does not compare to String
- String fqNameOfReturnType = returnedElement.getQualifiedName().toString();
- String collection = COLLECTIONS.get( fqNameOfReturnType );
- String targetEntity = getTargetEntity( element.getAnnotationMirrors() );
- if ( collection != null ) {
- if ( TypeUtils.containsAnnotation( element, ElementCollection.class ) ) {
- String explicitTargetEntity = getTargetEntity( element.getAnnotationMirrors() );
- TypeMirror collectionElementType = getCollectionElementType(
- declaredType, fqNameOfReturnType, explicitTargetEntity
- );
- final TypeElement collectionElement = ( TypeElement ) context.getProcessingEnvironment()
- .getTypeUtils()
- .asElement( collectionElementType );
- this.parent.context.processElement(
- collectionElement,
- this.parent.defaultAccessTypeForElement
- );
- }
- if ( collection.equals( "javax.persistence.metamodel.MapAttribute" ) ) {
- return createAnnotationMetaAttributeForMap( declaredType, element, collection, targetEntity );
- }
- else {
- return new AnnotationMetaCollection(
- parent, element, collection, getElementType( declaredType, targetEntity )
- );
- }
- }
- else {
- //FIXME Consider XML
- if ( TypeUtils.containsAnnotation( returnedElement, Embedded.class, Embeddable.class ) ) {
- this.parent.context.processElement(
- returnedElement,
- this.parent.defaultAccessTypeForElement
- );
- }
- return new AnnotationMetaSingleAttribute(
- parent, element, returnedElement.getQualifiedName().toString()
- );
- }
- }
- else {
- return null;
- }
- }
-
- private AnnotationMetaAttribute createAnnotationMetaAttributeForMap(DeclaredType declaredType, Element element, String collection, String targetEntity) {
- String keyType;
- if ( TypeUtils.containsAnnotation( element, MapKeyClass.class ) ) {
- TypeMirror typeMirror = ( TypeMirror ) TypeUtils.getAnnotationValue(
- TypeUtils.getAnnotationMirror(
- element, MapKeyClass.class
- ), DEFAULT_ANNOTATION_PARAMETER_NAME
- );
- keyType = typeMirror.toString();
- }
- else {
- keyType = getKeyType( declaredType );
- }
- return new AnnotationMetaMap(
- parent,
- element,
- collection,
- keyType,
- getElementType( declaredType, targetEntity )
- );
- }
-
- private TypeMirror getCollectionElementType(DeclaredType t, String fqNameOfReturnedType, String explicitTargetEntityName) {
- TypeMirror collectionElementType;
- if ( explicitTargetEntityName != null ) {
- Elements elements = context.getProcessingEnvironment().getElementUtils();
- TypeElement element = elements.getTypeElement( explicitTargetEntityName );
- collectionElementType = element.asType();
- }
- else {
- List extends TypeMirror> typeArguments = t.getTypeArguments();
- if ( typeArguments.size() == 0 ) {
- throw new MetaModelGenerationException( "Unable to determine collection type for property in " + getSimpleName() );
- }
- else if ( Map.class.getCanonicalName().equals( fqNameOfReturnedType ) ) {
- collectionElementType = t.getTypeArguments().get( 1 );
- }
- else {
- collectionElementType = t.getTypeArguments().get( 0 );
- }
- }
- return collectionElementType;
- }
-
- @Override
- public AnnotationMetaAttribute visitExecutable(ExecutableType t, Element p) {
- if ( !p.getKind().equals( ElementKind.METHOD ) ) {
- return null;
+ private void addPersistentMembers(List extends Element> membersOfClass, AccessType membersKind) {
+ for ( Element memberOfClass : membersOfClass ) {
+ AccessType forcedAccessType = TypeUtils.determineAnnotationSpecifiedAccessType( memberOfClass );
+ if ( entityAccessTypeInfo.getAccessType() != membersKind && forcedAccessType == null ) {
+ continue;
}
- String string = p.getSimpleName().toString();
- if ( string.startsWith( "get" ) || string.startsWith( "is" ) || string.startsWith( "has" ) ) {
- TypeMirror returnType = t.getReturnType();
- return returnType.accept( this, p );
+ if ( TypeUtils.containsAnnotation( memberOfClass, Transient.class )
+ || memberOfClass.getModifiers().contains( Modifier.TRANSIENT )
+ || memberOfClass.getModifiers().contains( Modifier.STATIC ) ) {
+ continue;
}
- else {
- return null;
+
+ TypeVisitor visitor = new TypeVisitor( this );
+ AnnotationMetaAttribute result = memberOfClass.asType().accept( visitor, memberOfClass );
+ if ( result != null ) {
+ members.put( result.getPropertyName(), result );
}
}
}
- /**
- * @param annotations list of annotation mirrors.
- *
- * @return target entity class name as string or {@code null} if no targetEntity is here or if equals to void
- */
- private String getTargetEntity(List extends AnnotationMirror> annotations) {
+ protected void init() {
+ TypeUtils.determineAccessTypeForHierarchy( element, context );
+ entityAccessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
- String fullyQualifiedTargetEntityName = null;
- for ( AnnotationMirror mirror : annotations ) {
- if ( TypeUtils.isAnnotationMirrorOfType( mirror, ElementCollection.class ) ) {
- fullyQualifiedTargetEntityName = getFullyQualifiedClassNameOfTargetEntity( mirror, "targetClass" );
- }
- else if ( TypeUtils.isAnnotationMirrorOfType( mirror, OneToMany.class )
- || TypeUtils.isAnnotationMirrorOfType( mirror, ManyToMany.class )
- || TypeUtils.isAnnotationMirrorOfType( mirror, ManyToOne.class )
- || TypeUtils.isAnnotationMirrorOfType( mirror, OneToOne.class ) ) {
- fullyQualifiedTargetEntityName = getFullyQualifiedClassNameOfTargetEntity( mirror, "targetEntity" );
- }
- }
- return fullyQualifiedTargetEntityName;
- }
+ List extends Element> fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() );
+ addPersistentMembers( fieldsOfClass, AccessType.FIELD );
- private String getFullyQualifiedClassNameOfTargetEntity(AnnotationMirror mirror, String parameterName) {
- assert mirror != null;
- assert parameterName != null;
-
- String targetEntityName = null;
- Object parameterValue = TypeUtils.getAnnotationValue( mirror, parameterName );
- if ( parameterValue != null ) {
- TypeMirror parameterType = ( TypeMirror ) parameterValue;
- if ( !parameterType.getKind().equals( TypeKind.VOID ) ) {
- targetEntityName = parameterType.toString();
- }
- }
- return targetEntityName;
+ List extends Element> methodsOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
+ addPersistentMembers( methodsOfClass, AccessType.PROPERTY );
}
public String generateImports() {
@@ -539,29 +181,253 @@ public class AnnotationMetaEntity implements MetaEntity {
return element;
}
- private String getKeyType(DeclaredType t) {
- return TypeUtils.extractClosestRealTypeAsString( t.getTypeArguments().get( 0 ), context );
+ class TypeVisitor extends SimpleTypeVisitor6 {
+ AnnotationMetaEntity parent;
+
+ TypeVisitor(AnnotationMetaEntity parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public AnnotationMetaAttribute visitPrimitive(PrimitiveType t, Element element) {
+ return new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
+ }
+
+ @Override
+ public AnnotationMetaAttribute visitArray(ArrayType t, Element element) {
+ // METAGEN-2 - For now we handle arrays as SingularAttribute
+ // The code below is an attempt to be closer to the spec and only allow byte[], Byte[], char[] and Character[]
+// AnnotationMetaSingleAttribute attribute = null;
+// TypeMirror componentMirror = t.getComponentType();
+// if ( TypeKind.CHAR.equals( componentMirror.getKind() )
+// || TypeKind.BYTE.equals( componentMirror.getKind() ) ) {
+// attribute = new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
+// }
+// else if ( TypeKind.DECLARED.equals( componentMirror.getKind() ) ) {
+// TypeElement componentElement = ( TypeElement ) context.getProcessingEnvironment()
+// .getTypeUtils()
+// .asElement( componentMirror );
+// if ( BASIC_ARRAY_TYPES.contains( componentElement.getQualifiedName().toString() ) ) {
+// attribute = new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
+// }
+// }
+// return attribute;
+ return new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
+ }
+
+ @Override
+ public AnnotationMetaAttribute visitDeclared(DeclaredType declaredType, Element element) {
+ TypeElement returnedElement = ( TypeElement ) context.getTypeUtils().asElement( declaredType );
+ // WARNING: .toString() is necessary here since Name equals does not compare to String
+ String fqNameOfReturnType = returnedElement.getQualifiedName().toString();
+ String collection = Constants.COLLECTIONS.get( fqNameOfReturnType );
+ String targetEntity = getTargetEntity( element.getAnnotationMirrors() );
+ if ( collection != null ) {
+ if ( TypeUtils.containsAnnotation( element, ElementCollection.class ) ) {
+ String explicitTargetEntity = getTargetEntity( element.getAnnotationMirrors() );
+ TypeMirror collectionElementType = TypeUtils.getCollectionElementType(
+ declaredType, fqNameOfReturnType, explicitTargetEntity, context
+ );
+ final TypeElement collectionElement = ( TypeElement ) context.getTypeUtils()
+ .asElement( collectionElementType );
+ AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( collectionElement.getQualifiedName().toString() );
+ if ( accessTypeInfo == null ) {
+ AccessType explicitAccessType = TypeUtils.determineAnnotationSpecifiedAccessType(
+ collectionElement
+ );
+ accessTypeInfo = new AccessTypeInformation(
+ collectionElement.getQualifiedName().toString(),
+ explicitAccessType,
+ entityAccessTypeInfo.getAccessType()
+ );
+ context.addAccessTypeInformation(
+ collectionElement.getQualifiedName().toString(), accessTypeInfo
+ );
+ }
+ else {
+ accessTypeInfo.setDefaultAccessType( entityAccessTypeInfo.getAccessType() );
+ }
+ }
+ if ( collection.equals( "javax.persistence.metamodel.MapAttribute" ) ) {
+ return createAnnotationMetaAttributeForMap( declaredType, element, collection, targetEntity );
+ }
+ else {
+ return new AnnotationMetaCollection(
+ parent, element, collection, getElementType( declaredType, targetEntity )
+ );
+ }
+ }
+ else {
+ if ( isBasicAttribute( element, returnedElement ) ) {
+ return new AnnotationMetaSingleAttribute(
+ parent, element, returnedElement.getQualifiedName().toString()
+ );
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public AnnotationMetaAttribute visitExecutable(ExecutableType t, Element p) {
+ if ( !p.getKind().equals( ElementKind.METHOD ) ) {
+ return null;
+ }
+
+ String string = p.getSimpleName().toString();
+ if ( !StringUtil.isPropertyName( string ) ) {
+ return null;
+ }
+
+ TypeMirror returnType = t.getReturnType();
+ return returnType.accept( this, p );
+ }
+
+ private boolean isBasicAttribute(Element element, Element returnedElement) {
+ if ( TypeUtils.containsAnnotation( element, Basic.class )
+ || TypeUtils.containsAnnotation( element, OneToOne.class )
+ || TypeUtils.containsAnnotation( element, ManyToOne.class ) ) {
+ return true;
+ }
+
+ BasicAttributeVisitor basicVisitor = new BasicAttributeVisitor();
+ return returnedElement.asType().accept( basicVisitor, returnedElement );
+ }
+
+ private AnnotationMetaAttribute createAnnotationMetaAttributeForMap(DeclaredType declaredType, Element element, String collection, String targetEntity) {
+ String keyType;
+ if ( TypeUtils.containsAnnotation( element, MapKeyClass.class ) ) {
+ TypeMirror typeMirror = ( TypeMirror ) TypeUtils.getAnnotationValue(
+ TypeUtils.getAnnotationMirror(
+ element, MapKeyClass.class
+ ), TypeUtils.DEFAULT_ANNOTATION_PARAMETER_NAME
+ );
+ keyType = typeMirror.toString();
+ }
+ else {
+ keyType = getKeyType( declaredType );
+ }
+ return new AnnotationMetaMap(
+ parent,
+ element,
+ collection,
+ keyType,
+ getElementType( declaredType, targetEntity )
+ );
+ }
+
+ private String getElementType(DeclaredType declaredType, String targetEntity) {
+ if ( targetEntity != null ) {
+ return targetEntity;
+ }
+ final List extends TypeMirror> mirrors = declaredType.getTypeArguments();
+ if ( mirrors.size() == 1 ) {
+ final TypeMirror type = mirrors.get( 0 );
+ return TypeUtils.extractClosestRealTypeAsString( type, context );
+ }
+ else if ( mirrors.size() == 2 ) {
+ return TypeUtils.extractClosestRealTypeAsString( mirrors.get( 1 ), context );
+ }
+ else {
+ //for 0 or many
+ //0 is expected, many is not
+ if ( mirrors.size() > 2 ) {
+ context.logMessage(
+ Diagnostic.Kind.WARNING, "Unable to find the closest solid type" + declaredType
+ );
+ }
+ return "?";
+ }
+ }
+
+ private String getKeyType(DeclaredType t) {
+ List extends TypeMirror> typeArguments = t.getTypeArguments();
+ if ( typeArguments.size() == 0 ) {
+ context.logMessage( Diagnostic.Kind.ERROR, "Entity: " + getQualifiedName() );
+ }
+ return TypeUtils.extractClosestRealTypeAsString( typeArguments.get( 0 ), context );
+ }
+
+ /**
+ * @param annotations list of annotation mirrors.
+ *
+ * @return target entity class name as string or {@code null} if no targetEntity is here or if equals to void
+ */
+ private String getTargetEntity(List extends AnnotationMirror> annotations) {
+
+ String fullyQualifiedTargetEntityName = null;
+ for ( AnnotationMirror mirror : annotations ) {
+ if ( TypeUtils.isAnnotationMirrorOfType( mirror, ElementCollection.class ) ) {
+ fullyQualifiedTargetEntityName = getFullyQualifiedClassNameOfTargetEntity( mirror, "targetClass" );
+ }
+ else if ( TypeUtils.isAnnotationMirrorOfType( mirror, OneToMany.class )
+ || TypeUtils.isAnnotationMirrorOfType( mirror, ManyToMany.class )
+ || TypeUtils.isAnnotationMirrorOfType( mirror, ManyToOne.class )
+ || TypeUtils.isAnnotationMirrorOfType( mirror, OneToOne.class ) ) {
+ fullyQualifiedTargetEntityName = getFullyQualifiedClassNameOfTargetEntity( mirror, "targetEntity" );
+ }
+ }
+ return fullyQualifiedTargetEntityName;
+ }
+
+ private String getFullyQualifiedClassNameOfTargetEntity(AnnotationMirror mirror, String parameterName) {
+ assert mirror != null;
+ assert parameterName != null;
+
+ String targetEntityName = null;
+ Object parameterValue = TypeUtils.getAnnotationValue( mirror, parameterName );
+ if ( parameterValue != null ) {
+ TypeMirror parameterType = ( TypeMirror ) parameterValue;
+ if ( !parameterType.getKind().equals( TypeKind.VOID ) ) {
+ targetEntityName = parameterType.toString();
+ }
+ }
+ return targetEntityName;
+ }
}
- private String getElementType(DeclaredType declaredType, String targetEntity) {
- if ( targetEntity != null ) {
- return targetEntity;
+ /**
+ * Checks whether the visited type is a basic attribute according to the JPA 2 spec
+ * ( section 2.8 Mapping Defaults for Non-Relationship Fields or Properties)
+ */
+ class BasicAttributeVisitor extends SimpleTypeVisitor6 {
+ @Override
+ public Boolean visitPrimitive(PrimitiveType t, Element element) {
+ return Boolean.TRUE;
}
- final List extends TypeMirror> mirrors = declaredType.getTypeArguments();
- if ( mirrors.size() == 1 ) {
- final TypeMirror type = mirrors.get( 0 );
- return TypeUtils.extractClosestRealTypeAsString( type, context );
+
+ @Override
+ public Boolean visitArray(ArrayType t, Element element) {
+ TypeMirror componentMirror = t.getComponentType();
+ TypeElement componentElement = ( TypeElement ) context.getTypeUtils().asElement( componentMirror );
+
+ return Constants.BASIC_ARRAY_TYPES.contains( componentElement.getQualifiedName().toString() );
}
- else if ( mirrors.size() == 2 ) {
- return TypeUtils.extractClosestRealTypeAsString( mirrors.get( 1 ), context );
- }
- else {
- //for 0 or many
- //0 is expected, many is not
- if ( mirrors.size() > 2 ) {
- context.logMessage( Diagnostic.Kind.WARNING, "Unable to find the closest solid type" + declaredType );
+
+ @Override
+ public Boolean visitDeclared(DeclaredType declaredType, Element element) {
+ if ( ElementKind.ENUM.equals( element.getKind() ) ) {
+ return Boolean.TRUE;
}
- return "?";
+
+ if ( ElementKind.CLASS.equals( element.getKind() ) ) {
+ TypeElement typeElement = ( ( TypeElement ) element );
+ String typeName = typeElement.getQualifiedName().toString();
+ if ( Constants.BASIC_TYPES.contains( typeName ) ) {
+ return Boolean.TRUE;
+ }
+ if ( TypeUtils.containsAnnotation( element, Embeddable.class ) ) {
+ return Boolean.TRUE;
+ }
+ for ( TypeMirror mirror : typeElement.getInterfaces() ) {
+ TypeElement interfaceElement = ( TypeElement ) context.getTypeUtils().asElement( mirror );
+ if ( "java.io.Serializable".equals( interfaceElement.getQualifiedName().toString() ) ) {
+ return Boolean.TRUE;
+ }
+ }
+ }
+ return Boolean.FALSE;
}
}
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaSingleAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaSingleAttribute.java
index 05937939b3..6376bff6a8 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaSingleAttribute.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaSingleAttribute.java
@@ -19,7 +19,7 @@ package org.hibernate.jpamodelgen.annotation;
import javax.lang.model.element.Element;
-import org.hibernate.jpamodelgen.MetaSingleAttribute;
+import org.hibernate.jpamodelgen.model.MetaSingleAttribute;
/**
* @author Max Andersen
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/ImportContext.java
similarity index 94%
rename from tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java
rename to tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/ImportContext.java
index a9c2b6fd48..151f64d2b4 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ImportContext.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/ImportContext.java
@@ -15,10 +15,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.hibernate.jpamodelgen;
+package org.hibernate.jpamodelgen.model;
/**
- *
* @author Max Andersen
* @author Hardy Ferentschik
* @author Emmanuel Bernard
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaAttribute.java
similarity index 95%
rename from tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java
rename to tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaAttribute.java
index 4ae7cf4b66..fc072f7fb9 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaAttribute.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaAttribute.java
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.hibernate.jpamodelgen;
+package org.hibernate.jpamodelgen.model;
/**
* @author Hardy Ferentschik
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaCollection.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaCollection.java
similarity index 95%
rename from tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaCollection.java
rename to tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaCollection.java
index 1e592c6f71..64df6447b9 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaCollection.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaCollection.java
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.hibernate.jpamodelgen;
+package org.hibernate.jpamodelgen.model;
/**
* @author Hardy Ferentschik
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaEntity.java
similarity index 75%
rename from tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaEntity.java
rename to tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaEntity.java
index 7b42c9e118..f30ad4da26 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaEntity.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaEntity.java
@@ -15,31 +15,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.hibernate.jpamodelgen;
+package org.hibernate.jpamodelgen.model;
+import java.util.List;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
-import java.util.List;
/**
* @author Hardy Ferentschik
*/
public interface MetaEntity extends ImportContext {
- String getSimpleName();
+ String getSimpleName();
- String getQualifiedName();
+ String getQualifiedName();
- String getPackageName();
+ String getPackageName();
- List getMembers();
+ List getMembers();
- String generateImports();
+ String generateImports();
- String importType(String fqcn);
+ String importType(String fqcn);
- String staticImport(String fqcn, String member);
+ String staticImport(String fqcn, String member);
- String importType(Name qualifiedName);
+ String importType(Name qualifiedName);
TypeElement getTypeElement();
+
+ boolean isMetaComplete();
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaSingleAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaSingleAttribute.java
similarity index 95%
rename from tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaSingleAttribute.java
rename to tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaSingleAttribute.java
index 36e960e712..69107aee8d 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/MetaSingleAttribute.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/model/MetaSingleAttribute.java
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.hibernate.jpamodelgen;
+package org.hibernate.jpamodelgen.model;
/**
* @author Hardy Ferentschik
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/Constants.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/Constants.java
new file mode 100644
index 0000000000..e792b7e2a4
--- /dev/null
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/Constants.java
@@ -0,0 +1,69 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Constants {
+ public static Map COLLECTIONS = new HashMap();
+
+ static {
+ COLLECTIONS.put( "java.util.Collection", "javax.persistence.metamodel.CollectionAttribute" );
+ COLLECTIONS.put( "java.util.Set", "javax.persistence.metamodel.SetAttribute" );
+ COLLECTIONS.put( "java.util.List", "javax.persistence.metamodel.ListAttribute" );
+ COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" );
+ }
+
+ public static List BASIC_TYPES = new ArrayList();
+
+ static {
+ BASIC_TYPES.add( "java.lang.String" );
+ BASIC_TYPES.add( "java.lang.Boolean" );
+ BASIC_TYPES.add( "java.lang.Byte" );
+ BASIC_TYPES.add( "java.lang.Character" );
+ BASIC_TYPES.add( "java.lang.Short" );
+ BASIC_TYPES.add( "java.lang.Integer" );
+ BASIC_TYPES.add( "java.lang.Long" );
+ BASIC_TYPES.add( "java.lang.Float" );
+ BASIC_TYPES.add( "java.lang.Double" );
+ BASIC_TYPES.add( "java.math.BigInteger" );
+ BASIC_TYPES.add( "java.math.BigDecimal" );
+ BASIC_TYPES.add( "java.util.Date" );
+ BASIC_TYPES.add( "java.util.Calendar" );
+ BASIC_TYPES.add( "java.sql.Date" );
+ BASIC_TYPES.add( "java.sql.Time" );
+ BASIC_TYPES.add( "java.sql.Timestamp" );
+ }
+
+ public static List BASIC_ARRAY_TYPES = new ArrayList();
+
+ static {
+ BASIC_ARRAY_TYPES.add( "java.lang.Character" );
+ BASIC_ARRAY_TYPES.add( "java.lang.Byte" );
+ }
+
+ private Constants(){}
+}
+
+
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/StringUtil.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/StringUtil.java
new file mode 100644
index 0000000000..02480c99f8
--- /dev/null
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/StringUtil.java
@@ -0,0 +1,77 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.util;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class StringUtil {
+ private static final String NAME_SEPARATOR = ".";
+ private static final String PROPERTY_PREFIX_GET = "get";
+ private static final String PROPERTY_PREFIX_IS = "is";
+ private static final String PROPERTY_PREFIX_HAS = "has";
+
+ private StringUtil() {
+ }
+
+ public static String determineFullyQualifiedClassName(String packageName, String name) {
+ if ( isFullyQualified( name ) ) {
+ return name;
+ }
+ else {
+ return packageName + NAME_SEPARATOR + name;
+ }
+ }
+
+ public static boolean isFullyQualified(String name) {
+ return name.contains( NAME_SEPARATOR );
+ }
+
+ public static String packageNameFromFqcn(String fqcn) {
+ return fqcn.substring( 0, fqcn.lastIndexOf( NAME_SEPARATOR ) );
+ }
+
+ public static String classNameFromFqcn(String fqcn) {
+ return fqcn.substring( fqcn.lastIndexOf( NAME_SEPARATOR ) + 1 );
+ }
+
+ public static boolean isPropertyName(String name) {
+ return name.startsWith( PROPERTY_PREFIX_GET ) || name.startsWith( PROPERTY_PREFIX_IS ) || name.startsWith(
+ PROPERTY_PREFIX_HAS
+ );
+ }
+
+ public static String getPropertyName(String name) {
+ if ( !isPropertyName( name ) ) {
+ return null;
+ }
+
+ if ( name.startsWith( PROPERTY_PREFIX_GET ) ) {
+ name = name.replaceFirst( PROPERTY_PREFIX_GET, "" );
+ }
+ else if ( name.startsWith( PROPERTY_PREFIX_IS ) ) {
+ name = name.replaceFirst( PROPERTY_PREFIX_IS, "" );
+ }
+ else if ( name.startsWith( PROPERTY_PREFIX_HAS ) ) {
+ name = name.replaceFirst( PROPERTY_PREFIX_HAS, "" );
+ }
+ return name.substring(0,1).toLowerCase() + name.substring(1);
+ }
+}
+
+
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java
index 066c004e31..6111bcce36 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java
@@ -25,15 +25,30 @@ import java.util.Map;
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.TypeElement;
import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleTypeVisitor6;
import javax.lang.model.util.Types;
+import javax.persistence.Access;
+import javax.persistence.AccessType;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.tools.Diagnostic;
+import org.hibernate.jpamodelgen.AccessTypeInformation;
import org.hibernate.jpamodelgen.Context;
+import org.hibernate.jpamodelgen.MetaModelGenerationException;
/**
* Utility class.
@@ -44,6 +59,7 @@ import org.hibernate.jpamodelgen.Context;
*/
public class TypeUtils {
+ public static final String DEFAULT_ANNOTATION_PARAMETER_NAME = "value";
private static final Map PRIMITIVES = new HashMap();
static {
@@ -84,7 +100,7 @@ public class TypeUtils {
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
if ( type instanceof TypeVariable ) {
final TypeMirror compositeUpperBound = ( ( TypeVariable ) type ).getUpperBound();
- final Types types = context.getProcessingEnvironment().getTypeUtils();
+ final Types types = context.getTypeUtils();
final List extends TypeMirror> upperBounds = types.directSupertypes( compositeUpperBound );
if ( upperBounds.size() == 0 ) {
return compositeUpperBound.toString();
@@ -181,4 +197,220 @@ public class TypeUtils {
}
return returnValue;
}
+
+ public static void determineAccessTypeForHierarchy(TypeElement searchedElement, Context context) {
+ String fqcn = searchedElement.getQualifiedName().toString();
+ context.logMessage( Diagnostic.Kind.OTHER, "Determining access type for " + fqcn );
+ AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
+
+ if ( accessTypeInfo != null && accessTypeInfo.isAccessTypeResolved() ) {
+ context.logMessage(
+ Diagnostic.Kind.OTHER,
+ "AccessType for " + searchedElement.toString() + "found in cache: " + accessTypeInfo
+ );
+ return;
+ }
+
+ // check for explicit access type
+ AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( searchedElement );
+ if ( forcedAccessType != null ) {
+ context.logMessage(
+ Diagnostic.Kind.OTHER, "Explicit access type on " + searchedElement + ":" + forcedAccessType
+ );
+ accessTypeInfo = new AccessTypeInformation( fqcn, forcedAccessType, null );
+ context.addAccessTypeInformation( fqcn, accessTypeInfo );
+ updateEmbeddableAccessType( searchedElement, context, forcedAccessType );
+ return;
+ }
+
+ // need to find the default access type for this class
+ // let's check first if this entity is the root of the class hierarchy and defines an id. If so the
+ // placement of the id annotation determines the access type
+ AccessType defaultAccessType = getAccessTypeInCaseElementIsRoot( searchedElement, context );
+ if ( defaultAccessType != null ) {
+ accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
+ context.addAccessTypeInformation( fqcn, accessTypeInfo );
+ updateEmbeddableAccessType( searchedElement, context, defaultAccessType );
+ return;
+ }
+
+ // if we end up here we need to recursively look for superclasses
+ defaultAccessType = getDefaultAccessForHierarchy( searchedElement, context );
+ if ( defaultAccessType == null ) {
+ defaultAccessType = AccessType.PROPERTY;
+ }
+ accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
+ context.addAccessTypeInformation( fqcn, accessTypeInfo );
+ }
+
+ public static TypeMirror getCollectionElementType(DeclaredType t, String fqNameOfReturnedType, String explicitTargetEntityName, Context context) {
+ TypeMirror collectionElementType;
+ if ( explicitTargetEntityName != null ) {
+ Elements elements = context.getElementUtils();
+ TypeElement element = elements.getTypeElement( explicitTargetEntityName );
+ collectionElementType = element.asType();
+ }
+ else {
+ List extends TypeMirror> typeArguments = t.getTypeArguments();
+ if ( typeArguments.size() == 0 ) {
+ throw new MetaModelGenerationException( "Unable to determine collection type" );
+ }
+ else if ( Map.class.getCanonicalName().equals( fqNameOfReturnedType ) ) {
+ collectionElementType = t.getTypeArguments().get( 1 );
+ }
+ else {
+ collectionElementType = t.getTypeArguments().get( 0 );
+ }
+ }
+ return collectionElementType;
+ }
+
+ private static void updateEmbeddableAccessType(TypeElement element, Context context, AccessType defaultAccessType) {
+ List extends Element> fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() );
+ for ( Element field : fieldsOfClass ) {
+ updateEmbeddableAccessTypeForMember( context, defaultAccessType, field );
+ }
+
+ List extends Element> methodOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
+ for ( Element method : methodOfClass ) {
+ updateEmbeddableAccessTypeForMember( context, defaultAccessType, method );
+ }
+ }
+
+ private static void updateEmbeddableAccessTypeForMember(Context context, AccessType defaultAccessType, Element member) {
+ EmbeddedAttributeVisitor visitor = new EmbeddedAttributeVisitor( context );
+ String embeddedClassName = member.asType().accept( visitor, member );
+ if ( embeddedClassName != null ) {
+ AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( embeddedClassName );
+ if ( accessTypeInfo == null ) {
+ accessTypeInfo = new AccessTypeInformation( embeddedClassName, null, defaultAccessType );
+ context.addAccessTypeInformation( embeddedClassName, accessTypeInfo );
+ }
+ else {
+ accessTypeInfo.setDefaultAccessType( defaultAccessType );
+ }
+ }
+ }
+
+ private static AccessType getDefaultAccessForHierarchy(TypeElement element, Context context) {
+ AccessType defaultAccessType = null;
+ TypeElement superClass = element;
+ do {
+ superClass = TypeUtils.getSuperclassTypeElement( superClass );
+ if ( superClass != null ) {
+ String fqcn = superClass.getQualifiedName().toString();
+ AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
+ if ( accessTypeInfo != null && accessTypeInfo.getDefaultAccessType() != null ) {
+ return accessTypeInfo.getDefaultAccessType();
+ }
+ if ( TypeUtils.containsAnnotation( superClass, Entity.class, MappedSuperclass.class ) ) {
+ defaultAccessType = getAccessTypeInCaseElementIsRoot( superClass, context );
+ if ( defaultAccessType != null ) {
+ accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
+ context.addAccessTypeInformation( fqcn, accessTypeInfo );
+ defaultAccessType = accessTypeInfo.getAccessType();
+ }
+ else {
+ defaultAccessType = getDefaultAccessForHierarchy( superClass, context );
+ }
+ }
+ }
+ }
+ while ( superClass != null );
+ return defaultAccessType;
+ }
+
+ private static AccessType getAccessTypeInCaseElementIsRoot(TypeElement searchedElement, Context context) {
+ AccessType defaultAccessType = null;
+ List extends Element> myMembers = searchedElement.getEnclosedElements();
+ for ( Element subElement : myMembers ) {
+ List extends AnnotationMirror> entityAnnotations =
+ context.getElementUtils().getAllAnnotationMirrors( subElement );
+ for ( Object entityAnnotation : entityAnnotations ) {
+ AnnotationMirror annotationMirror = ( AnnotationMirror ) entityAnnotation;
+ if ( isIdAnnotation( annotationMirror ) ) {
+ defaultAccessType = getAccessTypeOfIdAnnotation( subElement );
+ break;
+ }
+ }
+ }
+ return defaultAccessType;
+ }
+
+ private static AccessType getAccessTypeOfIdAnnotation(Element element) {
+ AccessType accessType = null;
+ final ElementKind kind = element.getKind();
+ if ( kind == ElementKind.FIELD || kind == ElementKind.METHOD ) {
+ accessType = kind == ElementKind.FIELD ? AccessType.FIELD : AccessType.PROPERTY;
+ }
+ return accessType;
+ }
+
+ private static boolean isIdAnnotation(AnnotationMirror annotationMirror) {
+ return TypeUtils.isAnnotationMirrorOfType( annotationMirror, Id.class )
+ || TypeUtils.isAnnotationMirrorOfType( annotationMirror, EmbeddedId.class );
+ }
+
+ public static AccessType determineAnnotationSpecifiedAccessType(Element element) {
+ final AnnotationMirror accessAnnotationMirror = TypeUtils.getAnnotationMirror( element, Access.class );
+ AccessType forcedAccessType = null;
+ if ( accessAnnotationMirror != null ) {
+ Element accessElement = ( Element ) TypeUtils.getAnnotationValue(
+ accessAnnotationMirror,
+ DEFAULT_ANNOTATION_PARAMETER_NAME
+ );
+ if ( accessElement.getKind().equals( ElementKind.ENUM_CONSTANT ) ) {
+ if ( accessElement.getSimpleName().toString().equals( AccessType.PROPERTY.toString() ) ) {
+ forcedAccessType = AccessType.PROPERTY;
+ }
+ else if ( accessElement.getSimpleName().toString().equals( AccessType.FIELD.toString() ) ) {
+ forcedAccessType = AccessType.FIELD;
+ }
+ }
+ }
+ return forcedAccessType;
+ }
+
+ public static ElementKind getElementKindForAccessType(AccessType accessType) {
+ if ( AccessType.FIELD.equals( accessType ) ) {
+ return ElementKind.FIELD;
+ }
+ else {
+ return ElementKind.METHOD;
+ }
+ }
+
+ static class EmbeddedAttributeVisitor extends SimpleTypeVisitor6 {
+
+ private Context context;
+
+ EmbeddedAttributeVisitor(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public String visitDeclared(DeclaredType declaredType, Element element) {
+ TypeElement returnedElement = ( TypeElement ) context.getTypeUtils().asElement( declaredType );
+ String fqNameOfReturnType = null;
+ if ( containsAnnotation( returnedElement, Embeddable.class ) ) {
+ fqNameOfReturnType = returnedElement.getQualifiedName().toString();
+ }
+ return fqNameOfReturnType;
+ }
+
+ @Override
+ public String visitExecutable(ExecutableType t, Element p) {
+ if ( !p.getKind().equals( ElementKind.METHOD ) ) {
+ return null;
+ }
+
+ String string = p.getSimpleName().toString();
+ if ( !StringUtil.isPropertyName( string ) ) {
+ return null;
+ }
+
+ TypeMirror returnType = t.getReturnType();
+ return returnType.accept( this, p );
+ }
+ }
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java
index 14dbded3a0..7d78b52742 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaAttribute.java
@@ -18,7 +18,7 @@
package org.hibernate.jpamodelgen.xml;
-import org.hibernate.jpamodelgen.MetaAttribute;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
/**
* @author Hardy Ferentschik
@@ -37,7 +37,6 @@ public abstract class XmlMetaAttribute implements MetaAttribute {
this.type = type;
}
-
@Override
public String getDeclarationString() {
return "public static volatile " + parentEntity.importType(getMetaType()) + "<" + parentEntity.importType(parentEntity.getQualifiedName()) + ", " + parentEntity.importType(getTypeDeclaration()) + "> " + getPropertyName() + ";";
@@ -53,4 +52,14 @@ public abstract class XmlMetaAttribute implements MetaAttribute {
@Override
abstract public String getMetaType();
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "XmlMetaAttribute" );
+ sb.append( "{propertyName='" ).append( propertyName ).append( '\'' );
+ sb.append( ", type='" ).append( type ).append( '\'' );
+ sb.append( '}' );
+ return sb.toString();
+ }
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java
index e7a55d637a..f34b39c825 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaCollection.java
@@ -17,7 +17,7 @@
*/
package org.hibernate.jpamodelgen.xml;
-import org.hibernate.jpamodelgen.MetaCollection;
+import org.hibernate.jpamodelgen.model.MetaCollection;
/**
* @author Hardy Ferentschik
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEmbeddable.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEmbeddable.java
new file mode 100644
index 0000000000..52f66f0661
--- /dev/null
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEmbeddable.java
@@ -0,0 +1,69 @@
+// $Id: XmlMetaEntity.java 18753 2010-02-09 21:29:34Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.xml;
+
+import java.util.List;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+import org.hibernate.jpamodelgen.Context;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
+import org.hibernate.jpamodelgen.xml.jaxb.Embeddable;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class XmlMetaEmbeddable extends XmlMetaEntity {
+ // Embeddables needs to be lazily initialized since the access type be determined by the class which is embedding
+ // the entity. This might not be known until annotations are processed.
+ // Also note, that if two different classes with different access types embed this entity the access type of the
+ // embeddable will be the one of the last embedding entity processed. The result is not determined (that's ok
+ // according to the spec)
+ private boolean initialized;
+
+ public XmlMetaEmbeddable(Embeddable embeddable, String packageName, TypeElement element, Context context) {
+ super( embeddable, packageName, element, context );
+ }
+
+ public List getMembers() {
+ if ( !initialized ) {
+ context.logMessage( Diagnostic.Kind.OTHER, "Entity " + getQualifiedName() + "was lazily initialised." );
+ init();
+ initialized = true;
+ }
+ return members;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "XmlMetaEmbeddable" );
+ sb.append( "{accessTypeInfo=" ).append( accessTypeInfo );
+ sb.append( ", clazzName='" ).append( clazzName ).append( '\'' );
+ sb.append( ", members=" );
+ if ( initialized ) {
+ sb.append( members );
+ }
+ else {
+ sb.append( "[un-initalized]" );
+ }
+ sb.append( ", isMetaComplete=" ).append( isMetaComplete );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java
index 923aa1c3f1..c83b4d3bbf 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaEntity.java
@@ -22,18 +22,22 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
+import org.hibernate.jpamodelgen.AccessTypeInformation;
import org.hibernate.jpamodelgen.Context;
-import org.hibernate.jpamodelgen.ImportContext;
import org.hibernate.jpamodelgen.ImportContextImpl;
-import org.hibernate.jpamodelgen.MetaAttribute;
-import org.hibernate.jpamodelgen.MetaEntity;
import org.hibernate.jpamodelgen.MetaModelGenerationException;
+import org.hibernate.jpamodelgen.model.ImportContext;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
+import org.hibernate.jpamodelgen.model.MetaEntity;
+import org.hibernate.jpamodelgen.util.StringUtil;
import org.hibernate.jpamodelgen.util.TypeUtils;
import org.hibernate.jpamodelgen.xml.jaxb.Attributes;
import org.hibernate.jpamodelgen.xml.jaxb.Basic;
@@ -62,46 +66,61 @@ public class XmlMetaEntity implements MetaEntity {
COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" );
}
- final private String clazzName;
+ protected final String clazzName;
+ protected final String packageName;
+ protected final ImportContext importContext;
+ protected final List members = new ArrayList();
+ protected final TypeElement element;
+ protected final Context context;
+ protected final boolean isMetaComplete;
- final private String packageName;
-
- final private ImportContext importContext;
-
- final private List members = new ArrayList();
-
- private TypeElement element;
- private Context context;
+ private Attributes attributes;
+ private EmbeddableAttributes embeddableAttributes;
+ protected AccessTypeInformation accessTypeInfo;
public XmlMetaEntity(Entity ormEntity, String packageName, TypeElement element, Context context) {
- this.clazzName = ormEntity.getClazz();
- this.packageName = packageName;
- this.context = context;
- this.importContext = new ImportContextImpl( getPackageName() );
- this.element = element;
- Attributes attributes = ormEntity.getAttributes();
-
- parseAttributes( attributes );
+ this( ormEntity.getClazz(), packageName, element, context, ormEntity.isMetadataComplete() );
+ this.attributes = ormEntity.getAttributes();
+ this.embeddableAttributes = null;
+ // entities can be directly initialised
+ init();
}
- public XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element, Context context) {
- this.clazzName = mappedSuperclass.getClazz();
- this.packageName = packageName;
- this.context = context;
- this.importContext = new ImportContextImpl( getPackageName() );
- this.element = element;
- Attributes attributes = mappedSuperclass.getAttributes();
- parseAttributes( attributes );
+ protected XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element, Context context) {
+ this( mappedSuperclass.getClazz(), packageName, element, context, mappedSuperclass.isMetadataComplete() );
+ this.attributes = mappedSuperclass.getAttributes();
+ this.embeddableAttributes = null;
}
- public XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element, Context context) {
- this.clazzName = embeddable.getClazz();
+ protected XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element, Context context) {
+ this( embeddable.getClazz(), packageName, element, context, embeddable.isMetadataComplete() );
+ this.attributes = null;
+ this.embeddableAttributes = embeddable.getAttributes();
+ }
+
+ private XmlMetaEntity(String clazz, String packageName, TypeElement element, Context context, Boolean metaComplete) {
+ String className = clazz;
+ if ( StringUtil.isFullyQualified( className ) ) {
+ // we have to extract the package name from the fqcn. default package name gets ignored
+ packageName = StringUtil.packageNameFromFqcn( className );
+ className = StringUtil.classNameFromFqcn( clazz );
+ }
+ this.clazzName = className;
this.packageName = packageName;
this.context = context;
this.importContext = new ImportContextImpl( getPackageName() );
this.element = element;
- EmbeddableAttributes attributes = embeddable.getAttributes();
- parseEmbeddableAttributes( attributes );
+ this.isMetaComplete = initIsMetaComplete( metaComplete );
+ }
+
+ protected void init() {
+ this.accessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
+ if ( attributes != null ) {
+ parseAttributes( attributes );
+ }
+ else {
+ parseEmbeddableAttributes( embeddableAttributes );
+ }
}
public String getSimpleName() {
@@ -140,150 +159,295 @@ public class XmlMetaEntity implements MetaEntity {
return element;
}
- private String[] getCollectionType(String propertyName, String explicitTargetEntity) {
- String types[] = new String[2];
- for ( Element elem : element.getEnclosedElements() ) {
- if ( elem.getSimpleName().toString().equals( propertyName ) ) {
- DeclaredType type = ( ( DeclaredType ) elem.asType() );
- List extends TypeMirror> typeArguments = type.getTypeArguments();
-
- if ( typeArguments.size() == 0 && explicitTargetEntity == null ) {
- throw new MetaModelGenerationException( "Unable to determine target entity type for " + clazzName + "." + propertyName + "." );
- }
-
- if ( explicitTargetEntity == null ) {
- types[0] = TypeUtils.extractClosestRealTypeAsString( typeArguments.get( 0 ), context );
- }
- else {
- types[0] = explicitTargetEntity;
- }
- types[1] = COLLECTIONS.get( type.asElement().toString() );
- }
- }
- return types;
- }
-
- /**
- * Returns the entity type for relation.
- *
- * @param propertyName The property name of the association
- * @param explicitTargetEntity The explicitly specified target entity type
- *
- * @return The entity type for relation/association.
- */
- private String getType(String propertyName, String explicitTargetEntity) {
- if ( explicitTargetEntity != null ) {
- // TODO should there be a check of the target entity class and if it is loadable?
- return explicitTargetEntity;
- }
-
- String typeName = null;
- for ( Element elem : element.getEnclosedElements() ) {
- if ( elem.getSimpleName().toString().equals( propertyName ) ) {
- switch ( elem.asType().getKind() ) {
- case INT: {
- typeName = "java.lang.Integer";
- break;
- }
- case LONG: {
- typeName = "java.lang.Long";
- break;
- }
- case BOOLEAN: {
- typeName = "java.lang.Boolean";
- break;
- }
- case DECLARED: {
- typeName = elem.asType().toString();
- break;
- }
- case TYPEVAR: {
- typeName = elem.asType().toString();
- break;
- }
- }
- break;
- }
- }
- return typeName;
+ @Override
+ public boolean isMetaComplete() {
+ return isMetaComplete;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "XmlMetaEntity" );
- sb.append( "{type=" ).append( element );
+ sb.append( "{accessTypeInfo=" ).append( accessTypeInfo );
+ sb.append( ", clazzName='" ).append( clazzName ).append( '\'' );
+ sb.append( ", members=" ).append( members );
+ sb.append( ", isMetaComplete=" ).append( isMetaComplete );
sb.append( '}' );
return sb.toString();
}
+ private boolean initIsMetaComplete(Boolean metadataComplete) {
+ return context.isPersistenceUnitCompletelyXmlConfigured() || Boolean.TRUE.equals( metadataComplete );
+ }
+
+ private String[] getCollectionType(String propertyName, String explicitTargetEntity, ElementKind expectedElementKind) {
+ String types[] = new String[2];
+ for ( Element elem : element.getEnclosedElements() ) {
+ if ( expectedElementKind.equals( elem.getKind() ) ) {
+ continue;
+ }
+
+ if ( !elem.getSimpleName().toString().equals( propertyName ) ) {
+ continue;
+ }
+
+ DeclaredType type = ( ( DeclaredType ) elem.asType() );
+ List extends TypeMirror> typeArguments = type.getTypeArguments();
+
+ if ( typeArguments.size() == 0 && explicitTargetEntity == null ) {
+ throw new MetaModelGenerationException( "Unable to determine target entity type for " + clazzName + "." + propertyName + "." );
+ }
+
+ if ( explicitTargetEntity == null ) {
+ types[0] = TypeUtils.extractClosestRealTypeAsString( typeArguments.get( 0 ), context );
+ }
+ else {
+ types[0] = explicitTargetEntity;
+ }
+ types[1] = COLLECTIONS.get( type.asElement().toString() );
+ return types;
+
+ }
+ return null;
+ }
+
+ /**
+ * Returns the entity type for a property.
+ *
+ * @param propertyName The property name
+ * @param explicitTargetEntity The explicitly specified target entity type or {@code null}.
+ * @param expectedElementKind Determines property vs field access type
+ *
+ * @return The entity type for this property or {@code null} if the property with the name and the matching access
+ * type does not exist.
+ */
+ private String getType(String propertyName, String explicitTargetEntity, ElementKind expectedElementKind) {
+ for ( Element elem : element.getEnclosedElements() ) {
+ if ( !expectedElementKind.equals( elem.getKind() ) ) {
+ continue;
+ }
+
+ TypeMirror mirror;
+ String name = elem.getSimpleName().toString();
+ if ( ElementKind.METHOD.equals( elem.getKind() ) ) {
+ name = StringUtil.getPropertyName( name );
+ mirror = ( ( ExecutableElement ) elem ).getReturnType();
+ }
+ else {
+ mirror = elem.asType();
+ }
+
+ if ( name == null || !name.equals( propertyName ) ) {
+ continue;
+ }
+
+ if ( explicitTargetEntity != null ) {
+ // TODO should there be a check of the target entity class and if it is loadable?
+ return explicitTargetEntity;
+ }
+
+ switch ( mirror.getKind() ) {
+ case INT: {
+ return "java.lang.Integer";
+ }
+ case LONG: {
+ return "java.lang.Long";
+ }
+ case BOOLEAN: {
+ return "java.lang.Boolean";
+ }
+ case BYTE: {
+ return "java.lang.Byte";
+ }
+ case SHORT: {
+ return "java.lang.Short";
+ }
+ case CHAR: {
+ return "java.lang.Char";
+ }
+ case FLOAT: {
+ return "java.lang.Float";
+ }
+ case DOUBLE: {
+ return "java.lang.Double";
+ }
+ case DECLARED: {
+ return mirror.toString();
+ }
+ case TYPEVAR: {
+ return mirror.toString();
+ }
+ }
+ }
+
+ context.logMessage(
+ Diagnostic.Kind.WARNING,
+ "Unable to determine type for property " + propertyName + " of class " + getQualifiedName()
+ + " using assess type " + accessTypeInfo.getDefaultAccessType()
+ );
+ return null;
+ }
+
private void parseAttributes(Attributes attributes) {
XmlMetaSingleAttribute attribute;
-
- if ( !attributes.getId().isEmpty() ) {
- // TODO what do we do if there are more than one id nodes?
- Id id = attributes.getId().get( 0 );
- attribute = new XmlMetaSingleAttribute(
- this, id.getName(), getType( id.getName(), null )
- );
- members.add( attribute );
+ for ( Id id : attributes.getId() ) {
+ ElementKind elementKind = getElementKind( id.getAccess() );
+ String type = getType( id.getName(), null, elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, id.getName(), type );
+ members.add( attribute );
+ }
}
for ( Basic basic : attributes.getBasic() ) {
- attribute = new XmlMetaSingleAttribute( this, basic.getName(), getType( basic.getName(), null ) );
- members.add( attribute );
+ ElementKind elementKind = getElementKind( basic.getAccess() );
+ String type = getType( basic.getName(), null, elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, basic.getName(), type );
+ members.add( attribute );
+ }
}
for ( ManyToOne manyToOne : attributes.getManyToOne() ) {
- attribute = new XmlMetaSingleAttribute(
- this, manyToOne.getName(), getType( manyToOne.getName(), manyToOne.getTargetEntity() )
- );
- members.add( attribute );
+ ElementKind elementKind = getElementKind( manyToOne.getAccess() );
+ String type = getType( manyToOne.getName(), manyToOne.getTargetEntity(), elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, manyToOne.getName(), type );
+ members.add( attribute );
+ }
}
for ( OneToOne oneToOne : attributes.getOneToOne() ) {
- attribute = new XmlMetaSingleAttribute(
- this, oneToOne.getName(), getType( oneToOne.getName(), oneToOne.getTargetEntity() )
- );
- members.add( attribute );
+ ElementKind elementKind = getElementKind( oneToOne.getAccess() );
+ String type = getType( oneToOne.getName(), oneToOne.getTargetEntity(), elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, oneToOne.getName(), type );
+ members.add( attribute );
+ }
}
XmlMetaCollection metaCollection;
String[] types;
for ( ManyToMany manyToMany : attributes.getManyToMany() ) {
+ ElementKind elementKind = getElementKind( manyToMany.getAccess() );
try {
- types = getCollectionType( manyToMany.getName(), manyToMany.getTargetEntity() );
+ types = getCollectionType( manyToMany.getName(), manyToMany.getTargetEntity(), elementKind );
}
catch ( MetaModelGenerationException e ) {
logMetaModelException( manyToMany.getName(), e );
break;
}
- metaCollection = new XmlMetaCollection( this, manyToMany.getName(), types[0], types[1] );
- members.add( metaCollection );
+ if ( types != null ) {
+ metaCollection = new XmlMetaCollection( this, manyToMany.getName(), types[0], types[1] );
+ members.add( metaCollection );
+ }
}
for ( OneToMany oneToMany : attributes.getOneToMany() ) {
+ ElementKind elementKind = getElementKind( oneToMany.getAccess() );
try {
- types = getCollectionType( oneToMany.getName(), oneToMany.getTargetEntity() );
+ types = getCollectionType( oneToMany.getName(), oneToMany.getTargetEntity(), elementKind );
}
catch ( MetaModelGenerationException e ) {
logMetaModelException( oneToMany.getName(), e );
break;
}
- metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] );
- members.add( metaCollection );
+ if ( types != null ) {
+ metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] );
+ members.add( metaCollection );
+ }
}
for ( ElementCollection collection : attributes.getElementCollection() ) {
+ ElementKind elementKind = getElementKind( collection.getAccess() );
try {
- types = getCollectionType( collection.getName(), collection.getTargetClass() );
+ types = getCollectionType( collection.getName(), collection.getTargetClass(), elementKind );
}
catch ( MetaModelGenerationException e ) {
logMetaModelException( collection.getName(), e );
break;
}
- metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] );
- members.add( metaCollection );
+ if ( types != null ) {
+ metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] );
+ members.add( metaCollection );
+ }
+ }
+ }
+
+ private void parseEmbeddableAttributes(EmbeddableAttributes attributes) {
+ XmlMetaSingleAttribute attribute;
+ for ( Basic basic : attributes.getBasic() ) {
+ ElementKind elementKind = getElementKind( basic.getAccess() );
+ String type = getType( basic.getName(), null, elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, basic.getName(), type );
+ members.add( attribute );
+ }
+ }
+
+ for ( ManyToOne manyToOne : attributes.getManyToOne() ) {
+ ElementKind elementKind = getElementKind( manyToOne.getAccess() );
+ String type = getType( manyToOne.getName(), manyToOne.getTargetEntity(), elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, manyToOne.getName(), type );
+ members.add( attribute );
+ }
+ }
+
+ for ( OneToOne oneToOne : attributes.getOneToOne() ) {
+ ElementKind elementKind = getElementKind( oneToOne.getAccess() );
+ String type = getType( oneToOne.getName(), oneToOne.getTargetEntity(), elementKind );
+ if ( type != null ) {
+ attribute = new XmlMetaSingleAttribute( this, oneToOne.getName(), type );
+ members.add( attribute );
+ }
+ }
+
+ XmlMetaCollection metaCollection;
+ String[] types;
+ for ( ManyToMany manyToMany : attributes.getManyToMany() ) {
+ ElementKind elementKind = getElementKind( manyToMany.getAccess() );
+ try {
+ types = getCollectionType( manyToMany.getName(), manyToMany.getTargetEntity(), elementKind );
+ }
+ catch ( MetaModelGenerationException e ) {
+ logMetaModelException( manyToMany.getName(), e );
+ break;
+ }
+ if ( types != null ) {
+ metaCollection = new XmlMetaCollection( this, manyToMany.getName(), types[0], types[1] );
+ members.add( metaCollection );
+ }
+ }
+
+ for ( OneToMany oneToMany : attributes.getOneToMany() ) {
+ ElementKind elementKind = getElementKind( oneToMany.getAccess() );
+ try {
+ types = getCollectionType( oneToMany.getName(), oneToMany.getTargetEntity(), elementKind );
+ }
+ catch ( MetaModelGenerationException e ) {
+ logMetaModelException( oneToMany.getName(), e );
+ break;
+ }
+ if ( types != null ) {
+ metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] );
+ members.add( metaCollection );
+ }
+ }
+
+ for ( ElementCollection collection : attributes.getElementCollection() ) {
+ ElementKind elementKind = getElementKind( collection.getAccess() );
+ try {
+ types = getCollectionType( collection.getName(), collection.getTargetClass(), elementKind );
+ }
+ catch ( MetaModelGenerationException e ) {
+ logMetaModelException( collection.getName(), e );
+ break;
+ }
+ if ( types != null ) {
+ metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] );
+ members.add( metaCollection );
+ }
}
}
@@ -301,44 +465,17 @@ public class XmlMetaEntity implements MetaEntity {
);
}
- private void parseEmbeddableAttributes(EmbeddableAttributes attributes) {
- XmlMetaSingleAttribute attribute;
- for ( Basic basic : attributes.getBasic() ) {
- attribute = new XmlMetaSingleAttribute( this, basic.getName(), getType( basic.getName(), null ) );
- members.add( attribute );
+ private ElementKind getElementKind(org.hibernate.jpamodelgen.xml.jaxb.AccessType accessType) {
+ // if no explicit access type was specified in xml we use the entity access type
+ if ( accessType == null ) {
+ return TypeUtils.getElementKindForAccessType( accessTypeInfo.getDefaultAccessType() );
}
- for ( ManyToOne manyToOne : attributes.getManyToOne() ) {
- attribute = new XmlMetaSingleAttribute(
- this, manyToOne.getName(), getType( manyToOne.getName(), manyToOne.getTargetEntity() )
- );
- members.add( attribute );
+ if ( org.hibernate.jpamodelgen.xml.jaxb.AccessType.FIELD.equals( accessType ) ) {
+ return ElementKind.FIELD;
}
-
- for ( OneToOne oneToOne : attributes.getOneToOne() ) {
- attribute = new XmlMetaSingleAttribute(
- this, oneToOne.getName(), getType( oneToOne.getName(), oneToOne.getTargetEntity() )
- );
- members.add( attribute );
- }
-
- XmlMetaCollection metaCollection;
- for ( ManyToMany manyToMany : attributes.getManyToMany() ) {
- String[] types = getCollectionType( manyToMany.getName(), manyToMany.getTargetEntity() );
- metaCollection = new XmlMetaCollection( this, manyToMany.getName(), types[0], types[1] );
- members.add( metaCollection );
- }
-
- for ( OneToMany oneToMany : attributes.getOneToMany() ) {
- String[] types = getCollectionType( oneToMany.getName(), oneToMany.getTargetEntity() );
- metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] );
- members.add( metaCollection );
- }
-
- for ( ElementCollection collection : attributes.getElementCollection() ) {
- String[] types = getCollectionType( collection.getName(), collection.getTargetClass() );
- metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] );
- members.add( metaCollection );
+ else {
+ return ElementKind.METHOD;
}
}
}
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaMappedSuperClass.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaMappedSuperClass.java
new file mode 100644
index 0000000000..4e599801c9
--- /dev/null
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaMappedSuperClass.java
@@ -0,0 +1,74 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.xml;
+
+import java.util.List;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+
+import org.hibernate.jpamodelgen.Context;
+import org.hibernate.jpamodelgen.MetaModelGenerationException;
+import org.hibernate.jpamodelgen.model.MetaAttribute;
+import org.hibernate.jpamodelgen.xml.jaxb.Basic;
+import org.hibernate.jpamodelgen.xml.jaxb.ElementCollection;
+import org.hibernate.jpamodelgen.xml.jaxb.EmbeddableAttributes;
+import org.hibernate.jpamodelgen.xml.jaxb.ManyToMany;
+import org.hibernate.jpamodelgen.xml.jaxb.ManyToOne;
+import org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass;
+import org.hibernate.jpamodelgen.xml.jaxb.OneToMany;
+import org.hibernate.jpamodelgen.xml.jaxb.OneToOne;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class XmlMetaMappedSuperClass extends XmlMetaEntity {
+ private boolean initialized;
+
+ public XmlMetaMappedSuperClass(MappedSuperclass mappedSuperclass, String packageName, TypeElement element, Context context) {
+ super( mappedSuperclass, packageName, element, context );
+ }
+
+ public List getMembers() {
+ if ( !initialized ) {
+ context.logMessage( Diagnostic.Kind.OTHER, "Entity " + getQualifiedName() + "was lazily initialised." );
+ init();
+ initialized = true;
+ }
+ return members;
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "XmlMetaEntity" );
+ sb.append( "{accessTypeInfo=" ).append( accessTypeInfo );
+ sb.append( ", clazzName='" ).append( clazzName ).append( '\'' );
+ sb.append( ", members=" );
+ if ( initialized ) {
+ sb.append( members );
+ }
+ else {
+ sb.append( "[un-initalized]" );
+ }
+ sb.append( ", isMetaComplete=" ).append( isMetaComplete );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java
index 231dd715f0..ecc418eb1b 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlMetaSingleAttribute.java
@@ -17,7 +17,7 @@
*/
package org.hibernate.jpamodelgen.xml;
-import org.hibernate.jpamodelgen.MetaSingleAttribute;
+import org.hibernate.jpamodelgen.model.MetaSingleAttribute;
/**
* @author Hardy Ferentschik
diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlParser.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlParser.java
index be24bbf169..179632b6b8 100644
--- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlParser.java
+++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/xml/XmlParser.java
@@ -20,6 +20,7 @@ package org.hibernate.jpamodelgen.xml;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.lang.model.element.TypeElement;
@@ -36,7 +37,10 @@ import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
+import org.hibernate.jpamodelgen.AccessTypeInformation;
import org.hibernate.jpamodelgen.Context;
+import org.hibernate.jpamodelgen.util.StringUtil;
+import org.hibernate.jpamodelgen.util.TypeUtils;
import org.hibernate.jpamodelgen.xml.jaxb.Entity;
import org.hibernate.jpamodelgen.xml.jaxb.EntityMappings;
import org.hibernate.jpamodelgen.xml.jaxb.ObjectFactory;
@@ -48,132 +52,145 @@ import org.hibernate.jpamodelgen.xml.jaxb.PersistenceUnitMetadata;
* @author Hardy Ferentschik
*/
public class XmlParser {
-
- private static final String PERSISTENCE_XML = "/META-INF/persistence.xml";
private static final String ORM_XML = "/META-INF/orm.xml";
private static final String PERSISTENCE_XML_XSD = "persistence_2_0.xsd";
private static final String ORM_XSD = "orm_2_0.xsd";
private static final String PATH_SEPARATOR = "/";
- private static final AccessType DEFAULT_XML_ACCESS_TYPE = AccessType.PROPERTY;
private Context context;
+ private List entityMappings;
public XmlParser(Context context) {
this.context = context;
+ this.entityMappings = new ArrayList();
}
- public void parsePersistenceXml() {
- Persistence persistence = parseXml( PERSISTENCE_XML, Persistence.class, PERSISTENCE_XML_XSD );
+ public void parseXml() {
+ collectAllEntityMappings();
+ determineDefaultAccessTypeAndMetaCompleteness();
+ determineXmlAccessTypes();
+ if ( !context.isPersistenceUnitCompletelyXmlConfigured() ) {
+ // need to take annotations into consideration, since they can override xml settings
+ // we have to at least determine whether any of the xml configured entities is influenced by annotations
+ determineAnnotationAccessTypes();
+ }
+
+ for ( EntityMappings mappings : entityMappings ) {
+ String defaultPackageName = mappings.getPackage();
+ parseEntities( mappings.getEntity(), defaultPackageName );
+ parseEmbeddable( mappings.getEmbeddable(), defaultPackageName );
+ parseMappedSuperClass( mappings.getMappedSuperclass(), defaultPackageName );
+ }
+ }
+
+ private void collectAllEntityMappings() {
+ Persistence persistence = parseXml(
+ context.getPersistenceXmlLocation(), Persistence.class, PERSISTENCE_XML_XSD
+ );
if ( persistence != null ) {
List persistenceUnits = persistence.getPersistenceUnit();
for ( Persistence.PersistenceUnit unit : persistenceUnits ) {
List mappingFiles = unit.getMappingFile();
for ( String mappingFile : mappingFiles ) {
- parsingOrmXml( mappingFile );
+ loadEntityMappings( mappingFile );
}
}
}
- parsingOrmXml( ORM_XML ); // /META-INF/orm.xml is implicit
- }
- private void parsingOrmXml(String resource) {
- EntityMappings mappings = parseXml( resource, EntityMappings.class, ORM_XSD );
- if ( mappings == null ) {
- return;
+ // /META-INF/orm.xml is implicit
+ loadEntityMappings( ORM_XML );
+
+ // not really part of the official spec, but the processor allows to specify mapping files directly as
+ // command line options
+ for ( String optionalOrmFiles : context.getOrmXmlFiles() ) {
+ loadEntityMappings( optionalOrmFiles );
}
-
- AccessType accessType = determineGlobalAccessType( mappings );
-
- parseEntities( mappings, accessType );
- parseEmbeddable( mappings, accessType );
- parseMappedSuperClass( mappings, accessType );
}
- private void parseEntities(EntityMappings mappings, AccessType accessType) {
- String packageName = mappings.getPackage();
- Collection entities = mappings.getEntity();
+ private void loadEntityMappings(String resource) {
+ EntityMappings mapping = parseXml( resource, EntityMappings.class, ORM_XSD );
+ if ( mapping != null ) {
+ entityMappings.add( mapping );
+ }
+ }
+
+ private void parseEntities(Collection entities, String defaultPackageName) {
for ( Entity entity : entities ) {
- String fullyQualifiedClassName = packageName + "." + entity.getClazz();
+ String fqcn = StringUtil.determineFullyQualifiedClassName( defaultPackageName, entity.getClazz() );
- if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) {
+ if ( !xmlMappedTypeExists( fqcn ) ) {
context.logMessage(
Diagnostic.Kind.WARNING,
- fullyQualifiedClassName + " is mapped in xml, but class does not exists. Skipping meta model generation."
+ fqcn + " is mapped in xml, but class does not exists. Skipping meta model generation."
);
continue;
}
XmlMetaEntity metaEntity = new XmlMetaEntity(
- entity, packageName, getXmlMappedType( fullyQualifiedClassName ),
- context
+ entity, defaultPackageName, getXmlMappedType( fqcn ), context
);
-
- if ( context.getMetaEntitiesToProcess().containsKey( fullyQualifiedClassName ) ) {
+ if ( context.containsMetaEntity( fqcn ) ) {
context.logMessage(
Diagnostic.Kind.WARNING,
- fullyQualifiedClassName + " was already processed once. Skipping second occurance."
+ fqcn + " was already processed once. Skipping second occurance."
);
}
- context.getMetaEntitiesToProcess().put( fullyQualifiedClassName, metaEntity );
+ context.addMetaEntity( fqcn, metaEntity );
}
}
- private void parseEmbeddable(EntityMappings mappings, AccessType accessType) {
- String packageName = mappings.getPackage();
- Collection embeddables = mappings.getEmbeddable();
+ private void parseEmbeddable(Collection embeddables, String defaultPackageName) {
for ( org.hibernate.jpamodelgen.xml.jaxb.Embeddable embeddable : embeddables ) {
- String fullyQualifiedClassName = packageName + "." + embeddable.getClazz();
+ String fqcn = StringUtil.determineFullyQualifiedClassName( defaultPackageName, embeddable.getClazz() );
+ // we have to extract the package name from the fqcn. Maybe the entity was setting a fqcn directly
+ String pkg = StringUtil.packageNameFromFqcn( fqcn );
- if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) {
+ if ( !xmlMappedTypeExists( fqcn ) ) {
context.logMessage(
Diagnostic.Kind.WARNING,
- fullyQualifiedClassName + " is mapped in xml, but class does not exists. Skipping meta model generation."
+ fqcn + " is mapped in xml, but class does not exists. Skipping meta model generation."
);
continue;
}
- XmlMetaEntity metaEntity = new XmlMetaEntity(
- embeddable, packageName, getXmlMappedType( fullyQualifiedClassName ),
- context
- );
-
- if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) {
+ XmlMetaEntity metaEntity = new XmlMetaEmbeddable( embeddable, pkg, getXmlMappedType( fqcn ), context );
+ if ( context.containsMetaSuperclassOrEmbeddable( fqcn ) ) {
context.logMessage(
Diagnostic.Kind.WARNING,
- fullyQualifiedClassName + " was already processed once. Skipping second occurance."
+ fqcn + " was already processed once. Skipping second occurance."
);
}
- context.getMetaSuperclassAndEmbeddableToProcess().put( fullyQualifiedClassName, metaEntity );
+ context.addMetaSuperclassOrEmbeddable( fqcn, metaEntity );
}
}
-
- private void parseMappedSuperClass(EntityMappings mappings, AccessType accessType) {
- String packageName = mappings.getPackage();
- Collection mappedSuperClasses = mappings.getMappedSuperclass();
+ private void parseMappedSuperClass(Collection mappedSuperClasses, String defaultPackageName) {
for ( org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass mappedSuperClass : mappedSuperClasses ) {
- String fullyQualifiedClassName = packageName + "." + mappedSuperClass.getClazz();
+ String fqcn = StringUtil.determineFullyQualifiedClassName(
+ defaultPackageName, mappedSuperClass.getClazz()
+ );
+ // we have to extract the package name from the fqcn. Maybe the entity was setting a fqcn directly
+ String pkg = StringUtil.packageNameFromFqcn( fqcn );
- if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) {
+ if ( !xmlMappedTypeExists( fqcn ) ) {
context.logMessage(
Diagnostic.Kind.WARNING,
- fullyQualifiedClassName + " is mapped in xml, but class does not exists. Skipping meta model generation."
+ fqcn + " is mapped in xml, but class does not exists. Skipping meta model generation."
);
continue;
}
- XmlMetaEntity metaEntity = new XmlMetaEntity(
- mappedSuperClass, packageName, getXmlMappedType( fullyQualifiedClassName ),
- context
+ XmlMetaEntity metaEntity = new XmlMetaMappedSuperClass(
+ mappedSuperClass, pkg, getXmlMappedType( fqcn ), context
);
- if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) {
+ if ( context.containsMetaSuperclassOrEmbeddable( fqcn ) ) {
context.logMessage(
Diagnostic.Kind.WARNING,
- fullyQualifiedClassName + " was already processed once. Skipping second occurance."
+ fqcn + " was already processed once. Skipping second occurance."
);
}
- context.getMetaSuperclassAndEmbeddableToProcess().put( fullyQualifiedClassName, metaEntity );
+ context.addMetaSuperclassOrEmbeddable( fqcn, metaEntity );
}
}
@@ -184,7 +201,8 @@ public class XmlParser {
* @param clazz The type of jaxb node to return
* @param schemaName The schema to validate against (can be {@code null});
*
- * @return The top level jaxb instance contained in the xml file or {@code null} in case the file could not be found.
+ * @return The top level jaxb instance contained in the xml file or {@code null} in case the file could not be found
+ * or could not be unmarshalled.
*/
private T parseXml(String resource, Class clazz, String schemaName) {
@@ -274,35 +292,135 @@ public class XmlParser {
}
private boolean xmlMappedTypeExists(String fullyQualifiedClassName) {
- Elements utils = context.getProcessingEnvironment().getElementUtils();
+ Elements utils = context.getElementUtils();
return utils.getTypeElement( fullyQualifiedClassName ) != null;
}
private TypeElement getXmlMappedType(String fullyQualifiedClassName) {
- Elements utils = context.getProcessingEnvironment().getElementUtils();
+ Elements utils = context.getElementUtils();
return utils.getTypeElement( fullyQualifiedClassName );
}
-
- private AccessType determineGlobalAccessType(EntityMappings mappings) {
- AccessType accessType = DEFAULT_XML_ACCESS_TYPE;
-
+ private AccessType determineEntityAccessType(EntityMappings mappings) {
+ AccessType accessType = context.getPersistenceUnitDefaultAccessType();
if ( mappings.getAccess() != null ) {
accessType = mapXmlAccessTypeToJpaAccessType( mappings.getAccess() );
- return accessType; // no need to check persistence unit default
}
+ return accessType;
+ }
- PersistenceUnitMetadata meta = mappings.getPersistenceUnitMetadata();
- if ( meta != null ) {
- PersistenceUnitDefaults persistenceUnitDefaults = meta.getPersistenceUnitDefaults();
- if ( persistenceUnitDefaults != null ) {
- org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType = persistenceUnitDefaults.getAccess();
- if ( xmlAccessType != null ) {
- accessType = mapXmlAccessTypeToJpaAccessType( xmlAccessType );
+ private void determineXmlAccessTypes() {
+ for ( EntityMappings mappings : entityMappings ) {
+ String fqcn;
+ String packageName = mappings.getPackage();
+ AccessType defaultAccessType = determineEntityAccessType( mappings );
+
+ for ( Entity entity : mappings.getEntity() ) {
+ String name = entity.getClazz();
+ fqcn = StringUtil.determineFullyQualifiedClassName( packageName, name );
+ AccessType explicitAccessType = null;
+ org.hibernate.jpamodelgen.xml.jaxb.AccessType type = entity.getAccess();
+ if ( type != null ) {
+ explicitAccessType = mapXmlAccessTypeToJpaAccessType( type );
+ }
+ AccessTypeInformation accessInfo = new AccessTypeInformation(
+ fqcn, explicitAccessType, defaultAccessType
+ );
+ context.addAccessTypeInformation( fqcn, accessInfo );
+ }
+
+ for ( org.hibernate.jpamodelgen.xml.jaxb.Embeddable embeddable : mappings.getEmbeddable() ) {
+ String name = embeddable.getClazz();
+ fqcn = StringUtil.determineFullyQualifiedClassName( packageName, name );
+ AccessType explicitAccessType = null;
+ org.hibernate.jpamodelgen.xml.jaxb.AccessType type = embeddable.getAccess();
+ if ( type != null ) {
+ explicitAccessType = mapXmlAccessTypeToJpaAccessType( type );
+ }
+ AccessTypeInformation accessInfo = new AccessTypeInformation(
+ fqcn, explicitAccessType, defaultAccessType
+ );
+ context.addAccessTypeInformation( fqcn, accessInfo );
+
+ }
+
+ for ( org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass mappedSuperClass : mappings.getMappedSuperclass() ) {
+ String name = mappedSuperClass.getClazz();
+ fqcn = StringUtil.determineFullyQualifiedClassName( packageName, name );
+ AccessType explicitAccessType = null;
+ org.hibernate.jpamodelgen.xml.jaxb.AccessType type = mappedSuperClass.getAccess();
+ if ( type != null ) {
+ explicitAccessType = mapXmlAccessTypeToJpaAccessType( type );
+ }
+ AccessTypeInformation accessInfo = new AccessTypeInformation(
+ fqcn, explicitAccessType, defaultAccessType
+ );
+ context.addAccessTypeInformation( fqcn, accessInfo );
+ }
+ }
+ }
+
+ private void determineAnnotationAccessTypes() {
+ for ( EntityMappings mappings : entityMappings ) {
+ String fqcn;
+ String packageName = mappings.getPackage();
+
+ for ( Entity entity : mappings.getEntity() ) {
+ String name = entity.getClazz();
+ fqcn = StringUtil.determineFullyQualifiedClassName( packageName, name );
+ TypeElement element = context.getTypeElementForFullyQualifiedName( fqcn );
+ if ( element != null ) {
+ TypeUtils.determineAccessTypeForHierarchy( element, context );
+ }
+ }
+
+ for ( org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass mappedSuperClass : mappings.getMappedSuperclass() ) {
+ String name = mappedSuperClass.getClazz();
+ fqcn = StringUtil.determineFullyQualifiedClassName( packageName, name );
+ TypeElement element = context.getTypeElementForFullyQualifiedName( fqcn );
+ if ( element != null ) {
+ TypeUtils.determineAccessTypeForHierarchy( element, context );
}
}
}
- return accessType;
+ }
+
+ /**
+ * Determines the default access type as specified in the persistence-unit-defaults as well as whether the
+ * xml configuration is complete and annotations should be ignored.
+ *
+ * Note, the spec says:
+ *
+ * - The persistence-unit-metadata element contains metadata for the entire persistence unit. It is
+ * undefined if this element occurs in multiple mapping files within the same persistence unit.
+ * - If the xml-mapping-metadata-complete subelement is specified, the complete set of mapping
+ * metadata for the persistence unit is contained in the XML mapping files for the persistence unit, and any
+ * persistence annotations on the classes are ignored.
+ * - When the xml-mapping-metadata-complete element is specified, any metadata-complete attributes specified
+ * within the entity, mapped-superclass, and embeddable elements are ignored.
-
+ *
+ */
+ private void determineDefaultAccessTypeAndMetaCompleteness() {
+ for ( EntityMappings mappings : entityMappings ) {
+ PersistenceUnitMetadata meta = mappings.getPersistenceUnitMetadata();
+ if ( meta != null ) {
+ if ( meta.getXmlMappingMetadataComplete() != null ) {
+ context.setPersistenceUnitCompletelyXmlConfigured( true );
+ }
+
+ PersistenceUnitDefaults persistenceUnitDefaults = meta.getPersistenceUnitDefaults();
+ if ( persistenceUnitDefaults != null ) {
+ org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType = persistenceUnitDefaults.getAccess();
+ if ( xmlAccessType != null ) {
+ context.setPersistenceUnitDefaultAccessType( mapXmlAccessTypeToJpaAccessType( xmlAccessType ) );
+ }
+ }
+ // for simplicity we stop looking for PersistenceUnitMetadata instances. We assume that all files
+ // are consistent in the data specified in PersistenceUnitMetadata. If not the behaviour is not specified
+ // anyways. It is up to the JPA provider to handle this when bootstrapping
+ break;
+ }
+ }
}
private AccessType mapXmlAccessTypeToJpaAccessType(org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType) {
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/AccessTypeTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/AccessTypeTest.java
index bb5a2dcaaa..69e5d65ce8 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/AccessTypeTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/AccessTypeTest.java
@@ -17,6 +17,10 @@
*/
package org.hibernate.jpamodelgen.test.accesstype;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
import org.testng.annotations.Test;
import org.hibernate.jpamodelgen.test.util.CompilationTest;
@@ -32,6 +36,11 @@ import static org.hibernate.jpamodelgen.test.util.TestUtil.assertPresenceOfField
*/
public class AccessTypeTest extends CompilationTest {
+ @Test
+ public void testXmlConfiguredEntityGenerated() {
+ TestUtil.assertMetamodelClassGeneratedFor( Order.class );
+ }
+
@Test
public void testExcludeTransientFieldAndStatic() {
TestUtil.assertAbsenceOfFieldInMetamodelFor( Product.class, "nonPersistent" );
@@ -88,7 +97,14 @@ public class AccessTypeTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
- return Product.class.getPackage().getName();
+ protected String getPackageNameOfTestSources() {
+ return AccessTypeTest.class.getPackage().getName();
+ }
+
+ @Override
+ protected Collection getOrmFiles() {
+ List ormFiles = new ArrayList();
+ ormFiles.add( TestUtil.fcnToPath( AccessTypeTest.class.getPackage().getName() ) + "/orm.xml" );
+ return ormFiles;
}
}
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/Order.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/Order.java
index 41bba2b35b..750b449cf9 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/Order.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/accesstype/Order.java
@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Set;
/**
- *
* @author Max Andersen
* @author Hardy Ferentschik
* @author Emmanuel Bernard
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/ArrayTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/ArrayTest.java
index 59e33bfd51..50301e9bbd 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/ArrayTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/ArrayTest.java
@@ -47,7 +47,7 @@ public class ArrayTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
+ protected String getPackageNameOfTestSources() {
return Image.class.getPackage().getName();
}
}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/TemperatureSamples.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/TemperatureSamples.java
index 1b9f07ea95..2b136fe93a 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/TemperatureSamples.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/arraytype/TemperatureSamples.java
@@ -20,7 +20,7 @@ package org.hibernate.jpamodelgen.test.arraytype;
import javax.persistence.Entity;
/**
- * @author Hardy Feretnschik
+ * @author Hardy Ferentschik
*/
@Entity
public class TemperatureSamples {
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/elementcollection/ElementCollectionTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/elementcollection/ElementCollectionTest.java
index 17460c3b56..426fbb20a3 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/elementcollection/ElementCollectionTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/elementcollection/ElementCollectionTest.java
@@ -56,7 +56,7 @@ public class ElementCollectionTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
- return House.class.getPackage().getName();
+ protected String getPackageNameOfTestSources() {
+ return ElementCollectionTest.class.getPackage().getName();
}
}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java
index f178a65d01..eb84aec026 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generics/GenericsTest.java
@@ -35,7 +35,7 @@ public class GenericsTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
- return Parent.class.getPackage().getName();
+ protected String getPackageNameOfTestSources() {
+ return GenericsTest.class.getPackage().getName();
}
}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/inheritance/InheritanceTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/inheritance/InheritanceTest.java
index 4dc7777211..9d98ecf443 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/inheritance/InheritanceTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/inheritance/InheritanceTest.java
@@ -40,7 +40,7 @@ public class InheritanceTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
- return Customer.class.getPackage().getName();
+ protected String getPackageNameOfTestSources() {
+ return InheritanceTest.class.getPackage().getName();
}
}
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Car.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Car.java
new file mode 100644
index 0000000000..5cf7315b76
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Car.java
@@ -0,0 +1,42 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Car extends Vehicle {
+ private String make;
+
+ public int getHorsePower() {
+ return 0;
+ }
+
+ public void setHorsePower(int horsePower) {
+ }
+
+ public String getMake() {
+ return make;
+ }
+
+ public void setMake(String make) {
+ this.make = make;
+ }
+}
+
+
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Coordinates.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Coordinates.java
new file mode 100644
index 0000000000..62c8831346
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Coordinates.java
@@ -0,0 +1,31 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Embeddable;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Embeddable
+public class Coordinates {
+ public float longitude;
+ public float latitude;
+}
+
+
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Insurance.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Insurance.java
new file mode 100644
index 0000000000..1e954cc219
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Insurance.java
@@ -0,0 +1,47 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Embeddable;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Embeddable
+public class Insurance {
+ String number;
+ String policyNumber;
+
+ public String getPolicyNumber() {
+ return policyNumber;
+ }
+
+ public void setPolicyNumber(String policyNumber) {
+ this.policyNumber = policyNumber;
+ }
+
+ public String getNumber() {
+ return number;
+ }
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+}
+
+
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Location.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Location.java
new file mode 100644
index 0000000000..4792f913a3
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Location.java
@@ -0,0 +1,73 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Access;
+import javax.persistence.AccessType;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+@Access(AccessType.FIELD)
+public class Location {
+ @Id
+ private long id;
+ private String description;
+ // implicitly embedded
+ private Coordinates coordinates;
+ @Embedded
+ private ZeroCoordinates zeroCoordinates;
+
+ public Coordinates getCoordinates() {
+ return coordinates;
+ }
+
+ public void setCoordinates(Coordinates coordinates) {
+ this.coordinates = coordinates;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public ZeroCoordinates getZeroCoordinates() {
+ return zeroCoordinates;
+ }
+
+ public void setZeroCoordinates(ZeroCoordinates zeroCoordinates) {
+ this.zeroCoordinates = zeroCoordinates;
+ }
+}
+
+
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/MixedConfigurationTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/MixedConfigurationTest.java
new file mode 100644
index 0000000000..78c7733bc0
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/MixedConfigurationTest.java
@@ -0,0 +1,111 @@
+// $Id: MixedModeMappingTest.java 18683 2010-02-02 21:51:40Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.hibernate.jpamodelgen.test.util.CompilationTest;
+import org.hibernate.jpamodelgen.test.util.TestUtil;
+
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAbsenceOfFieldInMetamodelFor;
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertPresenceOfFieldInMetamodelFor;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class MixedConfigurationTest extends CompilationTest {
+ @Test
+ public void testDefaultAccessTypeApplied() {
+ assertMetamodelClassGeneratedFor( Vehicle.class );
+ assertMetamodelClassGeneratedFor( Car.class );
+
+ assertAbsenceOfFieldInMetamodelFor(
+ Car.class, "horsePower", "'horsePower' should not appear in metamodel since it does have no field."
+ );
+ }
+
+ @Test
+ public void testExplicitXmlConfiguredAccessTypeApplied() {
+ assertMetamodelClassGeneratedFor( Vehicle.class );
+ assertMetamodelClassGeneratedFor( Truck.class );
+
+ assertPresenceOfFieldInMetamodelFor(
+ Truck.class, "horsePower", "Property 'horsePower' has explicit access type and should be in metamodel"
+ );
+ assertAttributeTypeInMetaModelFor( Truck.class, "horsePower", Integer.class, "Wrong meta model type" );
+ }
+
+ @Test
+ public void testMixedConfiguration() {
+ assertMetamodelClassGeneratedFor( RentalCar.class );
+ assertMetamodelClassGeneratedFor( RentalCompany.class );
+
+ assertPresenceOfFieldInMetamodelFor(
+ RentalCar.class, "company", "Property 'company' should be included due to xml configuration"
+ );
+ assertAttributeTypeInMetaModelFor( RentalCar.class, "company", RentalCompany.class, "Wrong meta model type" );
+
+ assertPresenceOfFieldInMetamodelFor(
+ RentalCar.class, "insurance", "Property 'insurance' should be included since it is an embeddable"
+ );
+ assertAttributeTypeInMetaModelFor( RentalCar.class, "insurance", Insurance.class, "Wrong meta model type" );
+ }
+
+ @Test
+ public void testAccessTypeForXmlConfiguredEmbeddables() {
+ assertMetamodelClassGeneratedFor( Coordinates.class );
+ assertPresenceOfFieldInMetamodelFor(
+ Coordinates.class, "longitude", "field exists and should be in metamodel"
+ );
+ assertPresenceOfFieldInMetamodelFor( Coordinates.class, "latitude", "field exists and should be in metamodel" );
+
+ assertMetamodelClassGeneratedFor( ZeroCoordinates.class );
+ assertAbsenceOfFieldInMetamodelFor(
+ ZeroCoordinates.class,
+ "longitude",
+ "Field access should be used, but ZeroCoordinates does not define fields"
+ );
+ assertAbsenceOfFieldInMetamodelFor(
+ ZeroCoordinates.class,
+ "latitude",
+ "Field access should be used, but ZeroCoordinates does not define fields"
+ );
+ }
+
+ @Override
+ protected String getPackageNameOfTestSources() {
+ return MixedConfigurationTest.class.getPackage().getName();
+ }
+
+ @Override
+ protected Collection getOrmFiles() {
+ List ormFiles = new ArrayList();
+ String dir = TestUtil.fcnToPath( MixedConfigurationTest.class.getPackage().getName() );
+ ormFiles.add( dir + "/car.xml" );
+ ormFiles.add( dir + "/rentalcar.xml" );
+ ormFiles.add( dir + "/truck.xml" );
+ ormFiles.add( dir + "/coordinates.xml" );
+ return ormFiles;
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Person.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Person.java
new file mode 100644
index 0000000000..622e45e328
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Person.java
@@ -0,0 +1,49 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+public class Person {
+ @Id
+ @GeneratedValue
+ private long id;
+ private String name;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/RentalCar.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/RentalCar.java
new file mode 100644
index 0000000000..5f5b9e3b21
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/RentalCar.java
@@ -0,0 +1,71 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Entity;
+
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+public class RentalCar extends Car {
+ private RentalCompany company;
+
+ private CURRENTLY_HIRED hired;
+
+ private Character[] chassisNumber;
+
+ private Insurance insurance;
+
+ public RentalCompany getCompany() {
+ return company;
+ }
+
+ public void setCompany(RentalCompany company) {
+ this.company = company;
+ }
+
+ public Character[] getChassisNumber() {
+ return chassisNumber;
+ }
+
+ public void setChassisNumber(Character[] chassisNumber) {
+ this.chassisNumber = chassisNumber;
+ }
+
+ public CURRENTLY_HIRED getHired() {
+ return hired;
+ }
+
+ public void setHired(CURRENTLY_HIRED hired) {
+ this.hired = hired;
+ }
+
+ public Insurance getInsurance() {
+ return insurance;
+ }
+
+ public void setInsurance(Insurance insurance) {
+ this.insurance = insurance;
+ }
+
+ enum CURRENTLY_HIRED {
+ YES, NO
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/RentalCompany.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/RentalCompany.java
new file mode 100644
index 0000000000..e212d30c25
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/RentalCompany.java
@@ -0,0 +1,50 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+public class RentalCompany {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ private String name;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Truck.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Truck.java
new file mode 100644
index 0000000000..f39ef3f0e8
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Truck.java
@@ -0,0 +1,41 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Truck extends Vehicle {
+ private String make;
+
+ public int getHorsePower() {
+ return 0;
+ }
+
+ public void setHorsePower(int horsePower) {
+ }
+
+ public String getMake() {
+ return make;
+ }
+
+ public void setMake(String make) {
+ this.make = make;
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Vehicle.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Vehicle.java
new file mode 100644
index 0000000000..f05fb2261f
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/Vehicle.java
@@ -0,0 +1,43 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+public class Vehicle {
+ // default access type for classes in this hierarchy is FIELD
+ @Id
+ @GeneratedValue
+ private long id;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+}
+
+
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/XmlMetaCompleteTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/XmlMetaCompleteTest.java
new file mode 100644
index 0000000000..43e2ea6801
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/XmlMetaCompleteTest.java
@@ -0,0 +1,53 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.hibernate.jpamodelgen.test.util.CompilationTest;
+import org.hibernate.jpamodelgen.test.util.TestUtil;
+
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAbsenceOfFieldInMetamodelFor;
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class XmlMetaCompleteTest extends CompilationTest {
+ @Test
+ public void testXmlConfiguredEmbeddedClassGenerated() {
+ assertMetamodelClassGeneratedFor( Person.class );
+ assertAbsenceOfFieldInMetamodelFor( Person.class, "name" );
+ }
+
+ @Override
+ protected String getPackageNameOfTestSources() {
+ return XmlMetaCompleteTest.class.getPackage().getName();
+ }
+
+ @Override
+ protected Collection getOrmFiles() {
+ List ormFiles = new ArrayList();
+ ormFiles.add( TestUtil.fcnToPath( XmlMetaCompleteTest.class.getPackage().getName() ) + "/orm.xml" );
+ return ormFiles;
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/ZeroCoordinates.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/ZeroCoordinates.java
new file mode 100644
index 0000000000..a965567876
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/mixedmode/ZeroCoordinates.java
@@ -0,0 +1,41 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.mixedmode;
+
+import javax.persistence.Embeddable;
+
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Embeddable
+public class ZeroCoordinates {
+ public float getLatitude() {
+ return 0f;
+ }
+
+ public void setLatitude(float latitude) {
+ }
+
+ public float getLongitude() {
+ return 0f;
+ }
+
+ public void setLongitude(float longitude) {
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/DeskWithRawType.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/DeskWithRawType.java
similarity index 96%
rename from tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/DeskWithRawType.java
rename to tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/DeskWithRawType.java
index 2a00521ed4..9498391dfe 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/DeskWithRawType.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/DeskWithRawType.java
@@ -1,4 +1,4 @@
-package org.hibernate.jpamodelgen.test.rawTypes;
+package org.hibernate.jpamodelgen.test.rawtypes;
import java.util.Collection;
import javax.persistence.Basic;
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/EmployeeWithRawType.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/EmployeeWithRawType.java
similarity index 94%
rename from tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/EmployeeWithRawType.java
rename to tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/EmployeeWithRawType.java
index 599b7f43a6..d4ef6080d3 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/EmployeeWithRawType.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/EmployeeWithRawType.java
@@ -1,4 +1,4 @@
-package org.hibernate.jpamodelgen.test.rawTypes;
+package org.hibernate.jpamodelgen.test.rawtypes;
import java.util.Collection;
import javax.persistence.Basic;
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/RawTypesTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/RawTypesTest.java
similarity index 88%
rename from tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/RawTypesTest.java
rename to tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/RawTypesTest.java
index be140b7529..436d7bc6f3 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawTypes/RawTypesTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/rawtypes/RawTypesTest.java
@@ -1,4 +1,4 @@
-// $Id$
+// $Id: RawTypesTest.java 18664 2010-01-28 16:56:51Z hardy.ferentschik $
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.hibernate.jpamodelgen.test.rawTypes;
+package org.hibernate.jpamodelgen.test.rawtypes;
import org.testng.annotations.Test;
@@ -35,7 +35,7 @@ public class RawTypesTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
+ protected String getPackageNameOfTestSources() {
return DeskWithRawType.class.getPackage().getName();
}
}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/CompilationTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/CompilationTest.java
index a830836864..5d4d51c48c 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/CompilationTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/CompilationTest.java
@@ -19,34 +19,47 @@ package org.hibernate.jpamodelgen.test.util;
import java.io.File;
import java.io.FilenameFilter;
-import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeClass;
+
+import org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor;
+
import static org.testng.FileAssert.fail;
/**
* @author Hardy Ferentschik
*/
public abstract class CompilationTest {
-
+ private static final Logger log = LoggerFactory.getLogger( CompilationTest.class );
private static final String PATH_SEPARATOR = System.getProperty( "file.separator" );
+ private static final String ANNOTATION_PROCESSOR_OPTION_PREFIX = "-A";
+ private static final String SOURCE_BASE_DIR_PROPERTY = "sourceBaseDir";
+ private static final String OUT_BASE_DIR_PROPERTY = "outBaseDir";
private static final String sourceBaseDir;
private static final String outBaseDir;
static {
- String tmp = System.getProperty( "sourceBaseDir" );
+ String tmp = System.getProperty( SOURCE_BASE_DIR_PROPERTY );
if ( tmp == null ) {
fail( "The system property sourceBaseDir has to be set and point to the base directory of the test java sources." );
}
sourceBaseDir = tmp;
- tmp = System.getProperty( "outBaseDir" );
+ tmp = System.getProperty( OUT_BASE_DIR_PROPERTY );
if ( tmp == null ) {
fail( "The system property outBaseDir has to be set and point to the base directory of the test output directory." );
}
@@ -54,17 +67,11 @@ public abstract class CompilationTest {
}
public CompilationTest() {
- try {
- TestUtil.clearOutputFolder();
- compile();
- }
- catch ( Exception e ) {
- e.printStackTrace( );
- fail( "Unable to compile test sources. " + e.getMessage() );
- }
}
- private void compile() throws IOException {
+ @BeforeClass
+ protected void compile() throws Exception {
+ TestUtil.deleteGeneratedSourceFiles( new File( outBaseDir ) );
List options = createJavaOptions();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
@@ -82,6 +89,7 @@ public abstract class CompilationTest {
compilationUnits = fileManager.getJavaFileObjectsFromFiles(
getCompilationUnits( outBaseDir )
);
+ options.add( "-proc:none" ); // for the second compile skip the processor
compileSources( options, compiler, diagnostics, fileManager, compilationUnits );
fileManager.close();
}
@@ -91,24 +99,46 @@ public abstract class CompilationTest {
null, fileManager, diagnostics, options, null, compilationUnits
);
task.call();
-// for ( Diagnostic diagnostic : diagnostics.getDiagnostics() ) {
-// System.out.println( diagnostic.getMessage( null ) );
-// }
+ for ( Diagnostic diagnostic : diagnostics.getDiagnostics() ) {
+ log.debug( diagnostic.getMessage( null ) );
+ }
}
private List createJavaOptions() {
- // TODO
- // passing any other options as -d seems to throw IllegalArgumentExceptions. I would like to set -s for example
- // in order to see whether recursive recompilation would work then. Also '-proc only' could be interesting
List options = new ArrayList();
options.add( "-d" );
options.add( outBaseDir );
+
+ // pass orm files if specified
+ if ( !getOrmFiles().isEmpty() ) {
+ StringBuilder builder = new StringBuilder();
+ builder.append( ANNOTATION_PROCESSOR_OPTION_PREFIX );
+ builder.append( JPAMetaModelEntityProcessor.ORM_XML_OPTION );
+ builder.append( "=" );
+ for ( String ormFile : getOrmFiles() ) {
+ builder.append( ormFile );
+ builder.append( "," );
+ }
+ builder.deleteCharAt( builder.length() - 1 );
+ options.add( builder.toString() );
+ }
+
+ // add any additional options specified by the test
+ for ( Map.Entry entry : getProcessorOptions().entrySet() ) {
+ StringBuilder builder = new StringBuilder();
+ builder.append( ANNOTATION_PROCESSOR_OPTION_PREFIX );
+ builder.append( entry.getKey() );
+ builder.append( "=" );
+ builder.append( entry.getValue() );
+ options.add( builder.toString() );
+ }
+ options.add( "-Adebug=true" );
return options;
}
private List getCompilationUnits(String baseDir) {
List javaFiles = new ArrayList();
- String packageDirName = baseDir + PATH_SEPARATOR + getTestPackage().replace( ".", PATH_SEPARATOR );
+ String packageDirName = baseDir + PATH_SEPARATOR + getPackageNameOfTestSources().replace( ".", PATH_SEPARATOR );
File packageDir = new File( packageDirName );
FilenameFilter javaFileFilter = new FilenameFilter() {
@Override
@@ -117,16 +147,22 @@ public abstract class CompilationTest {
}
};
final File[] files = packageDir.listFiles( javaFileFilter );
- if (files == null) {
+ if ( files == null ) {
throw new RuntimeException( "Cannot find package directory (is your base dir correct?): " + packageDirName );
}
- for ( File file : files ) {
- javaFiles.add( file );
- }
+ javaFiles.addAll( Arrays.asList( files ) );
return javaFiles;
}
- abstract protected String getTestPackage();
+ abstract protected String getPackageNameOfTestSources();
+
+ protected Map getProcessorOptions() {
+ return Collections.emptyMap();
+ }
+
+ protected Collection getOrmFiles() {
+ return Collections.emptyList();
+ }
}
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java
index 14fa9f792e..c89e8d51b8 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java
@@ -18,11 +18,14 @@
package org.hibernate.jpamodelgen.test.util;
import java.io.File;
+import java.io.FileFilter;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.testng.Assert;
import static org.testng.Assert.assertEquals;
@@ -34,8 +37,9 @@ import static org.testng.FileAssert.fail;
* @author Hardy Ferentschik
*/
public class TestUtil {
-
+ private static final Logger log = LoggerFactory.getLogger( TestUtil.class );
private static final String PATH_SEPARATOR = System.getProperty( "file.separator" );
+ private static final String PACKAGE_SEPARATOR = ".";
private static final String META_MODEL_CLASS_POSTFIX = "_";
private static final String outBaseDir;
@@ -50,11 +54,23 @@ public class TestUtil {
private TestUtil() {
}
- public static void clearOutputFolder() {
- File outDir = new File( outBaseDir );
- File[] files = outDir.listFiles();
- for ( File file : files ) {
- file.delete();
+ public static void deleteGeneratedSourceFiles(File path) {
+ if ( path.exists() ) {
+ File[] files = path.listFiles( new MetaModelFilenameFilter() );
+ for ( File file : files ) {
+ if ( file.isDirectory() ) {
+ deleteGeneratedSourceFiles( file );
+ }
+ else {
+ boolean success = file.delete();
+ if ( success ) {
+ log.debug( file.getAbsolutePath() + " deleted successfully" );
+ }
+ else {
+ log.debug( "Failed to delete generated source file" + file.getAbsolutePath() );
+ }
+ }
+ }
}
}
@@ -78,7 +94,7 @@ public class TestUtil {
assertNotNull( clazz, "Class parameter cannot be null" );
String metaModelClassName = clazz.getName() + META_MODEL_CLASS_POSTFIX;
// generate the file name
- String fileName = metaModelClassName.replace( ".", PATH_SEPARATOR );
+ String fileName = metaModelClassName.replace( PACKAGE_SEPARATOR, PATH_SEPARATOR );
fileName = fileName.concat( ".java" );
File sourceFile = new File( outBaseDir + PATH_SEPARATOR + fileName );
assertFalse( sourceFile.exists(), "There should be no source file: " + fileName );
@@ -98,14 +114,18 @@ public class TestUtil {
public static void assertAttributeTypeInMetaModelFor(Class> clazz, String fieldName, Class> expectedType, String errorString) {
Field field = getFieldFromMetamodelFor( clazz, fieldName );
- assertNotNull( field );
+ assertNotNull( field, "Cannot find field '" + fieldName + "' in " + clazz.getName() );
ParameterizedType type = ( ParameterizedType ) field.getGenericType();
Type actualType = type.getActualTypeArguments()[1];
if ( expectedType.isArray() ) {
expectedType = expectedType.getComponentType();
actualType = ( ( GenericArrayType ) actualType ).getGenericComponentType();
}
- assertEquals( actualType, expectedType, errorString );
+ assertEquals(
+ actualType,
+ expectedType,
+ "Types do not match: " + errorString
+ );
}
public static void assertMapAttributesInMetaModelFor(Class> clazz, String fieldName, Class> expectedMapKey, Class> expectedMapValue, String errorString) {
@@ -157,6 +177,23 @@ public class TestUtil {
}
return field;
}
+
+ public static String fcnToPath(String fcn) {
+ return fcn.replace( PACKAGE_SEPARATOR, PATH_SEPARATOR );
+ }
+
+ private static class MetaModelFilenameFilter implements FileFilter {
+ @Override
+ public boolean accept(File pathName) {
+ if ( pathName.isDirectory() ) {
+ return true;
+ }
+ else {
+ return pathName.getAbsolutePath().endsWith( "_.java" )
+ || pathName.getAbsolutePath().endsWith( "_.class" );
+ }
+ }
+ }
}
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/IgnoreInvalidXmlTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/IgnoreInvalidXmlTest.java
new file mode 100644
index 0000000000..54ef06b30e
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/IgnoreInvalidXmlTest.java
@@ -0,0 +1,57 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jpamodelgen.test.xmlmapped;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.hibernate.jpamodelgen.test.util.CompilationTest;
+import org.hibernate.jpamodelgen.test.util.TestUtil;
+
+import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class IgnoreInvalidXmlTest extends CompilationTest {
+ @Test
+ public void testInvalidXmlFilesGetIgnored() {
+ // this is only a indirect test, but if the invalid xml files would cause the processor to abort the
+ // meta class would not have been generated
+ assertMetamodelClassGeneratedFor( Superhero.class );
+ }
+
+ @Override
+ protected String getPackageNameOfTestSources() {
+ return IgnoreInvalidXmlTest.class.getPackage().getName();
+ }
+
+ @Override
+ protected Collection getOrmFiles() {
+ List ormFiles = new ArrayList();
+ String packageName = TestUtil.fcnToPath( IgnoreInvalidXmlTest.class.getPackage().getName() );
+ ormFiles.add( packageName + "/orm.xml" );
+ ormFiles.add( packageName + "/jpa1-orm.xml" );
+ ormFiles.add( packageName + "/malformed-mapping.xml" );
+ ormFiles.add( packageName + "/non-existend-class.xml" );
+ return ormFiles;
+ }
+}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/LivingBeing.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/LivingBeing.java
index a8de6332ad..2a2d0d3355 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/LivingBeing.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/LivingBeing.java
@@ -21,14 +21,14 @@ package org.hibernate.jpamodelgen.test.xmlmapped;
* @author Hardy Ferentschik
*/
public class LivingBeing {
- boolean isReallyAlive;
+ boolean reallyAlive;
public boolean isReallyAlive() {
- return isReallyAlive;
+ return reallyAlive;
}
public void setReallyAlive(boolean reallyAlive) {
- isReallyAlive = reallyAlive;
+ this.reallyAlive = reallyAlive;
}
public int nonPersistent() {
diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/XmlMappingTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/XmlMappingTest.java
index 5f7299e3a9..9e79ee74f5 100644
--- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/XmlMappingTest.java
+++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/xmlmapped/XmlMappingTest.java
@@ -17,9 +17,14 @@
*/
package org.hibernate.jpamodelgen.test.xmlmapped;
+import java.util.HashMap;
+import java.util.Map;
+
import org.testng.annotations.Test;
+import org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor;
import org.hibernate.jpamodelgen.test.util.CompilationTest;
+import org.hibernate.jpamodelgen.test.util.TestUtil;
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
@@ -84,7 +89,6 @@ public class XmlMappingTest extends CompilationTest {
assertAttributeTypeInMetaModelFor( Boy.class, "nickNames", String.class, "target class overridden in xml" );
}
-
@Test
public void testClassHierarchy() {
assertMetamodelClassGeneratedFor( Mammal.class );
@@ -98,7 +102,17 @@ public class XmlMappingTest extends CompilationTest {
}
@Override
- protected String getTestPackage() {
- return Address.class.getPackage().getName();
+ protected String getPackageNameOfTestSources() {
+ return XmlMappingTest.class.getPackage().getName();
+ }
+
+ @Override
+ protected Map getProcessorOptions() {
+ Map properties = new HashMap();
+ properties.put(
+ JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION,
+ TestUtil.fcnToPath( XmlMappingTest.class.getPackage().getName() ) + "/persistence.xml"
+ );
+ return properties;
}
}
\ No newline at end of file
diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml b/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml
index b755fe4208..d52a1685e4 100644
--- a/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml
+++ b/tooling/metamodel-generator/src/test/resources/META-INF/persistence.xml
@@ -1,15 +1,8 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence.xsd" version="2.0">
Test persistence unit
- /META-INF/dummy.xml
- /META-INF/malformed-mapping-xml.xml
- /META-INF/jpa1-orm.xml
- /org/hibernate/jpamodelgen/test/xmlmapped/address.xml
- /org/hibernate/jpamodelgen/test/xmlmapped/building.xml
- /org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml
- /org/hibernate/jpamodelgen/test/xmlmapped/boy.xml
diff --git a/tooling/metamodel-generator/src/test/resources/log4j.properties b/tooling/metamodel-generator/src/test/resources/log4j.properties
new file mode 100644
index 0000000000..2be85f43d4
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/log4j.properties
@@ -0,0 +1,24 @@
+### direct log messages to stdout ###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+### direct messages to file hibernate.log ###
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.File=hibernate.log
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+### direct messages to socket - chainsaw ###
+log4j.appender.socket=org.apache.log4j.net.SocketAppender
+log4j.appender.socket.remoteHost=localhost
+log4j.appender.socket.port=4560
+log4j.appender.socket.locationInfo=true
+
+
+### set log levels - for more verbose logging change 'info' to 'debug' ###
+log4j.rootLogger=debug, stdout
+
+#log4j.logger.org.hibernate.jpamodelgen.test.util.CompilationTest=trace
+
diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/orm.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/accesstype/orm.xml
similarity index 94%
rename from tooling/metamodel-generator/src/test/resources/META-INF/orm.xml
rename to tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/accesstype/orm.xml
index 9b504d313f..66627ef8bd 100644
--- a/tooling/metamodel-generator/src/test/resources/META-INF/orm.xml
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/accesstype/orm.xml
@@ -6,7 +6,6 @@
version="2.0"
>
org.hibernate.jpamodelgen.test.accesstype
-
@@ -23,7 +22,6 @@
-
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/car.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/car.xml
new file mode 100644
index 0000000000..534a51dcbf
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/car.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ foo.bar
+
+
+
+
+
+
+
+
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/coordinates.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/coordinates.xml
new file mode 100644
index 0000000000..a2c9ec3368
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/coordinates.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/orm.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/orm.xml
new file mode 100644
index 0000000000..505ac838b9
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/orm.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ org.hibernate.jpamodelgen.test.mixedmode
+
+
+
+
+
+
+
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/rentalcar.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/rentalcar.xml
new file mode 100644
index 0000000000..1ccfff0855
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/rentalcar.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ foo.bar
+
+
+
+
+
+
+
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/truck.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/truck.xml
new file mode 100644
index 0000000000..14d81abfaa
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/mixedmode/truck.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ foo.bar
+
+
+
+
+
+
+
+
diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/jpa1-orm.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/jpa1-orm.xml
similarity index 100%
rename from tooling/metamodel-generator/src/test/resources/META-INF/jpa1-orm.xml
rename to tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/jpa1-orm.xml
diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/malformed-mapping-xml.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/malformed-mapping.xml
similarity index 100%
rename from tooling/metamodel-generator/src/test/resources/META-INF/malformed-mapping-xml.xml
rename to tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/malformed-mapping.xml
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml
index 57216ccd1c..1b032c4b5b 100644
--- a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml
@@ -8,7 +8,7 @@
org.hibernate.jpamodelgen.test.xmlmapped
-
+
diff --git a/tooling/metamodel-generator/src/test/resources/META-INF/dummy.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/non-existend-class.xml
similarity index 100%
rename from tooling/metamodel-generator/src/test/resources/META-INF/dummy.xml
rename to tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/non-existend-class.xml
diff --git a/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/persistence.xml b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/persistence.xml
new file mode 100644
index 0000000000..611a222b87
--- /dev/null
+++ b/tooling/metamodel-generator/src/test/resources/org/hibernate/jpamodelgen/test/xmlmapped/persistence.xml
@@ -0,0 +1,11 @@
+
+
+
+ /org/hibernate/jpamodelgen/test/xmlmapped/address.xml
+ /org/hibernate/jpamodelgen/test/xmlmapped/building.xml
+ /org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml
+ /org/hibernate/jpamodelgen/test/xmlmapped/boy.xml
+
+
diff --git a/tooling/metamodel-generator/src/test/suite/unit-tests.xml b/tooling/metamodel-generator/src/test/suite/unit-tests.xml
index 91528da7bc..1115776fec 100644
--- a/tooling/metamodel-generator/src/test/suite/unit-tests.xml
+++ b/tooling/metamodel-generator/src/test/suite/unit-tests.xml
@@ -8,7 +8,8 @@
-
+
+