METAGEN-9 Extended infrastructure to allow the specification of persistence.xml
This commit is contained in:
parent
f82b6a7d3c
commit
813339a647
|
@ -24,6 +24,17 @@
|
||||||
<classifier>jdk15</classifier>
|
<classifier>jdk15</classifier>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.5.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
<version>1.5.6</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
|
@ -150,6 +161,7 @@
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>2.4.3</version>
|
<version>2.4.3</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||||
<systemProperties>
|
<systemProperties>
|
||||||
<property>
|
<property>
|
||||||
<name>sourceBaseDir</name>
|
<name>sourceBaseDir</name>
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,9 @@ import javax.lang.model.type.TypeMirror;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
import javax.tools.FileObject;
|
import javax.tools.FileObject;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
||||||
|
import org.hibernate.jpamodelgen.model.MetaEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
|
@ -112,8 +115,8 @@ public class ClassWriter {
|
||||||
//F..king Ch...t Have those people used their horrible APIs even once?
|
//F..king Ch...t Have those people used their horrible APIs even once?
|
||||||
final Element superClassElement = ( ( DeclaredType ) superClass ).asElement();
|
final Element superClassElement = ( ( DeclaredType ) superClass ).asElement();
|
||||||
String superClassName = ( ( TypeElement ) superClassElement ).getQualifiedName().toString();
|
String superClassName = ( ( TypeElement ) superClassElement ).getQualifiedName().toString();
|
||||||
if ( context.getMetaEntitiesToProcess().containsKey( superClassName )
|
if ( context.containsMetaEntity( superClassName )
|
||||||
|| context.getMetaSuperclassAndEmbeddableToProcess().containsKey( superClassName ) ) {
|
|| context.containsMetaSuperclassOrEmbeddable( superClassName ) ) {
|
||||||
pw.print( " extends " + superClassName + "_" );
|
pw.print( " extends " + superClassName + "_" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,20 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.util.Elements;
|
||||||
|
import javax.lang.model.util.Types;
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
|
import org.hibernate.jpamodelgen.model.MetaEntity;
|
||||||
import org.hibernate.jpamodelgen.util.TypeUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
|
@ -35,84 +38,115 @@ import org.hibernate.jpamodelgen.util.TypeUtils;
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
public class Context {
|
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<String, MetaEntity> metaEntities = new HashMap<String, MetaEntity>();
|
||||||
|
private final Map<String, MetaEntity> metaSuperclassAndEmbeddable = new HashMap<String, MetaEntity>();
|
||||||
|
private final Map<String, AccessTypeInformation> accessTypeInformation = new HashMap<String, AccessTypeInformation>();
|
||||||
|
|
||||||
private final Map<String, MetaEntity> metaEntitiesToProcess = new HashMap<String, MetaEntity>();
|
private final ProcessingEnvironment pe;
|
||||||
private final Map<String, MetaEntity> metaSuperclassAndEmbeddableToProcess = new HashMap<String, MetaEntity>();
|
private final boolean logDebug;
|
||||||
|
private final String persistenceXmlLocation;
|
||||||
|
|
||||||
private ProcessingEnvironment pe;
|
private final List<String> ormXmlFiles;
|
||||||
private boolean logDebug = false;
|
private boolean isPersistenceUnitCompletelyXmlConfigured;
|
||||||
|
private AccessType persistenceUnitDefaultAccessType;
|
||||||
//used to cache access types
|
|
||||||
private Map<TypeElement, AccessTypeHolder> accessTypes = new HashMap<TypeElement, AccessTypeHolder>();
|
|
||||||
private Set<String> elementsAlreadyProcessed = new HashSet<String>();
|
|
||||||
|
|
||||||
private static class AccessTypeHolder {
|
|
||||||
public AccessType elementAccessType;
|
|
||||||
public AccessType hierarchyAccessType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context(ProcessingEnvironment pe) {
|
public Context(ProcessingEnvironment pe) {
|
||||||
this.pe = pe;
|
this.pe = pe;
|
||||||
String debugParam = pe.getOptions().get( JPAMetaModelEntityProcessor.DEBUG_OPTION );
|
|
||||||
if ( debugParam != null && "true".equals( debugParam ) ) {
|
if ( pe.getOptions().get( JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION ) != null ) {
|
||||||
logDebug = true;
|
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<String>();
|
||||||
|
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() {
|
public ProcessingEnvironment getProcessingEnvironment() {
|
||||||
return pe;
|
return pe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, MetaEntity> getMetaEntitiesToProcess() {
|
public Elements getElementUtils() {
|
||||||
return metaEntitiesToProcess;
|
return pe.getElementUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, MetaEntity> getMetaSuperclassAndEmbeddableToProcess() {
|
public Types getTypeUtils() {
|
||||||
return metaSuperclassAndEmbeddableToProcess;
|
return pe.getTypeUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAccessType(TypeElement element, AccessType accessType) {
|
public String getPersistenceXmlLocation() {
|
||||||
AccessTypeHolder typeHolder = accessTypes.get( element );
|
return persistenceXmlLocation;
|
||||||
if ( typeHolder == null ) {
|
|
||||||
typeHolder = new AccessTypeHolder();
|
|
||||||
accessTypes.put( element, typeHolder );
|
|
||||||
}
|
|
||||||
typeHolder.elementAccessType = accessType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAccessTypeForHierarchy(TypeElement element, AccessType accessType) {
|
public List<String> getOrmXmlFiles() {
|
||||||
AccessTypeHolder typeHolder = accessTypes.get( element );
|
return ormXmlFiles;
|
||||||
if ( typeHolder == null ) {
|
|
||||||
typeHolder = new AccessTypeHolder();
|
|
||||||
accessTypes.put( element, typeHolder );
|
|
||||||
}
|
|
||||||
typeHolder.hierarchyAccessType = accessType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessType getAccessType(TypeElement element) {
|
public boolean containsMetaEntity(String fqcn) {
|
||||||
final AccessTypeHolder typeHolder = accessTypes.get( element );
|
return metaEntities.containsKey( fqcn );
|
||||||
return typeHolder != null ? typeHolder.elementAccessType : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessType getDefaultAccessTypeForHerarchy(TypeElement element) {
|
public MetaEntity getMetaEntity(String fqcn) {
|
||||||
final AccessTypeHolder typeHolder = accessTypes.get( element );
|
return metaEntities.get( fqcn );
|
||||||
return typeHolder != null ? typeHolder.hierarchyAccessType : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getElementsAlreadyProcessed() {
|
public Collection<MetaEntity> getMetaEntities() {
|
||||||
return elementsAlreadyProcessed;
|
return metaEntities.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
//only process Embeddable or Superclass
|
public void addMetaEntity(String fcqn, MetaEntity metaEntity) {
|
||||||
//does not work for Entity (risk of circularity)
|
metaEntities.put( fcqn, metaEntity );
|
||||||
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 );
|
public boolean containsMetaSuperclassOrEmbeddable(String fqcn) {
|
||||||
elementsAlreadyProcessed.add( element.getQualifiedName().toString() );
|
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<MetaEntity> 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) {
|
public void logMessage(Diagnostic.Kind type, String message) {
|
||||||
|
@ -121,4 +155,33 @@ public class Context {
|
||||||
}
|
}
|
||||||
pe.getMessager().printMessage( type, message );
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.model.ImportContext;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
|
@ -39,6 +39,7 @@ public class ImportContextImpl implements ImportContext {
|
||||||
String basePackage = "";
|
String basePackage = "";
|
||||||
|
|
||||||
private static final Map<String, String> PRIMITIVES = new HashMap<String, String>();
|
private static final Map<String, String> PRIMITIVES = new HashMap<String, String>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
PRIMITIVES.put( "char", "Character" );
|
PRIMITIVES.put( "char", "Character" );
|
||||||
|
|
||||||
|
@ -61,13 +62,13 @@ public class ImportContextImpl implements ImportContext {
|
||||||
/**
|
/**
|
||||||
* Add fqcn to the import list. Returns fqcn as needed in source code.
|
* Add fqcn to the import list. Returns fqcn as needed in source code.
|
||||||
* Attempts to handle fqcn with array and generics references.
|
* Attempts to handle fqcn with array and generics references.
|
||||||
*
|
* <p/>
|
||||||
* e.g.
|
* e.g.
|
||||||
* java.util.Collection<org.marvel.Hulk> imports java.util.Collection and returns Collection
|
* java.util.Collection<org.marvel.Hulk> imports java.util.Collection and returns Collection
|
||||||
* org.marvel.Hulk[] imports org.marvel.Hulk and returns Hulk
|
* org.marvel.Hulk[] imports org.marvel.Hulk and returns Hulk
|
||||||
*
|
*
|
||||||
|
* @param fqcn Fully qualified class name
|
||||||
*
|
*
|
||||||
* @param fqcn
|
|
||||||
* @return import string
|
* @return import string
|
||||||
*/
|
*/
|
||||||
public String importType(String fqcn) {
|
public String importType(String fqcn) {
|
||||||
|
@ -76,43 +77,46 @@ public class ImportContextImpl implements ImportContext {
|
||||||
//if(fqcn==null) return "/** (null) **/";
|
//if(fqcn==null) return "/** (null) **/";
|
||||||
|
|
||||||
String additionalTypePart = null;
|
String additionalTypePart = null;
|
||||||
if(fqcn.indexOf('<')>=0) {
|
if ( fqcn.indexOf( '<' ) >= 0 ) {
|
||||||
additionalTypePart = result.substring(fqcn.indexOf('<'));
|
additionalTypePart = result.substring( fqcn.indexOf( '<' ) );
|
||||||
result = result.substring(0,fqcn.indexOf('<'));
|
result = result.substring( 0, fqcn.indexOf( '<' ) );
|
||||||
fqcn = result;
|
fqcn = result;
|
||||||
} else if(fqcn.indexOf('[')>=0) {
|
}
|
||||||
additionalTypePart = result.substring(fqcn.indexOf('['));
|
else if ( fqcn.indexOf( '[' ) >= 0 ) {
|
||||||
result = result.substring(0,fqcn.indexOf('['));
|
additionalTypePart = result.substring( fqcn.indexOf( '[' ) );
|
||||||
|
result = result.substring( 0, fqcn.indexOf( '[' ) );
|
||||||
fqcn = result;
|
fqcn = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String pureFqcn = fqcn.replace( '$', '.' );
|
String pureFqcn = fqcn.replace( '$', '.' );
|
||||||
|
|
||||||
boolean canBeSimple = true;
|
boolean canBeSimple;
|
||||||
|
|
||||||
|
String simpleName = unqualify( fqcn );
|
||||||
String simpleName = unqualify(fqcn);
|
if ( simpleNames.containsKey( simpleName ) ) {
|
||||||
if(simpleNames.containsKey(simpleName)) {
|
String existingFqcn = simpleNames.get( simpleName );
|
||||||
String existingFqcn = simpleNames.get(simpleName);
|
if ( existingFqcn.equals( pureFqcn ) ) {
|
||||||
if(existingFqcn.equals(pureFqcn)) {
|
|
||||||
canBeSimple = true;
|
canBeSimple = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
canBeSimple = false;
|
canBeSimple = false;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
canBeSimple = true;
|
canBeSimple = true;
|
||||||
simpleNames.put(simpleName, pureFqcn);
|
simpleNames.put( simpleName, pureFqcn );
|
||||||
imports.add( pureFqcn );
|
imports.add( pureFqcn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( inSamePackage(fqcn) || (imports.contains( pureFqcn ) && canBeSimple) ) {
|
if ( inSamePackage( fqcn ) || ( imports.contains( pureFqcn ) && canBeSimple ) ) {
|
||||||
result = unqualify( result ); // dequalify
|
result = unqualify( result ); // de-qualify
|
||||||
} else if ( inJavaLang( fqcn ) ) {
|
}
|
||||||
|
else if ( inJavaLang( fqcn ) ) {
|
||||||
result = result.substring( "java.lang.".length() );
|
result = result.substring( "java.lang.".length() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if(additionalTypePart!=null) {
|
if ( additionalTypePart != null ) {
|
||||||
result = result + additionalTypePart;
|
result = result + additionalTypePart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,12 +126,13 @@ public class ImportContextImpl implements ImportContext {
|
||||||
|
|
||||||
public String staticImport(String fqcn, String member) {
|
public String staticImport(String fqcn, String member) {
|
||||||
String local = fqcn + "." + member;
|
String local = fqcn + "." + member;
|
||||||
imports.add(local);
|
imports.add( local );
|
||||||
staticImports.add(local);
|
staticImports.add( local );
|
||||||
|
|
||||||
if(member.equals("*")) {
|
if ( member.equals( "*" ) ) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +148,7 @@ public class ImportContextImpl implements ImportContext {
|
||||||
private boolean inSamePackage(String className) {
|
private boolean inSamePackage(String className) {
|
||||||
String other = qualifier( className );
|
String other = qualifier( className );
|
||||||
return other == basePackage
|
return other == basePackage
|
||||||
|| (other != null && other.equals( basePackage ) );
|
|| ( other != null && other.equals( basePackage ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean inJavaLang(String className) {
|
private boolean inJavaLang(String className) {
|
||||||
|
@ -153,32 +158,33 @@ public class ImportContextImpl implements ImportContext {
|
||||||
public String generateImports() {
|
public String generateImports() {
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
|
|
||||||
for ( Iterator<String> imps = imports.iterator(); imps.hasNext(); ) {
|
for ( String next : imports ) {
|
||||||
String next = imps.next();
|
if ( isPrimitive( next ) || inDefaultPackage( next ) || inJavaLang( next ) || inSamePackage( next ) ) {
|
||||||
if(isPrimitive(next) || inDefaultPackage(next) || inJavaLang(next) || inSamePackage(next)) {
|
|
||||||
// dont add automatically "imported" stuff
|
// dont add automatically "imported" stuff
|
||||||
} else {
|
}
|
||||||
if(staticImports.contains(next)) {
|
else {
|
||||||
buf.append("import static " + next + ";\r\n");
|
if ( staticImports.contains( next ) ) {
|
||||||
} else {
|
buf.append( "import static " + next + ";\r\n" );
|
||||||
buf.append("import " + 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();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String unqualify(String qualifiedName) {
|
public static String unqualify(String qualifiedName) {
|
||||||
int loc = qualifiedName.lastIndexOf(".");
|
int loc = qualifiedName.lastIndexOf( "." );
|
||||||
return ( loc < 0 ) ? qualifiedName : qualifiedName.substring( qualifiedName.lastIndexOf(".") + 1 );
|
return ( loc < 0 ) ? qualifiedName : qualifiedName.substring( qualifiedName.lastIndexOf( "." ) + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String qualifier(String qualifiedName) {
|
public static String qualifier(String qualifiedName) {
|
||||||
int loc = qualifiedName.lastIndexOf(".");
|
int loc = qualifiedName.lastIndexOf( "." );
|
||||||
return ( loc < 0 ) ? "" : qualifiedName.substring( 0, loc );
|
return ( loc < 0 ) ? "" : qualifiedName.substring( 0, loc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.processing.AbstractProcessor;
|
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.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.element.TypeElement;
|
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.Embeddable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.annotation.AnnotationEmbeddable;
|
||||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
|
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.util.TypeUtils;
|
||||||
import org.hibernate.jpamodelgen.xml.XmlParser;
|
import org.hibernate.jpamodelgen.xml.XmlParser;
|
||||||
|
|
||||||
|
@ -49,9 +61,15 @@ import static javax.lang.model.SourceVersion.RELEASE_6;
|
||||||
*/
|
*/
|
||||||
@SupportedAnnotationTypes("*")
|
@SupportedAnnotationTypes("*")
|
||||||
@SupportedSourceVersion(RELEASE_6)
|
@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 class JPAMetaModelEntityProcessor extends AbstractProcessor {
|
||||||
public static final String DEBUG_OPTION = "debug";
|
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 static final Boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = Boolean.FALSE;
|
||||||
|
|
||||||
private boolean xmlProcessed = false;
|
private boolean xmlProcessed = false;
|
||||||
|
@ -78,75 +96,190 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
if ( !xmlProcessed ) {
|
if ( !xmlProcessed ) {
|
||||||
XmlParser parser = new XmlParser( context );
|
XmlParser parser = new XmlParser( context );
|
||||||
parser.parsePersistenceXml();
|
parser.parseXml();
|
||||||
xmlProcessed = true;
|
xmlProcessed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !hostJPAAnnotations( annotations ) ) {
|
if ( context.isPersistenceUnitCompletelyXmlConfigured() ) {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Current processing round does not contain entities" );
|
context.logMessage(
|
||||||
|
Diagnostic.Kind.OTHER,
|
||||||
|
"Skipping the processing of annotations since persistence unit is purely xml configured."
|
||||||
|
);
|
||||||
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
|
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<? extends Element> elements = roundEnvironment.getRootElements();
|
Set<? extends Element> elements = roundEnvironment.getRootElements();
|
||||||
for ( Element element : elements ) {
|
for ( Element element : elements ) {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Processing " + element.toString() );
|
if ( isJPAEntity( element ) ) {
|
||||||
|
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class " + element.toString() );
|
||||||
handleRootElementAnnotationMirrors( element );
|
handleRootElementAnnotationMirrors( element );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
|
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMetaModelClasses() {
|
private void createMetaModelClasses() {
|
||||||
for ( MetaEntity entity : context.getMetaEntitiesToProcess().values() ) {
|
for ( MetaEntity entity : context.getMetaEntities() ) {
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Writing meta model for " + entity );
|
context.logMessage( Diagnostic.Kind.OTHER, "Writing meta model for entity " + entity );
|
||||||
ClassWriter.writeFile( entity, context );
|
ClassWriter.writeFile( entity, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
//process left over, in most cases is empty
|
// we cannot process the delayed entities in any order. There might be dependencies between them.
|
||||||
for ( String className : context.getElementsAlreadyProcessed() ) {
|
// we need to process the top level entities first
|
||||||
context.getMetaSuperclassAndEmbeddableToProcess().remove( className );
|
// TODO make sure that we don't run into circular dependencies here
|
||||||
|
Collection<MetaEntity> toProcessEntities = context.getMetaSuperclassOrEmbeddable();
|
||||||
|
while ( !toProcessEntities.isEmpty() ) {
|
||||||
|
Set<MetaEntity> processedEntities = new HashSet<MetaEntity>();
|
||||||
|
for ( MetaEntity entity : toProcessEntities ) {
|
||||||
|
if ( containedInEntity( toProcessEntities, entity ) ) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
context.logMessage(
|
||||||
for ( MetaEntity entity : context.getMetaSuperclassAndEmbeddableToProcess().values() ) {
|
Diagnostic.Kind.OTHER, "Writing meta model for embeddable/mapped superclass" + entity
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Writing meta model for " + entity );
|
);
|
||||||
ClassWriter.writeFile( entity, context );
|
ClassWriter.writeFile( entity, context );
|
||||||
|
processedEntities.add( entity );
|
||||||
|
}
|
||||||
|
toProcessEntities.removeAll( processedEntities );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hostJPAAnnotations(Set<? extends TypeElement> annotations) {
|
private boolean containedInEntity(Collection<MetaEntity> entities, MetaEntity containedEntity) {
|
||||||
for ( TypeElement type : annotations ) {
|
ContainsAttributeTypeVisitor visitor = new ContainsAttributeTypeVisitor(
|
||||||
if ( TypeUtils.isTypeElementOfType( type, Entity.class ) ) {
|
containedEntity.getTypeElement(), context
|
||||||
|
);
|
||||||
|
for ( MetaEntity entity : entities ) {
|
||||||
|
if ( entity.equals( containedEntity ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
else if ( TypeUtils.isTypeElementOfType( type, Embeddable.class ) ) {
|
}
|
||||||
|
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 true;
|
||||||
}
|
}
|
||||||
else if ( TypeUtils.isTypeElementOfType( type, MappedSuperclass.class ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isJPAEntity(Element element) {
|
||||||
|
return TypeUtils.containsAnnotation( element, Entity.class, MappedSuperclass.class, Embeddable.class );
|
||||||
|
}
|
||||||
|
|
||||||
private void handleRootElementAnnotationMirrors(final Element element) {
|
private void handleRootElementAnnotationMirrors(final Element element) {
|
||||||
|
|
||||||
List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
|
List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
|
||||||
|
|
||||||
for ( AnnotationMirror mirror : annotationMirrors ) {
|
for ( AnnotationMirror mirror : annotationMirrors ) {
|
||||||
if ( element.getKind() == ElementKind.CLASS ) {
|
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 ) ) {
|
if ( TypeUtils.isAnnotationMirrorOfType( mirror, Entity.class ) ) {
|
||||||
AnnotationMetaEntity metaEntity = new AnnotationMetaEntity( ( TypeElement ) element, context );
|
alreadyExistingMetaEntity = context.getMetaEntity( fqn );
|
||||||
// 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 )
|
else if ( TypeUtils.isAnnotationMirrorOfType( mirror, MappedSuperclass.class )
|
||||||
|| TypeUtils.isAnnotationMirrorOfType( mirror, Embeddable.class ) ) {
|
|| TypeUtils.isAnnotationMirrorOfType( mirror, Embeddable.class ) ) {
|
||||||
AnnotationMetaEntity metaEntity = new AnnotationMetaEntity( ( TypeElement ) element, context );
|
alreadyExistingMetaEntity = context.getMetaSuperclassOrEmbeddable( fqn );
|
||||||
|
}
|
||||||
|
return alreadyExistingMetaEntity;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO instead of just adding the entity we have to do some merging.
|
private void addMetaEntityToContext(AnnotationMirror mirror, AnnotationMetaEntity metaEntity) {
|
||||||
context.getMetaSuperclassAndEmbeddableToProcess().put( metaEntity.getQualifiedName(), 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<Boolean, Element> {
|
||||||
|
|
||||||
|
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<MetaAttribute> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.MetaAttribute;
|
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
|
@ -47,7 +47,7 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPropertyName() {
|
public String getPropertyName() {
|
||||||
Elements elementsUtil = parent.getContext().getProcessingEnvironment().getElementUtils();
|
Elements elementsUtil = parent.getContext().getElementUtils();
|
||||||
if ( element.getKind() == ElementKind.FIELD ) {
|
if ( element.getKind() == ElementKind.FIELD ) {
|
||||||
return element.getSimpleName().toString();
|
return element.getSimpleName().toString();
|
||||||
}
|
}
|
||||||
|
@ -71,4 +71,14 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute {
|
||||||
public String getTypeDeclaration() {
|
public String getTypeDeclaration() {
|
||||||
return type;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.MetaCollection;
|
import org.hibernate.jpamodelgen.model.MetaCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.hibernate.jpamodelgen.annotation;
|
package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.ElementFilter;
|
import javax.lang.model.util.ElementFilter;
|
||||||
import javax.lang.model.util.Elements;
|
|
||||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||||
import javax.persistence.Access;
|
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.Basic;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Embeddable;
|
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.ManyToMany;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.MapKeyClass;
|
import javax.persistence.MapKeyClass;
|
||||||
import javax.persistence.MappedSuperclass;
|
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.OneToOne;
|
import javax.persistence.OneToOne;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.AccessTypeInformation;
|
||||||
import org.hibernate.jpamodelgen.Context;
|
import org.hibernate.jpamodelgen.Context;
|
||||||
import org.hibernate.jpamodelgen.ImportContext;
|
|
||||||
import org.hibernate.jpamodelgen.ImportContextImpl;
|
import org.hibernate.jpamodelgen.ImportContextImpl;
|
||||||
import org.hibernate.jpamodelgen.MetaAttribute;
|
import org.hibernate.jpamodelgen.model.ImportContext;
|
||||||
import org.hibernate.jpamodelgen.MetaEntity;
|
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
||||||
import org.hibernate.jpamodelgen.MetaModelGenerationException;
|
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.util.TypeUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,32 +66,25 @@ import org.hibernate.jpamodelgen.util.TypeUtils;
|
||||||
*/
|
*/
|
||||||
public class AnnotationMetaEntity implements MetaEntity {
|
public class AnnotationMetaEntity implements MetaEntity {
|
||||||
|
|
||||||
private static final String DEFAULT_ANNOTATION_PARAMETER_NAME = "value";
|
protected final ImportContext importContext;
|
||||||
static Map<String, String> COLLECTIONS = new HashMap<String, String>();
|
protected final TypeElement element;
|
||||||
|
protected final Map<String, MetaAttribute> members;
|
||||||
|
protected Context context;
|
||||||
|
|
||||||
static {
|
private AccessTypeInformation entityAccessTypeInfo;
|
||||||
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;
|
|
||||||
|
|
||||||
public AnnotationMetaEntity(TypeElement element, Context context) {
|
public AnnotationMetaEntity(TypeElement element, Context context) {
|
||||||
this.element = element;
|
this( element, context, false );
|
||||||
this.context = context;
|
|
||||||
importContext = new ImportContextImpl( getPackageName() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnnotationMetaEntity(TypeElement element, Context context, AccessType accessType) {
|
protected AnnotationMetaEntity(TypeElement element, Context context, boolean lazilyInitialised) {
|
||||||
this( element, context );
|
this.element = element;
|
||||||
this.defaultAccessTypeForHierarchy = accessType;
|
this.context = context;
|
||||||
|
this.members = new HashMap<String, MetaAttribute>();
|
||||||
|
this.importContext = new ImportContextImpl( getPackageName() );
|
||||||
|
if ( !lazilyInitialised ) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
|
@ -110,289 +100,153 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
PackageElement packageOf = context.getProcessingEnvironment().getElementUtils().getPackageOf( element );
|
PackageElement packageOf = context.getElementUtils().getPackageOf( element );
|
||||||
return context.getProcessingEnvironment().getElementUtils().getName( packageOf.getQualifiedName() ).toString();
|
return context.getElementUtils().getName( packageOf.getQualifiedName() ).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MetaAttribute> getMembers() {
|
public List<MetaAttribute> getMembers() {
|
||||||
List<MetaAttribute> membersFound = new ArrayList<MetaAttribute>();
|
return new ArrayList<MetaAttribute>( members.values() );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPersistentMembers(
|
@Override
|
||||||
List<MetaAttribute> membersFound,
|
public boolean isMetaComplete() {
|
||||||
AccessType elementAccessType,
|
return false;
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessType getAccessTypeForElement() {
|
public void mergeInMembers(Collection<MetaAttribute> attributes) {
|
||||||
|
for ( MetaAttribute attribute : attributes ) {
|
||||||
//get local strategy
|
members.put( attribute.getPropertyName(), attribute );
|
||||||
AccessType accessType = getAccessTypeForClass( element );
|
|
||||||
if ( accessType == null ) {
|
|
||||||
accessType = this.defaultAccessTypeForHierarchy;
|
|
||||||
}
|
}
|
||||||
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append( "MetaEntity" );
|
sb.append( "AnnotationMetaEntity" );
|
||||||
sb.append( "{element=" ).append( element );
|
sb.append( "{element=" ).append( element );
|
||||||
|
sb.append( ", members=" ).append( members );
|
||||||
sb.append( '}' );
|
sb.append( '}' );
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypeVisitor extends SimpleTypeVisitor6<AnnotationMetaAttribute, Element> {
|
private void addPersistentMembers(List<? extends Element> membersOfClass, AccessType membersKind) {
|
||||||
|
for ( Element memberOfClass : membersOfClass ) {
|
||||||
AnnotationMetaEntity parent;
|
AccessType forcedAccessType = TypeUtils.determineAnnotationSpecifiedAccessType( memberOfClass );
|
||||||
|
if ( entityAccessTypeInfo.getAccessType() != membersKind && forcedAccessType == null ) {
|
||||||
/*
|
continue;
|
||||||
* 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
|
if ( TypeUtils.containsAnnotation( memberOfClass, Transient.class )
|
||||||
protected AnnotationMetaAttribute defaultAction(TypeMirror e, Element p) {
|
|| memberOfClass.getModifiers().contains( Modifier.TRANSIENT )
|
||||||
return super.defaultAction( e, p );
|
|| memberOfClass.getModifiers().contains( Modifier.STATIC ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeVisitor visitor = new TypeVisitor( this );
|
||||||
|
AnnotationMetaAttribute result = memberOfClass.asType().accept( visitor, memberOfClass );
|
||||||
|
if ( result != null ) {
|
||||||
|
members.put( result.getPropertyName(), result );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void init() {
|
||||||
|
TypeUtils.determineAccessTypeForHierarchy( element, context );
|
||||||
|
entityAccessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
|
||||||
|
|
||||||
|
List<? extends Element> fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() );
|
||||||
|
addPersistentMembers( fieldsOfClass, AccessType.FIELD );
|
||||||
|
|
||||||
|
List<? extends Element> methodsOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
|
||||||
|
addPersistentMembers( methodsOfClass, AccessType.PROPERTY );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateImports() {
|
||||||
|
return importContext.generateImports();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String importType(String fqcn) {
|
||||||
|
return importContext.importType( fqcn );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String staticImport(String fqcn, String member) {
|
||||||
|
return importContext.staticImport( fqcn, member );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String importType(Name qualifiedName) {
|
||||||
|
return importType( qualifiedName.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeElement getTypeElement() {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeVisitor extends SimpleTypeVisitor6<AnnotationMetaAttribute, Element> {
|
||||||
|
AnnotationMetaEntity parent;
|
||||||
|
|
||||||
|
TypeVisitor(AnnotationMetaEntity parent) {
|
||||||
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AnnotationMetaAttribute visitPrimitive(PrimitiveType t, Element element) {
|
public AnnotationMetaAttribute visitPrimitive(PrimitiveType t, Element element) {
|
||||||
if ( isPersistent( element ) ) {
|
|
||||||
return new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
|
return new AnnotationMetaSingleAttribute( parent, element, TypeUtils.toTypeString( t ) );
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AnnotationMetaAttribute visitArray(ArrayType t, Element element) {
|
public AnnotationMetaAttribute visitArray(ArrayType t, Element element) {
|
||||||
if ( isPersistent( 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 ) );
|
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
|
@Override
|
||||||
public AnnotationMetaAttribute visitDeclared(DeclaredType declaredType, Element element) {
|
public AnnotationMetaAttribute visitDeclared(DeclaredType declaredType, Element element) {
|
||||||
if ( isPersistent( element ) ) {
|
TypeElement returnedElement = ( TypeElement ) context.getTypeUtils().asElement( declaredType );
|
||||||
TypeElement returnedElement = ( TypeElement ) context.getProcessingEnvironment()
|
|
||||||
.getTypeUtils()
|
|
||||||
.asElement( declaredType );
|
|
||||||
// WARNING: .toString() is necessary here since Name equals does not compare to String
|
// WARNING: .toString() is necessary here since Name equals does not compare to String
|
||||||
String fqNameOfReturnType = returnedElement.getQualifiedName().toString();
|
String fqNameOfReturnType = returnedElement.getQualifiedName().toString();
|
||||||
String collection = COLLECTIONS.get( fqNameOfReturnType );
|
String collection = Constants.COLLECTIONS.get( fqNameOfReturnType );
|
||||||
String targetEntity = getTargetEntity( element.getAnnotationMirrors() );
|
String targetEntity = getTargetEntity( element.getAnnotationMirrors() );
|
||||||
if ( collection != null ) {
|
if ( collection != null ) {
|
||||||
if ( TypeUtils.containsAnnotation( element, ElementCollection.class ) ) {
|
if ( TypeUtils.containsAnnotation( element, ElementCollection.class ) ) {
|
||||||
String explicitTargetEntity = getTargetEntity( element.getAnnotationMirrors() );
|
String explicitTargetEntity = getTargetEntity( element.getAnnotationMirrors() );
|
||||||
TypeMirror collectionElementType = getCollectionElementType(
|
TypeMirror collectionElementType = TypeUtils.getCollectionElementType(
|
||||||
declaredType, fqNameOfReturnType, explicitTargetEntity
|
declaredType, fqNameOfReturnType, explicitTargetEntity, context
|
||||||
);
|
);
|
||||||
final TypeElement collectionElement = ( TypeElement ) context.getProcessingEnvironment()
|
final TypeElement collectionElement = ( TypeElement ) context.getTypeUtils()
|
||||||
.getTypeUtils()
|
|
||||||
.asElement( collectionElementType );
|
.asElement( collectionElementType );
|
||||||
this.parent.context.processElement(
|
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( collectionElement.getQualifiedName().toString() );
|
||||||
collectionElement,
|
if ( accessTypeInfo == null ) {
|
||||||
this.parent.defaultAccessTypeForElement
|
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" ) ) {
|
if ( collection.equals( "javax.persistence.metamodel.MapAttribute" ) ) {
|
||||||
return createAnnotationMetaAttributeForMap( declaredType, element, collection, targetEntity );
|
return createAnnotationMetaAttributeForMap( declaredType, element, collection, targetEntity );
|
||||||
|
@ -404,22 +258,42 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//FIXME Consider XML
|
if ( isBasicAttribute( element, returnedElement ) ) {
|
||||||
if ( TypeUtils.containsAnnotation( returnedElement, Embedded.class, Embeddable.class ) ) {
|
|
||||||
this.parent.context.processElement(
|
|
||||||
returnedElement,
|
|
||||||
this.parent.defaultAccessTypeForElement
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new AnnotationMetaSingleAttribute(
|
return new AnnotationMetaSingleAttribute(
|
||||||
parent, element, returnedElement.getQualifiedName().toString()
|
parent, element, returnedElement.getQualifiedName().toString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
return null;
|
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) {
|
private AnnotationMetaAttribute createAnnotationMetaAttributeForMap(DeclaredType declaredType, Element element, String collection, String targetEntity) {
|
||||||
String keyType;
|
String keyType;
|
||||||
|
@ -427,7 +301,7 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
TypeMirror typeMirror = ( TypeMirror ) TypeUtils.getAnnotationValue(
|
TypeMirror typeMirror = ( TypeMirror ) TypeUtils.getAnnotationValue(
|
||||||
TypeUtils.getAnnotationMirror(
|
TypeUtils.getAnnotationMirror(
|
||||||
element, MapKeyClass.class
|
element, MapKeyClass.class
|
||||||
), DEFAULT_ANNOTATION_PARAMETER_NAME
|
), TypeUtils.DEFAULT_ANNOTATION_PARAMETER_NAME
|
||||||
);
|
);
|
||||||
keyType = typeMirror.toString();
|
keyType = typeMirror.toString();
|
||||||
}
|
}
|
||||||
|
@ -443,43 +317,36 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeMirror getCollectionElementType(DeclaredType t, String fqNameOfReturnedType, String explicitTargetEntityName) {
|
private String getElementType(DeclaredType declaredType, String targetEntity) {
|
||||||
TypeMirror collectionElementType;
|
if ( targetEntity != null ) {
|
||||||
if ( explicitTargetEntityName != null ) {
|
return targetEntity;
|
||||||
Elements elements = context.getProcessingEnvironment().getElementUtils();
|
}
|
||||||
TypeElement element = elements.getTypeElement( explicitTargetEntityName );
|
final List<? extends TypeMirror> mirrors = declaredType.getTypeArguments();
|
||||||
collectionElementType = element.asType();
|
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 {
|
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();
|
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
|
||||||
if ( typeArguments.size() == 0 ) {
|
if ( typeArguments.size() == 0 ) {
|
||||||
throw new MetaModelGenerationException( "Unable to determine collection type for property in " + getSimpleName() );
|
context.logMessage( Diagnostic.Kind.ERROR, "Entity: " + getQualifiedName() );
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
String string = p.getSimpleName().toString();
|
|
||||||
if ( string.startsWith( "get" ) || string.startsWith( "is" ) || string.startsWith( "has" ) ) {
|
|
||||||
TypeMirror returnType = t.getReturnType();
|
|
||||||
return returnType.accept( this, p );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return TypeUtils.extractClosestRealTypeAsString( typeArguments.get( 0 ), context );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -518,50 +385,49 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
return targetEntityName;
|
return targetEntityName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateImports() {
|
|
||||||
return importContext.generateImports();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String importType(String fqcn) {
|
/**
|
||||||
return importContext.importType( fqcn );
|
* 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<Boolean, Element> {
|
||||||
|
@Override
|
||||||
|
public Boolean visitPrimitive(PrimitiveType t, Element element) {
|
||||||
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String staticImport(String fqcn, String member) {
|
@Override
|
||||||
return importContext.staticImport( fqcn, member );
|
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() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String importType(Name qualifiedName) {
|
@Override
|
||||||
return importType( qualifiedName.toString() );
|
public Boolean visitDeclared(DeclaredType declaredType, Element element) {
|
||||||
|
if ( ElementKind.ENUM.equals( element.getKind() ) ) {
|
||||||
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeElement getTypeElement() {
|
if ( ElementKind.CLASS.equals( element.getKind() ) ) {
|
||||||
return element;
|
TypeElement typeElement = ( ( TypeElement ) element );
|
||||||
|
String typeName = typeElement.getQualifiedName().toString();
|
||||||
|
if ( Constants.BASIC_TYPES.contains( typeName ) ) {
|
||||||
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
if ( TypeUtils.containsAnnotation( element, Embeddable.class ) ) {
|
||||||
private String getKeyType(DeclaredType t) {
|
return Boolean.TRUE;
|
||||||
return TypeUtils.extractClosestRealTypeAsString( t.getTypeArguments().get( 0 ), context );
|
|
||||||
}
|
}
|
||||||
|
for ( TypeMirror mirror : typeElement.getInterfaces() ) {
|
||||||
private String getElementType(DeclaredType declaredType, String targetEntity) {
|
TypeElement interfaceElement = ( TypeElement ) context.getTypeUtils().asElement( mirror );
|
||||||
if ( targetEntity != null ) {
|
if ( "java.io.Serializable".equals( interfaceElement.getQualifiedName().toString() ) ) {
|
||||||
return targetEntity;
|
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 );
|
|
||||||
}
|
}
|
||||||
else if ( mirrors.size() == 2 ) {
|
|
||||||
return TypeUtils.extractClosestRealTypeAsString( mirrors.get( 1 ), context );
|
|
||||||
}
|
}
|
||||||
else {
|
return Boolean.FALSE;
|
||||||
//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 "?";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.MetaSingleAttribute;
|
import org.hibernate.jpamodelgen.model.MetaSingleAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
|
|
|
@ -15,10 +15,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
|
@ -15,7 +15,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
|
@ -15,7 +15,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
|
@ -15,11 +15,11 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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.Name;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
@ -42,4 +42,6 @@ public interface MetaEntity extends ImportContext {
|
||||||
String importType(Name qualifiedName);
|
String importType(Name qualifiedName);
|
||||||
|
|
||||||
TypeElement getTypeElement();
|
TypeElement getTypeElement();
|
||||||
|
|
||||||
|
boolean isMetaComplete();
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen;
|
package org.hibernate.jpamodelgen.model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
|
@ -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<String, String> COLLECTIONS = new HashMap<String, String>();
|
||||||
|
|
||||||
|
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<String> BASIC_TYPES = new ArrayList<String>();
|
||||||
|
|
||||||
|
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<String> BASIC_ARRAY_TYPES = new ArrayList<String>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
BASIC_ARRAY_TYPES.add( "java.lang.Character" );
|
||||||
|
BASIC_ARRAY_TYPES.add( "java.lang.Byte" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Constants(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,30 @@ import java.util.Map;
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.AnnotationValue;
|
import javax.lang.model.element.AnnotationValue;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
|
import javax.lang.model.type.ExecutableType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.type.TypeVariable;
|
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.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.Context;
|
||||||
|
import org.hibernate.jpamodelgen.MetaModelGenerationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class.
|
* Utility class.
|
||||||
|
@ -44,6 +59,7 @@ import org.hibernate.jpamodelgen.Context;
|
||||||
*/
|
*/
|
||||||
public class TypeUtils {
|
public class TypeUtils {
|
||||||
|
|
||||||
|
public static final String DEFAULT_ANNOTATION_PARAMETER_NAME = "value";
|
||||||
private static final Map<String, String> PRIMITIVES = new HashMap<String, String>();
|
private static final Map<String, String> PRIMITIVES = new HashMap<String, String>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -84,7 +100,7 @@ public class TypeUtils {
|
||||||
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
|
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
|
||||||
if ( type instanceof TypeVariable ) {
|
if ( type instanceof TypeVariable ) {
|
||||||
final TypeMirror compositeUpperBound = ( ( TypeVariable ) type ).getUpperBound();
|
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 );
|
final List<? extends TypeMirror> upperBounds = types.directSupertypes( compositeUpperBound );
|
||||||
if ( upperBounds.size() == 0 ) {
|
if ( upperBounds.size() == 0 ) {
|
||||||
return compositeUpperBound.toString();
|
return compositeUpperBound.toString();
|
||||||
|
@ -181,4 +197,220 @@ public class TypeUtils {
|
||||||
}
|
}
|
||||||
return returnValue;
|
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<String, Element> {
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
package org.hibernate.jpamodelgen.xml;
|
package org.hibernate.jpamodelgen.xml;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.MetaAttribute;
|
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
@ -37,7 +37,6 @@ public abstract class XmlMetaAttribute implements MetaAttribute {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDeclarationString() {
|
public String getDeclarationString() {
|
||||||
return "public static volatile " + parentEntity.importType(getMetaType()) + "<" + parentEntity.importType(parentEntity.getQualifiedName()) + ", " + parentEntity.importType(getTypeDeclaration()) + "> " + getPropertyName() + ";";
|
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
|
@Override
|
||||||
abstract public String getMetaType();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen.xml;
|
package org.hibernate.jpamodelgen.xml;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.MetaCollection;
|
import org.hibernate.jpamodelgen.model.MetaCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
|
|
@ -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<MetaAttribute> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,18 +22,22 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.lang.model.element.Element;
|
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.Name;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.AccessTypeInformation;
|
||||||
import org.hibernate.jpamodelgen.Context;
|
import org.hibernate.jpamodelgen.Context;
|
||||||
import org.hibernate.jpamodelgen.ImportContext;
|
|
||||||
import org.hibernate.jpamodelgen.ImportContextImpl;
|
import org.hibernate.jpamodelgen.ImportContextImpl;
|
||||||
import org.hibernate.jpamodelgen.MetaAttribute;
|
|
||||||
import org.hibernate.jpamodelgen.MetaEntity;
|
|
||||||
import org.hibernate.jpamodelgen.MetaModelGenerationException;
|
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.util.TypeUtils;
|
||||||
import org.hibernate.jpamodelgen.xml.jaxb.Attributes;
|
import org.hibernate.jpamodelgen.xml.jaxb.Attributes;
|
||||||
import org.hibernate.jpamodelgen.xml.jaxb.Basic;
|
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" );
|
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<MetaAttribute> members = new ArrayList<MetaAttribute>();
|
||||||
|
protected final TypeElement element;
|
||||||
|
protected final Context context;
|
||||||
|
protected final boolean isMetaComplete;
|
||||||
|
|
||||||
final private String packageName;
|
private Attributes attributes;
|
||||||
|
private EmbeddableAttributes embeddableAttributes;
|
||||||
final private ImportContext importContext;
|
protected AccessTypeInformation accessTypeInfo;
|
||||||
|
|
||||||
final private List<MetaAttribute> members = new ArrayList<MetaAttribute>();
|
|
||||||
|
|
||||||
private TypeElement element;
|
|
||||||
private Context context;
|
|
||||||
|
|
||||||
public XmlMetaEntity(Entity ormEntity, String packageName, TypeElement element, Context context) {
|
public XmlMetaEntity(Entity ormEntity, String packageName, TypeElement element, Context context) {
|
||||||
this.clazzName = ormEntity.getClazz();
|
this( ormEntity.getClazz(), packageName, element, context, ormEntity.isMetadataComplete() );
|
||||||
this.packageName = packageName;
|
this.attributes = ormEntity.getAttributes();
|
||||||
this.context = context;
|
this.embeddableAttributes = null;
|
||||||
this.importContext = new ImportContextImpl( getPackageName() );
|
// entities can be directly initialised
|
||||||
this.element = element;
|
init();
|
||||||
Attributes attributes = ormEntity.getAttributes();
|
|
||||||
|
|
||||||
parseAttributes( attributes );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element, Context context) {
|
protected XmlMetaEntity(MappedSuperclass mappedSuperclass, String packageName, TypeElement element, Context context) {
|
||||||
this.clazzName = mappedSuperclass.getClazz();
|
this( mappedSuperclass.getClazz(), packageName, element, context, mappedSuperclass.isMetadataComplete() );
|
||||||
this.packageName = packageName;
|
this.attributes = mappedSuperclass.getAttributes();
|
||||||
this.context = context;
|
this.embeddableAttributes = null;
|
||||||
this.importContext = new ImportContextImpl( getPackageName() );
|
|
||||||
this.element = element;
|
|
||||||
Attributes attributes = mappedSuperclass.getAttributes();
|
|
||||||
parseAttributes( attributes );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element, Context context) {
|
protected XmlMetaEntity(Embeddable embeddable, String packageName, TypeElement element, Context context) {
|
||||||
this.clazzName = embeddable.getClazz();
|
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.packageName = packageName;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.importContext = new ImportContextImpl( getPackageName() );
|
this.importContext = new ImportContextImpl( getPackageName() );
|
||||||
this.element = element;
|
this.element = element;
|
||||||
EmbeddableAttributes attributes = embeddable.getAttributes();
|
this.isMetaComplete = initIsMetaComplete( metaComplete );
|
||||||
parseEmbeddableAttributes( attributes );
|
}
|
||||||
|
|
||||||
|
protected void init() {
|
||||||
|
this.accessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
|
||||||
|
if ( attributes != null ) {
|
||||||
|
parseAttributes( attributes );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parseEmbeddableAttributes( embeddableAttributes );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSimpleName() {
|
public String getSimpleName() {
|
||||||
|
@ -140,10 +159,38 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] getCollectionType(String propertyName, String explicitTargetEntity) {
|
@Override
|
||||||
|
public boolean isMetaComplete() {
|
||||||
|
return isMetaComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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=" ).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];
|
String types[] = new String[2];
|
||||||
for ( Element elem : element.getEnclosedElements() ) {
|
for ( Element elem : element.getEnclosedElements() ) {
|
||||||
if ( elem.getSimpleName().toString().equals( propertyName ) ) {
|
if ( expectedElementKind.equals( elem.getKind() ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !elem.getSimpleName().toString().equals( propertyName ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
DeclaredType type = ( ( DeclaredType ) elem.asType() );
|
DeclaredType type = ( ( DeclaredType ) elem.asType() );
|
||||||
List<? extends TypeMirror> typeArguments = type.getTypeArguments();
|
List<? extends TypeMirror> typeArguments = type.getTypeArguments();
|
||||||
|
|
||||||
|
@ -158,134 +205,251 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
types[0] = explicitTargetEntity;
|
types[0] = explicitTargetEntity;
|
||||||
}
|
}
|
||||||
types[1] = COLLECTIONS.get( type.asElement().toString() );
|
types[1] = COLLECTIONS.get( type.asElement().toString() );
|
||||||
}
|
|
||||||
}
|
|
||||||
return types;
|
return types;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the entity type for relation.
|
* Returns the entity type for a property.
|
||||||
*
|
*
|
||||||
* @param propertyName The property name of the association
|
* @param propertyName The property name
|
||||||
* @param explicitTargetEntity The explicitly specified target entity type
|
* @param explicitTargetEntity The explicitly specified target entity type or {@code null}.
|
||||||
|
* @param expectedElementKind Determines property vs field access type
|
||||||
*
|
*
|
||||||
* @return The entity type for relation/association.
|
* @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) {
|
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 ) {
|
if ( explicitTargetEntity != null ) {
|
||||||
// TODO should there be a check of the target entity class and if it is loadable?
|
// TODO should there be a check of the target entity class and if it is loadable?
|
||||||
return explicitTargetEntity;
|
return explicitTargetEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
String typeName = null;
|
switch ( mirror.getKind() ) {
|
||||||
for ( Element elem : element.getEnclosedElements() ) {
|
|
||||||
if ( elem.getSimpleName().toString().equals( propertyName ) ) {
|
|
||||||
switch ( elem.asType().getKind() ) {
|
|
||||||
case INT: {
|
case INT: {
|
||||||
typeName = "java.lang.Integer";
|
return "java.lang.Integer";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case LONG: {
|
case LONG: {
|
||||||
typeName = "java.lang.Long";
|
return "java.lang.Long";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case BOOLEAN: {
|
case BOOLEAN: {
|
||||||
typeName = "java.lang.Boolean";
|
return "java.lang.Boolean";
|
||||||
break;
|
}
|
||||||
|
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: {
|
case DECLARED: {
|
||||||
typeName = elem.asType().toString();
|
return mirror.toString();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case TYPEVAR: {
|
case TYPEVAR: {
|
||||||
typeName = elem.asType().toString();
|
return mirror.toString();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return typeName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
context.logMessage(
|
||||||
public String toString() {
|
Diagnostic.Kind.WARNING,
|
||||||
final StringBuilder sb = new StringBuilder();
|
"Unable to determine type for property " + propertyName + " of class " + getQualifiedName()
|
||||||
sb.append( "XmlMetaEntity" );
|
+ " using assess type " + accessTypeInfo.getDefaultAccessType()
|
||||||
sb.append( "{type=" ).append( element );
|
);
|
||||||
sb.append( '}' );
|
return null;
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseAttributes(Attributes attributes) {
|
private void parseAttributes(Attributes attributes) {
|
||||||
XmlMetaSingleAttribute attribute;
|
XmlMetaSingleAttribute attribute;
|
||||||
|
for ( Id id : attributes.getId() ) {
|
||||||
if ( !attributes.getId().isEmpty() ) {
|
ElementKind elementKind = getElementKind( id.getAccess() );
|
||||||
// TODO what do we do if there are more than one id nodes?
|
String type = getType( id.getName(), null, elementKind );
|
||||||
Id id = attributes.getId().get( 0 );
|
if ( type != null ) {
|
||||||
attribute = new XmlMetaSingleAttribute(
|
attribute = new XmlMetaSingleAttribute( this, id.getName(), type );
|
||||||
this, id.getName(), getType( id.getName(), null )
|
|
||||||
);
|
|
||||||
members.add( attribute );
|
members.add( attribute );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( Basic basic : attributes.getBasic() ) {
|
for ( Basic basic : attributes.getBasic() ) {
|
||||||
attribute = new XmlMetaSingleAttribute( this, basic.getName(), getType( basic.getName(), null ) );
|
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 );
|
members.add( attribute );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( ManyToOne manyToOne : attributes.getManyToOne() ) {
|
for ( ManyToOne manyToOne : attributes.getManyToOne() ) {
|
||||||
attribute = new XmlMetaSingleAttribute(
|
ElementKind elementKind = getElementKind( manyToOne.getAccess() );
|
||||||
this, manyToOne.getName(), getType( manyToOne.getName(), manyToOne.getTargetEntity() )
|
String type = getType( manyToOne.getName(), manyToOne.getTargetEntity(), elementKind );
|
||||||
);
|
if ( type != null ) {
|
||||||
|
attribute = new XmlMetaSingleAttribute( this, manyToOne.getName(), type );
|
||||||
members.add( attribute );
|
members.add( attribute );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( OneToOne oneToOne : attributes.getOneToOne() ) {
|
for ( OneToOne oneToOne : attributes.getOneToOne() ) {
|
||||||
attribute = new XmlMetaSingleAttribute(
|
ElementKind elementKind = getElementKind( oneToOne.getAccess() );
|
||||||
this, oneToOne.getName(), getType( oneToOne.getName(), oneToOne.getTargetEntity() )
|
String type = getType( oneToOne.getName(), oneToOne.getTargetEntity(), elementKind );
|
||||||
);
|
if ( type != null ) {
|
||||||
|
attribute = new XmlMetaSingleAttribute( this, oneToOne.getName(), type );
|
||||||
members.add( attribute );
|
members.add( attribute );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XmlMetaCollection metaCollection;
|
XmlMetaCollection metaCollection;
|
||||||
String[] types;
|
String[] types;
|
||||||
for ( ManyToMany manyToMany : attributes.getManyToMany() ) {
|
for ( ManyToMany manyToMany : attributes.getManyToMany() ) {
|
||||||
|
ElementKind elementKind = getElementKind( manyToMany.getAccess() );
|
||||||
try {
|
try {
|
||||||
types = getCollectionType( manyToMany.getName(), manyToMany.getTargetEntity() );
|
types = getCollectionType( manyToMany.getName(), manyToMany.getTargetEntity(), elementKind );
|
||||||
}
|
}
|
||||||
catch ( MetaModelGenerationException e ) {
|
catch ( MetaModelGenerationException e ) {
|
||||||
logMetaModelException( manyToMany.getName(), e );
|
logMetaModelException( manyToMany.getName(), e );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ( types != null ) {
|
||||||
metaCollection = new XmlMetaCollection( this, manyToMany.getName(), types[0], types[1] );
|
metaCollection = new XmlMetaCollection( this, manyToMany.getName(), types[0], types[1] );
|
||||||
members.add( metaCollection );
|
members.add( metaCollection );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( OneToMany oneToMany : attributes.getOneToMany() ) {
|
for ( OneToMany oneToMany : attributes.getOneToMany() ) {
|
||||||
|
ElementKind elementKind = getElementKind( oneToMany.getAccess() );
|
||||||
try {
|
try {
|
||||||
types = getCollectionType( oneToMany.getName(), oneToMany.getTargetEntity() );
|
types = getCollectionType( oneToMany.getName(), oneToMany.getTargetEntity(), elementKind );
|
||||||
}
|
}
|
||||||
catch ( MetaModelGenerationException e ) {
|
catch ( MetaModelGenerationException e ) {
|
||||||
logMetaModelException( oneToMany.getName(), e );
|
logMetaModelException( oneToMany.getName(), e );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ( types != null ) {
|
||||||
metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] );
|
metaCollection = new XmlMetaCollection( this, oneToMany.getName(), types[0], types[1] );
|
||||||
members.add( metaCollection );
|
members.add( metaCollection );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( ElementCollection collection : attributes.getElementCollection() ) {
|
for ( ElementCollection collection : attributes.getElementCollection() ) {
|
||||||
|
ElementKind elementKind = getElementKind( collection.getAccess() );
|
||||||
try {
|
try {
|
||||||
types = getCollectionType( collection.getName(), collection.getTargetClass() );
|
types = getCollectionType( collection.getName(), collection.getTargetClass(), elementKind );
|
||||||
}
|
}
|
||||||
catch ( MetaModelGenerationException e ) {
|
catch ( MetaModelGenerationException e ) {
|
||||||
logMetaModelException( collection.getName(), e );
|
logMetaModelException( collection.getName(), e );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ( types != null ) {
|
||||||
metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] );
|
metaCollection = new XmlMetaCollection( this, collection.getName(), types[0], types[1] );
|
||||||
members.add( metaCollection );
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void logMetaModelException(String name, MetaModelGenerationException e) {
|
private void logMetaModelException(String name, MetaModelGenerationException e) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
|
@ -301,44 +465,17 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseEmbeddableAttributes(EmbeddableAttributes attributes) {
|
private ElementKind getElementKind(org.hibernate.jpamodelgen.xml.jaxb.AccessType accessType) {
|
||||||
XmlMetaSingleAttribute attribute;
|
// if no explicit access type was specified in xml we use the entity access type
|
||||||
for ( Basic basic : attributes.getBasic() ) {
|
if ( accessType == null ) {
|
||||||
attribute = new XmlMetaSingleAttribute( this, basic.getName(), getType( basic.getName(), null ) );
|
return TypeUtils.getElementKindForAccessType( accessTypeInfo.getDefaultAccessType() );
|
||||||
members.add( attribute );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( ManyToOne manyToOne : attributes.getManyToOne() ) {
|
if ( org.hibernate.jpamodelgen.xml.jaxb.AccessType.FIELD.equals( accessType ) ) {
|
||||||
attribute = new XmlMetaSingleAttribute(
|
return ElementKind.FIELD;
|
||||||
this, manyToOne.getName(), getType( manyToOne.getName(), manyToOne.getTargetEntity() )
|
|
||||||
);
|
|
||||||
members.add( attribute );
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
for ( OneToOne oneToOne : attributes.getOneToOne() ) {
|
return ElementKind.METHOD;
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<MetaAttribute> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen.xml;
|
package org.hibernate.jpamodelgen.xml;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.MetaSingleAttribute;
|
import org.hibernate.jpamodelgen.model.MetaSingleAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.hibernate.jpamodelgen.xml;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
@ -36,7 +37,10 @@ import javax.xml.validation.SchemaFactory;
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.AccessTypeInformation;
|
||||||
import org.hibernate.jpamodelgen.Context;
|
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.Entity;
|
||||||
import org.hibernate.jpamodelgen.xml.jaxb.EntityMappings;
|
import org.hibernate.jpamodelgen.xml.jaxb.EntityMappings;
|
||||||
import org.hibernate.jpamodelgen.xml.jaxb.ObjectFactory;
|
import org.hibernate.jpamodelgen.xml.jaxb.ObjectFactory;
|
||||||
|
@ -48,132 +52,145 @@ import org.hibernate.jpamodelgen.xml.jaxb.PersistenceUnitMetadata;
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class XmlParser {
|
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 ORM_XML = "/META-INF/orm.xml";
|
||||||
private static final String PERSISTENCE_XML_XSD = "persistence_2_0.xsd";
|
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 ORM_XSD = "orm_2_0.xsd";
|
||||||
private static final String PATH_SEPARATOR = "/";
|
private static final String PATH_SEPARATOR = "/";
|
||||||
private static final AccessType DEFAULT_XML_ACCESS_TYPE = AccessType.PROPERTY;
|
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private List<EntityMappings> entityMappings;
|
||||||
|
|
||||||
public XmlParser(Context context) {
|
public XmlParser(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.entityMappings = new ArrayList<EntityMappings>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parsePersistenceXml() {
|
public void parseXml() {
|
||||||
Persistence persistence = parseXml( PERSISTENCE_XML, Persistence.class, PERSISTENCE_XML_XSD );
|
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 ) {
|
if ( persistence != null ) {
|
||||||
List<Persistence.PersistenceUnit> persistenceUnits = persistence.getPersistenceUnit();
|
List<Persistence.PersistenceUnit> persistenceUnits = persistence.getPersistenceUnit();
|
||||||
for ( Persistence.PersistenceUnit unit : persistenceUnits ) {
|
for ( Persistence.PersistenceUnit unit : persistenceUnits ) {
|
||||||
List<String> mappingFiles = unit.getMappingFile();
|
List<String> mappingFiles = unit.getMappingFile();
|
||||||
for ( String mappingFile : mappingFiles ) {
|
for ( String mappingFile : mappingFiles ) {
|
||||||
parsingOrmXml( mappingFile );
|
loadEntityMappings( mappingFile );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parsingOrmXml( ORM_XML ); // /META-INF/orm.xml is implicit
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parsingOrmXml(String resource) {
|
// /META-INF/orm.xml is implicit
|
||||||
EntityMappings mappings = parseXml( resource, EntityMappings.class, ORM_XSD );
|
loadEntityMappings( ORM_XML );
|
||||||
if ( mappings == null ) {
|
|
||||||
return;
|
// 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 );
|
private void loadEntityMappings(String resource) {
|
||||||
|
EntityMappings mapping = parseXml( resource, EntityMappings.class, ORM_XSD );
|
||||||
parseEntities( mappings, accessType );
|
if ( mapping != null ) {
|
||||||
parseEmbeddable( mappings, accessType );
|
entityMappings.add( mapping );
|
||||||
parseMappedSuperClass( mappings, accessType );
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseEntities(EntityMappings mappings, AccessType accessType) {
|
private void parseEntities(Collection<Entity> entities, String defaultPackageName) {
|
||||||
String packageName = mappings.getPackage();
|
|
||||||
Collection<Entity> entities = mappings.getEntity();
|
|
||||||
for ( Entity entity : entities ) {
|
for ( Entity entity : entities ) {
|
||||||
String fullyQualifiedClassName = packageName + "." + entity.getClazz();
|
String fqcn = StringUtil.determineFullyQualifiedClassName( defaultPackageName, entity.getClazz() );
|
||||||
|
|
||||||
if ( !xmlMappedTypeExists( fullyQualifiedClassName ) ) {
|
if ( !xmlMappedTypeExists( fqcn ) ) {
|
||||||
context.logMessage(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlMetaEntity metaEntity = new XmlMetaEntity(
|
XmlMetaEntity metaEntity = new XmlMetaEntity(
|
||||||
entity, packageName, getXmlMappedType( fullyQualifiedClassName ),
|
entity, defaultPackageName, getXmlMappedType( fqcn ), context
|
||||||
context
|
|
||||||
);
|
);
|
||||||
|
if ( context.containsMetaEntity( fqcn ) ) {
|
||||||
if ( context.getMetaEntitiesToProcess().containsKey( fullyQualifiedClassName ) ) {
|
|
||||||
context.logMessage(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
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) {
|
private void parseEmbeddable(Collection<org.hibernate.jpamodelgen.xml.jaxb.Embeddable> embeddables, String defaultPackageName) {
|
||||||
String packageName = mappings.getPackage();
|
|
||||||
Collection<org.hibernate.jpamodelgen.xml.jaxb.Embeddable> embeddables = mappings.getEmbeddable();
|
|
||||||
for ( org.hibernate.jpamodelgen.xml.jaxb.Embeddable embeddable : embeddables ) {
|
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(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlMetaEntity metaEntity = new XmlMetaEntity(
|
XmlMetaEntity metaEntity = new XmlMetaEmbeddable( embeddable, pkg, getXmlMappedType( fqcn ), context );
|
||||||
embeddable, packageName, getXmlMappedType( fullyQualifiedClassName ),
|
if ( context.containsMetaSuperclassOrEmbeddable( fqcn ) ) {
|
||||||
context
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) {
|
|
||||||
context.logMessage(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
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(Collection<org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass> mappedSuperClasses, String defaultPackageName) {
|
||||||
private void parseMappedSuperClass(EntityMappings mappings, AccessType accessType) {
|
|
||||||
String packageName = mappings.getPackage();
|
|
||||||
Collection<org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass> mappedSuperClasses = mappings.getMappedSuperclass();
|
|
||||||
for ( org.hibernate.jpamodelgen.xml.jaxb.MappedSuperclass mappedSuperClass : mappedSuperClasses ) {
|
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(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlMetaEntity metaEntity = new XmlMetaEntity(
|
XmlMetaEntity metaEntity = new XmlMetaMappedSuperClass(
|
||||||
mappedSuperClass, packageName, getXmlMappedType( fullyQualifiedClassName ),
|
mappedSuperClass, pkg, getXmlMappedType( fqcn ), context
|
||||||
context
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( context.getMetaSuperclassAndEmbeddableToProcess().containsKey( fullyQualifiedClassName ) ) {
|
if ( context.containsMetaSuperclassOrEmbeddable( fqcn ) ) {
|
||||||
context.logMessage(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
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 clazz The type of jaxb node to return
|
||||||
* @param schemaName The schema to validate against (can be {@code null});
|
* @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> T parseXml(String resource, Class<T> clazz, String schemaName) {
|
private <T> T parseXml(String resource, Class<T> clazz, String schemaName) {
|
||||||
|
|
||||||
|
@ -274,35 +292,135 @@ public class XmlParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean xmlMappedTypeExists(String fullyQualifiedClassName) {
|
private boolean xmlMappedTypeExists(String fullyQualifiedClassName) {
|
||||||
Elements utils = context.getProcessingEnvironment().getElementUtils();
|
Elements utils = context.getElementUtils();
|
||||||
return utils.getTypeElement( fullyQualifiedClassName ) != null;
|
return utils.getTypeElement( fullyQualifiedClassName ) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeElement getXmlMappedType(String fullyQualifiedClassName) {
|
private TypeElement getXmlMappedType(String fullyQualifiedClassName) {
|
||||||
Elements utils = context.getProcessingEnvironment().getElementUtils();
|
Elements utils = context.getElementUtils();
|
||||||
return utils.getTypeElement( fullyQualifiedClassName );
|
return utils.getTypeElement( fullyQualifiedClassName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AccessType determineEntityAccessType(EntityMappings mappings) {
|
||||||
private AccessType determineGlobalAccessType(EntityMappings mappings) {
|
AccessType accessType = context.getPersistenceUnitDefaultAccessType();
|
||||||
AccessType accessType = DEFAULT_XML_ACCESS_TYPE;
|
|
||||||
|
|
||||||
if ( mappings.getAccess() != null ) {
|
if ( mappings.getAccess() != null ) {
|
||||||
accessType = mapXmlAccessTypeToJpaAccessType( mappings.getAccess() );
|
accessType = mapXmlAccessTypeToJpaAccessType( mappings.getAccess() );
|
||||||
return accessType; // no need to check persistence unit default
|
}
|
||||||
|
return accessType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the default access type as specified in the <i>persistence-unit-defaults</i> as well as whether the
|
||||||
|
* xml configuration is complete and annotations should be ignored.
|
||||||
|
* <p/>
|
||||||
|
* Note, the spec says:
|
||||||
|
* <ul>
|
||||||
|
* <li>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.</li>
|
||||||
|
* <li>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.</li>
|
||||||
|
* <li>When the xml-mapping-metadata-complete element is specified, any metadata-complete attributes specified
|
||||||
|
* within the entity, mapped-superclass, and embeddable elements are ignored.<li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
private void determineDefaultAccessTypeAndMetaCompleteness() {
|
||||||
|
for ( EntityMappings mappings : entityMappings ) {
|
||||||
PersistenceUnitMetadata meta = mappings.getPersistenceUnitMetadata();
|
PersistenceUnitMetadata meta = mappings.getPersistenceUnitMetadata();
|
||||||
if ( meta != null ) {
|
if ( meta != null ) {
|
||||||
|
if ( meta.getXmlMappingMetadataComplete() != null ) {
|
||||||
|
context.setPersistenceUnitCompletelyXmlConfigured( true );
|
||||||
|
}
|
||||||
|
|
||||||
PersistenceUnitDefaults persistenceUnitDefaults = meta.getPersistenceUnitDefaults();
|
PersistenceUnitDefaults persistenceUnitDefaults = meta.getPersistenceUnitDefaults();
|
||||||
if ( persistenceUnitDefaults != null ) {
|
if ( persistenceUnitDefaults != null ) {
|
||||||
org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType = persistenceUnitDefaults.getAccess();
|
org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType = persistenceUnitDefaults.getAccess();
|
||||||
if ( xmlAccessType != null ) {
|
if ( xmlAccessType != null ) {
|
||||||
accessType = mapXmlAccessTypeToJpaAccessType( xmlAccessType );
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return accessType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessType mapXmlAccessTypeToJpaAccessType(org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType) {
|
private AccessType mapXmlAccessTypeToJpaAccessType(org.hibernate.jpamodelgen.xml.jaxb.AccessType xmlAccessType) {
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen.test.accesstype;
|
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.testng.annotations.Test;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
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 {
|
public class AccessTypeTest extends CompilationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testXmlConfiguredEntityGenerated() {
|
||||||
|
TestUtil.assertMetamodelClassGeneratedFor( Order.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExcludeTransientFieldAndStatic() {
|
public void testExcludeTransientFieldAndStatic() {
|
||||||
TestUtil.assertAbsenceOfFieldInMetamodelFor( Product.class, "nonPersistent" );
|
TestUtil.assertAbsenceOfFieldInMetamodelFor( Product.class, "nonPersistent" );
|
||||||
|
@ -88,7 +97,14 @@ public class AccessTypeTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return Product.class.getPackage().getName();
|
return AccessTypeTest.class.getPackage().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<String> getOrmFiles() {
|
||||||
|
List<String> ormFiles = new ArrayList<String>();
|
||||||
|
ormFiles.add( TestUtil.fcnToPath( AccessTypeTest.class.getPackage().getName() ) + "/orm.xml" );
|
||||||
|
return ormFiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class ArrayTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return Image.class.getPackage().getName();
|
return Image.class.getPackage().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@ package org.hibernate.jpamodelgen.test.arraytype;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Feretnschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class TemperatureSamples {
|
public class TemperatureSamples {
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class ElementCollectionTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return House.class.getPackage().getName();
|
return ElementCollectionTest.class.getPackage().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,7 +35,7 @@ public class GenericsTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return Parent.class.getPackage().getName();
|
return GenericsTest.class.getPackage().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -40,7 +40,7 @@ public class InheritanceTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return Customer.class.getPackage().getName();
|
return InheritanceTest.class.getPackage().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<String> getOrmFiles() {
|
||||||
|
List<String> ormFiles = new ArrayList<String>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<String> getOrmFiles() {
|
||||||
|
List<String> ormFiles = new ArrayList<String>();
|
||||||
|
ormFiles.add( TestUtil.fcnToPath( XmlMetaCompleteTest.class.getPackage().getName() ) + "/orm.xml" );
|
||||||
|
return ormFiles;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hibernate.jpamodelgen.test.rawTypes;
|
package org.hibernate.jpamodelgen.test.rawtypes;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.hibernate.jpamodelgen.test.rawTypes;
|
package org.hibernate.jpamodelgen.test.rawtypes;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
|
@ -1,4 +1,4 @@
|
||||||
// $Id$
|
// $Id: RawTypesTest.java 18664 2010-01-28 16:56:51Z hardy.ferentschik $
|
||||||
/*
|
/*
|
||||||
* JBoss, Home of Professional Open Source
|
* JBoss, Home of Professional Open Source
|
||||||
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen.test.rawTypes;
|
package org.hibernate.jpamodelgen.test.rawtypes;
|
||||||
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class RawTypesTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return DeskWithRawType.class.getPackage().getName();
|
return DeskWithRawType.class.getPackage().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,34 +19,47 @@ package org.hibernate.jpamodelgen.test.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
import javax.tools.DiagnosticCollector;
|
import javax.tools.DiagnosticCollector;
|
||||||
import javax.tools.JavaCompiler;
|
import javax.tools.JavaCompiler;
|
||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
import javax.tools.StandardJavaFileManager;
|
import javax.tools.StandardJavaFileManager;
|
||||||
import javax.tools.ToolProvider;
|
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;
|
import static org.testng.FileAssert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public abstract class CompilationTest {
|
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 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 sourceBaseDir;
|
||||||
private static final String outBaseDir;
|
private static final String outBaseDir;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String tmp = System.getProperty( "sourceBaseDir" );
|
String tmp = System.getProperty( SOURCE_BASE_DIR_PROPERTY );
|
||||||
if ( tmp == null ) {
|
if ( tmp == null ) {
|
||||||
fail( "The system property sourceBaseDir has to be set and point to the base directory of the test java sources." );
|
fail( "The system property sourceBaseDir has to be set and point to the base directory of the test java sources." );
|
||||||
}
|
}
|
||||||
sourceBaseDir = tmp;
|
sourceBaseDir = tmp;
|
||||||
|
|
||||||
tmp = System.getProperty( "outBaseDir" );
|
tmp = System.getProperty( OUT_BASE_DIR_PROPERTY );
|
||||||
if ( tmp == null ) {
|
if ( tmp == null ) {
|
||||||
fail( "The system property outBaseDir has to be set and point to the base directory of the test output directory." );
|
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() {
|
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<String> options = createJavaOptions();
|
List<String> options = createJavaOptions();
|
||||||
|
|
||||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
@ -82,6 +89,7 @@ public abstract class CompilationTest {
|
||||||
compilationUnits = fileManager.getJavaFileObjectsFromFiles(
|
compilationUnits = fileManager.getJavaFileObjectsFromFiles(
|
||||||
getCompilationUnits( outBaseDir )
|
getCompilationUnits( outBaseDir )
|
||||||
);
|
);
|
||||||
|
options.add( "-proc:none" ); // for the second compile skip the processor
|
||||||
compileSources( options, compiler, diagnostics, fileManager, compilationUnits );
|
compileSources( options, compiler, diagnostics, fileManager, compilationUnits );
|
||||||
fileManager.close();
|
fileManager.close();
|
||||||
}
|
}
|
||||||
|
@ -91,24 +99,46 @@ public abstract class CompilationTest {
|
||||||
null, fileManager, diagnostics, options, null, compilationUnits
|
null, fileManager, diagnostics, options, null, compilationUnits
|
||||||
);
|
);
|
||||||
task.call();
|
task.call();
|
||||||
// for ( Diagnostic diagnostic : diagnostics.getDiagnostics() ) {
|
for ( Diagnostic diagnostic : diagnostics.getDiagnostics() ) {
|
||||||
// System.out.println( diagnostic.getMessage( null ) );
|
log.debug( diagnostic.getMessage( null ) );
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> createJavaOptions() {
|
private List<String> 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<String> options = new ArrayList<String>();
|
List<String> options = new ArrayList<String>();
|
||||||
options.add( "-d" );
|
options.add( "-d" );
|
||||||
options.add( outBaseDir );
|
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<String, String> 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;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<File> getCompilationUnits(String baseDir) {
|
private List<File> getCompilationUnits(String baseDir) {
|
||||||
List<File> javaFiles = new ArrayList<File>();
|
List<File> javaFiles = new ArrayList<File>();
|
||||||
String packageDirName = baseDir + PATH_SEPARATOR + getTestPackage().replace( ".", PATH_SEPARATOR );
|
String packageDirName = baseDir + PATH_SEPARATOR + getPackageNameOfTestSources().replace( ".", PATH_SEPARATOR );
|
||||||
File packageDir = new File( packageDirName );
|
File packageDir = new File( packageDirName );
|
||||||
FilenameFilter javaFileFilter = new FilenameFilter() {
|
FilenameFilter javaFileFilter = new FilenameFilter() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,16 +147,22 @@ public abstract class CompilationTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final File[] files = packageDir.listFiles( javaFileFilter );
|
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 );
|
throw new RuntimeException( "Cannot find package directory (is your base dir correct?): " + packageDirName );
|
||||||
}
|
}
|
||||||
for ( File file : files ) {
|
javaFiles.addAll( Arrays.asList( files ) );
|
||||||
javaFiles.add( file );
|
|
||||||
}
|
|
||||||
return javaFiles;
|
return javaFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected String getTestPackage();
|
abstract protected String getPackageNameOfTestSources();
|
||||||
|
|
||||||
|
protected Map<String, String> getProcessorOptions() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<String> getOrmFiles() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,14 @@
|
||||||
package org.hibernate.jpamodelgen.test.util;
|
package org.hibernate.jpamodelgen.test.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.GenericArrayType;
|
import java.lang.reflect.GenericArrayType;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
@ -34,8 +37,9 @@ import static org.testng.FileAssert.fail;
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class TestUtil {
|
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 PATH_SEPARATOR = System.getProperty( "file.separator" );
|
||||||
|
private static final String PACKAGE_SEPARATOR = ".";
|
||||||
private static final String META_MODEL_CLASS_POSTFIX = "_";
|
private static final String META_MODEL_CLASS_POSTFIX = "_";
|
||||||
private static final String outBaseDir;
|
private static final String outBaseDir;
|
||||||
|
|
||||||
|
@ -50,11 +54,23 @@ public class TestUtil {
|
||||||
private TestUtil() {
|
private TestUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearOutputFolder() {
|
public static void deleteGeneratedSourceFiles(File path) {
|
||||||
File outDir = new File( outBaseDir );
|
if ( path.exists() ) {
|
||||||
File[] files = outDir.listFiles();
|
File[] files = path.listFiles( new MetaModelFilenameFilter() );
|
||||||
for ( File file : files ) {
|
for ( File file : files ) {
|
||||||
file.delete();
|
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" );
|
assertNotNull( clazz, "Class parameter cannot be null" );
|
||||||
String metaModelClassName = clazz.getName() + META_MODEL_CLASS_POSTFIX;
|
String metaModelClassName = clazz.getName() + META_MODEL_CLASS_POSTFIX;
|
||||||
// generate the file name
|
// generate the file name
|
||||||
String fileName = metaModelClassName.replace( ".", PATH_SEPARATOR );
|
String fileName = metaModelClassName.replace( PACKAGE_SEPARATOR, PATH_SEPARATOR );
|
||||||
fileName = fileName.concat( ".java" );
|
fileName = fileName.concat( ".java" );
|
||||||
File sourceFile = new File( outBaseDir + PATH_SEPARATOR + fileName );
|
File sourceFile = new File( outBaseDir + PATH_SEPARATOR + fileName );
|
||||||
assertFalse( sourceFile.exists(), "There should be no source file: " + 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) {
|
public static void assertAttributeTypeInMetaModelFor(Class<?> clazz, String fieldName, Class<?> expectedType, String errorString) {
|
||||||
Field field = getFieldFromMetamodelFor( clazz, fieldName );
|
Field field = getFieldFromMetamodelFor( clazz, fieldName );
|
||||||
assertNotNull( field );
|
assertNotNull( field, "Cannot find field '" + fieldName + "' in " + clazz.getName() );
|
||||||
ParameterizedType type = ( ParameterizedType ) field.getGenericType();
|
ParameterizedType type = ( ParameterizedType ) field.getGenericType();
|
||||||
Type actualType = type.getActualTypeArguments()[1];
|
Type actualType = type.getActualTypeArguments()[1];
|
||||||
if ( expectedType.isArray() ) {
|
if ( expectedType.isArray() ) {
|
||||||
expectedType = expectedType.getComponentType();
|
expectedType = expectedType.getComponentType();
|
||||||
actualType = ( ( GenericArrayType ) actualType ).getGenericComponentType();
|
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) {
|
public static void assertMapAttributesInMetaModelFor(Class<?> clazz, String fieldName, Class<?> expectedMapKey, Class<?> expectedMapValue, String errorString) {
|
||||||
|
@ -157,6 +177,23 @@ public class TestUtil {
|
||||||
}
|
}
|
||||||
return field;
|
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" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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<String> getOrmFiles() {
|
||||||
|
List<String> ormFiles = new ArrayList<String>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,14 +21,14 @@ package org.hibernate.jpamodelgen.test.xmlmapped;
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class LivingBeing {
|
public class LivingBeing {
|
||||||
boolean isReallyAlive;
|
boolean reallyAlive;
|
||||||
|
|
||||||
public boolean isReallyAlive() {
|
public boolean isReallyAlive() {
|
||||||
return isReallyAlive;
|
return reallyAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReallyAlive(boolean reallyAlive) {
|
public void setReallyAlive(boolean reallyAlive) {
|
||||||
isReallyAlive = reallyAlive;
|
this.reallyAlive = reallyAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int nonPersistent() {
|
public int nonPersistent() {
|
||||||
|
|
|
@ -17,9 +17,14 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpamodelgen.test.xmlmapped;
|
package org.hibernate.jpamodelgen.test.xmlmapped;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor;
|
||||||
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
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.assertAttributeTypeInMetaModelFor;
|
||||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
|
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" );
|
assertAttributeTypeInMetaModelFor( Boy.class, "nickNames", String.class, "target class overridden in xml" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClassHierarchy() {
|
public void testClassHierarchy() {
|
||||||
assertMetamodelClassGeneratedFor( Mammal.class );
|
assertMetamodelClassGeneratedFor( Mammal.class );
|
||||||
|
@ -98,7 +102,17 @@ public class XmlMappingTest extends CompilationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestPackage() {
|
protected String getPackageNameOfTestSources() {
|
||||||
return Address.class.getPackage().getName();
|
return XmlMappingTest.class.getPackage().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, String> getProcessorOptions() {
|
||||||
|
Map<String, String> properties = new HashMap<String, String>();
|
||||||
|
properties.put(
|
||||||
|
JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION,
|
||||||
|
TestUtil.fcnToPath( XmlMappingTest.class.getPackage().getName() ) + "/persistence.xml"
|
||||||
|
);
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,12 +4,5 @@
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence.xsd" version="2.0">
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence.xsd" version="2.0">
|
||||||
<persistence-unit name="annotation-processor" transaction-type="JTA">
|
<persistence-unit name="annotation-processor" transaction-type="JTA">
|
||||||
<description>Test persistence unit</description>
|
<description>Test persistence unit</description>
|
||||||
<mapping-file>/META-INF/dummy.xml</mapping-file>
|
|
||||||
<mapping-file>/META-INF/malformed-mapping-xml.xml</mapping-file>
|
|
||||||
<mapping-file>/META-INF/jpa1-orm.xml</mapping-file>
|
|
||||||
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/address.xml</mapping-file>
|
|
||||||
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/building.xml</mapping-file>
|
|
||||||
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml</mapping-file>
|
|
||||||
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/boy.xml</mapping-file>
|
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
version="2.0"
|
version="2.0"
|
||||||
>
|
>
|
||||||
<package>org.hibernate.jpamodelgen.test.accesstype</package>
|
<package>org.hibernate.jpamodelgen.test.accesstype</package>
|
||||||
<!-- default package -->
|
|
||||||
<entity class="Order" access="FIELD" metadata-complete="true"> <!--means ignore annotations-->
|
<entity class="Order" access="FIELD" metadata-complete="true"> <!--means ignore annotations-->
|
||||||
<attributes>
|
<attributes>
|
||||||
<id name="id">
|
<id name="id">
|
||||||
|
@ -23,7 +22,6 @@
|
||||||
</cascade>
|
</cascade>
|
||||||
</one-to-many>
|
</one-to-many>
|
||||||
<element-collection name="notes"/>
|
<element-collection name="notes"/>
|
||||||
<!-- new in JPA 2 -->
|
|
||||||
</attributes>
|
</attributes>
|
||||||
</entity>
|
</entity>
|
||||||
</entity-mappings>
|
</entity-mappings>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
|
||||||
|
version="2.0"
|
||||||
|
>
|
||||||
|
<!-- foo.bar should get ignored since class is fully qualified -->
|
||||||
|
<package>foo.bar</package>
|
||||||
|
<entity class="org.hibernate.jpamodelgen.test.mixedmode.Car">
|
||||||
|
<attributes>
|
||||||
|
<basic name="horsePower"/>
|
||||||
|
<basic name="make"/>
|
||||||
|
</attributes>
|
||||||
|
</entity>
|
||||||
|
</entity-mappings>
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
|
||||||
|
version="2.0"
|
||||||
|
>
|
||||||
|
<!-- no implicit or explicit access configured here -->
|
||||||
|
<embeddable class="org.hibernate.jpamodelgen.test.mixedmode.Coordinates">
|
||||||
|
<attributes>
|
||||||
|
<basic name="longitude"/>
|
||||||
|
<basic name="latitude"/>
|
||||||
|
</attributes>
|
||||||
|
</embeddable>
|
||||||
|
<embeddable class="org.hibernate.jpamodelgen.test.mixedmode.ZeroCoordinates">
|
||||||
|
<attributes>
|
||||||
|
<basic name="longitude"/>
|
||||||
|
<basic name="latitude"/>
|
||||||
|
</attributes>
|
||||||
|
</embeddable>
|
||||||
|
</entity-mappings>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
|
||||||
|
version="2.0"
|
||||||
|
>
|
||||||
|
<persistence-unit-metadata>
|
||||||
|
<xml-mapping-metadata-complete/>
|
||||||
|
</persistence-unit-metadata>
|
||||||
|
<package>org.hibernate.jpamodelgen.test.mixedmode</package>
|
||||||
|
<entity class="Person" access="FIELD" metadata-complete="true">
|
||||||
|
<attributes>
|
||||||
|
<id name="id"/>
|
||||||
|
</attributes>
|
||||||
|
</entity>
|
||||||
|
</entity-mappings>
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
|
||||||
|
version="2.0"
|
||||||
|
>
|
||||||
|
<!-- foo.bar should get ignored since class is fully qualified -->
|
||||||
|
<package>foo.bar</package>
|
||||||
|
<entity class="org.hibernate.jpamodelgen.test.mixedmode.RentalCar">
|
||||||
|
<attributes>
|
||||||
|
<many-to-one name="company" access="FIELD"/>
|
||||||
|
</attributes>
|
||||||
|
</entity>
|
||||||
|
</entity-mappings>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
|
||||||
|
version="2.0"
|
||||||
|
>
|
||||||
|
<!-- foo.bar should get ignored since class is fully qualified -->
|
||||||
|
<package>foo.bar</package>
|
||||||
|
<entity class="org.hibernate.jpamodelgen.test.mixedmode.Truck">
|
||||||
|
<attributes>
|
||||||
|
<basic name="horsePower" access="PROPERTY"/>
|
||||||
|
<basic name="make"/>
|
||||||
|
</attributes>
|
||||||
|
</entity>
|
||||||
|
</entity-mappings>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<package>org.hibernate.jpamodelgen.test.xmlmapped</package>
|
<package>org.hibernate.jpamodelgen.test.xmlmapped</package>
|
||||||
<entity class="LivingBeing" access="FIELD" metadata-complete="true">
|
<entity class="LivingBeing" access="FIELD" metadata-complete="true">
|
||||||
<attributes>
|
<attributes>
|
||||||
<basic name="isReallyAlive"/>
|
<basic name="reallyAlive"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</entity>
|
</entity>
|
||||||
<entity class="Mammal" access="FIELD" metadata-complete="true">
|
<entity class="Mammal" access="FIELD" metadata-complete="true">
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence.xsd" version="2.0">
|
||||||
|
<persistence-unit name="annotation-processor" transaction-type="JTA">
|
||||||
|
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/address.xml</mapping-file>
|
||||||
|
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/building.xml</mapping-file>
|
||||||
|
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/mammal.xml</mapping-file>
|
||||||
|
<mapping-file>/org/hibernate/jpamodelgen/test/xmlmapped/boy.xml</mapping-file>
|
||||||
|
</persistence-unit>
|
||||||
|
</persistence>
|
|
@ -8,7 +8,8 @@
|
||||||
<package name="org.hibernate.jpamodelgen.test.elementcollection"/>
|
<package name="org.hibernate.jpamodelgen.test.elementcollection"/>
|
||||||
<package name="org.hibernate.jpamodelgen.test.generics"/>
|
<package name="org.hibernate.jpamodelgen.test.generics"/>
|
||||||
<package name="org.hibernate.jpamodelgen.test.inheritance"/>
|
<package name="org.hibernate.jpamodelgen.test.inheritance"/>
|
||||||
<package name="org.hibernate.jpamodelgen.test.rawTypes"/>
|
<package name="org.hibernate.jpamodelgen.test.mixedmode"/>
|
||||||
|
<package name="org.hibernate.jpamodelgen.test.rawtypes"/>
|
||||||
<package name="org.hibernate.jpamodelgen.test.xmlmapped"/>
|
<package name="org.hibernate.jpamodelgen.test.xmlmapped"/>
|
||||||
</packages>
|
</packages>
|
||||||
</test>
|
</test>
|
||||||
|
|
Loading…
Reference in New Issue