HHH-4691 - Added support for access tye configuration via xml

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18506 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Hardy Ferentschik 2010-01-11 20:23:08 +00:00
parent b4caf0b909
commit 1c25ab12ef
11 changed files with 535 additions and 80 deletions

View File

@ -1,3 +1,4 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -259,7 +260,7 @@ public class AnnotationConfiguration extends Configuration {
@Override
protected void reset() {
super.reset();
namedGenerators = new HashMap();
namedGenerators = new HashMap<String, IdGenerator>();
joins = new HashMap<String, Map<String, Join>>();
classTypes = new HashMap<String, AnnotatedClassType>();
generatorTables = new HashMap<String, Properties>();
@ -784,7 +785,7 @@ public class AnnotationConfiguration extends Configuration {
private static void findClassNames(
String defaultPackage, final Element startNode,
final java.util.Set names
final java.util.Set<String> names
) {
// if we have some extends we need to check if those classes possibly could be inside the
// same hbm.xml file...

View File

@ -61,7 +61,7 @@ public class JPAMetadataProvider implements MetadataProvider {
}
defaults.put( EntityListeners.class, entityListeners );
for ( Element element : xmlContext.getAllDocuments() ) {
@SuppressWarnings( "unchecked" )
List<Element> elements = element.elements( "sequence-generator" );
List<SequenceGenerator> sequenceGenerators = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );
if ( sequenceGenerators == null ) {

View File

@ -1,3 +1,4 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -36,6 +37,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
@ -107,7 +110,6 @@ import javax.persistence.ElementCollection;
import org.dom4j.Attribute;
import org.dom4j.Element;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor;
@ -126,12 +128,13 @@ import org.slf4j.LoggerFactory;
* @author Paolo Perrotta
* @author Davide Marchignoli
* @author Emmanuel Bernard
* @author Hardy Ferentschik
*/
@SuppressWarnings("unchecked")
public class JPAOverridenAnnotationReader implements AnnotationReader {
private Logger log = LoggerFactory.getLogger( JPAOverridenAnnotationReader.class );
private static final Map<Class, String> annotationToXml;
private static final String SCHEMA_VALIDATION = "Activate schema validation for more informations";
private static final String SCHEMA_VALIDATION = "Activate schema validation for more information";
private static final Filter FILTER = new Filter() {
public boolean returnStatic() {
return false;
@ -292,12 +295,16 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
return annotations;
}
/*
* The idea is to create annotation proxies for the xml configuration elements. Using this proxy annotations together
* with the {@code JPAMetadataprovider} allows to handle xml configuration the same way as annotation configuration.
*/
private void initAnnotations() {
if ( annotations == null ) {
XMLContext.Default defaults = xmlContext.getDefault( className );
if ( className != null && propertyName == null ) {
//is a class
Element tree = xmlContext.getXMLTree( className, null );
Element tree = xmlContext.getXMLTree( className );
Annotation[] annotations = getJavaAnnotations();
List<Annotation> annotationList = new ArrayList<Annotation>( annotations.length + 5 );
annotationsMap = new HashMap<Class, Annotation>( annotations.length + 5 );
@ -336,7 +343,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
checkForOrphanProperties( tree );
}
else if ( className != null ) { //&& propertyName != null ) { //always true but less confusing
Element tree = xmlContext.getXMLTree( className, propertyName );
Element tree = xmlContext.getXMLTree( className );
Annotation[] annotations = getJavaAnnotations();
List<Annotation> annotationList = new ArrayList<Annotation>( annotations.length + 5 );
annotationsMap = new HashMap<Class, Annotation>( annotations.length + 5 );
@ -353,7 +360,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
else {
if ( defaults.canUseJavaAnnotations() ) {
Annotation annotation = getJavaAnnotation( AccessType.class );
Annotation annotation = getJavaAnnotation( Access.class );
addIfNotNull( annotationList, annotation );
}
getId( annotationList, defaults );
@ -425,13 +432,18 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
/**
* Addes the Annotation to the list (only if it's not null) and then returns it.
* Adds {@code annotation} to the list (only if it's not null) and then returns it.
*
* @param annotationList The list of annotations.
* @param annotation The annotation to add to the list.
*
* @return The annotation which was added to the list or {@code null}.
*/
private Annotation addIfNotNull(List<Annotation> annotationList, Annotation element) {
if ( element != null ) {
annotationList.add( element );
private Annotation addIfNotNull(List<Annotation> annotationList, Annotation annotation) {
if ( annotation != null ) {
annotationList.add( annotation );
}
return element;
return annotation;
}
//TODO mutualize the next 2 methods
@ -654,14 +666,15 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
getFetchType( ad, element );
getCascades( ad, element, defaults );
getJoinTable( annotationList, element, defaults );
buildJoinColumns( annotationList, element, defaults );
buildJoinColumns( annotationList, element);
Annotation annotation = getPrimaryKeyJoinColumns( element, defaults );
addIfNotNull( annotationList, annotation );
copyBooleanAttribute( ad, element, "optional" );
copyStringAttribute( ad, element, "mapped-by", false );
getOrderBy( annotationList, element, defaults );
getMapKey( annotationList, element, defaults );
getOrderBy( annotationList, element );
getMapKey( annotationList, element );
annotationList.add( AnnotationFactory.create( ad ) );
getAccessType( annotationList, element );
}
}
if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) {
@ -772,7 +785,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
}
private void getOrderBy(List<Annotation> annotationList, Element element, XMLContext.Default defaults) {
private void getOrderBy(List<Annotation> annotationList, Element element) {
Element subelement = element != null ? element.element( "order-by" ) : null;
if ( subelement != null ) {
String orderByString = subelement.getTextTrim();
@ -782,7 +795,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
}
private void getMapKey(List<Annotation> annotationList, Element element, XMLContext.Default defaults) {
private void getMapKey(List<Annotation> annotationList, Element element) {
Element subelement = element != null ? element.element( "map-key" ) : null;
if ( subelement != null ) {
String mapKeyString = subelement.attributeValue( "name" );
@ -792,7 +805,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
}
private void buildJoinColumns(List<Annotation> annotationList, Element element, XMLContext.Default defaults) {
private void buildJoinColumns(List<Annotation> annotationList, Element element) {
JoinColumn[] joinColumns = getJoinColumns( element, false );
if ( joinColumns.length > 0 ) {
AnnotationDescriptor ad = new AnnotationDescriptor( JoinColumns.class );
@ -867,6 +880,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
getTemporal( annotationList, element );
AnnotationDescriptor basic = new AnnotationDescriptor( Version.class );
annotationList.add( AnnotationFactory.create( basic ) );
getAccessType( annotationList, element );
}
}
if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) {
@ -889,6 +903,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
if ( "basic".equals( element.getName() ) ) {
Annotation annotation = buildColumns( element );
addIfNotNull( annotationList, annotation );
getAccessType( annotationList, element );
getTemporal( annotationList, element );
getLob( annotationList, element );
getEnumerated( annotationList, element );
@ -971,21 +986,6 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
AnnotationDescriptor ad = new AnnotationDescriptor( EmbeddedId.class );
annotationList.add( AnnotationFactory.create( ad ) );
}
// else {
// if ( defaults.canUseJavaAnnotations() ) {
// if ( ! properOverridingOnMetadataNonComplete ) {
// //check that id exists on the other attribute
// //TODO Id too?
// if ( mirroredAttribute == null || ! mirroredAttribute.isAnnotationPresent(
// EmbeddedId.class
// ) ) {
// throw new AnnotationException(
// "Cannot override an property with <embedded-id> not having an @EmbeddedId already"
// );
// }
// }
// }
// }
}
}
if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) {
@ -1054,20 +1054,8 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
addIfNotNull( annotationList, annotation );
AnnotationDescriptor id = new AnnotationDescriptor( Id.class );
annotationList.add( AnnotationFactory.create( id ) );
getAccessType( annotationList, element );
}
// else {
// if ( defaults.canUseJavaAnnotations() ) {
// if ( ! properOverridingOnMetadataNonComplete ) {
// //check that id exists on the other attribute
// //TODO EmbeddedId too?
// if ( mirroredAttribute == null || ! mirroredAttribute.isAnnotationPresent( Id.class ) ) {
// throw new AnnotationException(
// "Cannot override a property with <id> it does not have an @Id already"
// );
// }
// }
// }
// }
}
}
if ( elementsForProperty.size() == 0 && defaults.canUseJavaAnnotations() ) {
@ -1101,8 +1089,8 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
private boolean isProcessingId(XMLContext.Default defaults) {
boolean isExplicit = defaults.getAccess() != null;
boolean correctAccess =
( PropertyType.PROPERTY.equals( propertyType ) && "property".equals( defaults.getAccess() ) )
|| ( PropertyType.FIELD.equals( propertyType ) && "field".equals( defaults.getAccess() ) );
( PropertyType.PROPERTY.equals( propertyType ) && AccessType.PROPERTY.equals( defaults.getAccess() ) )
|| ( PropertyType.FIELD.equals( propertyType ) && AccessType.FIELD.equals( defaults.getAccess() ) );
boolean hasId = defaults.canUseJavaAnnotations()
&& ( isJavaAnnotationPresent( Id.class ) || isJavaAnnotationPresent( EmbeddedId.class ) );
//if ( properAccessOnMetadataComplete || properOverridingOnMetadataNonComplete ) {
@ -1180,6 +1168,31 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
}
private void getAccessType(List<Annotation> annotationList, Element element) {
if ( element == null ) {
return;
}
String access = element.attributeValue( "access" );
if ( access != null ) {
AnnotationDescriptor ad = new AnnotationDescriptor( Access.class );
AccessType type;
try {
type = AccessType.valueOf( access );
}
catch ( IllegalArgumentException e ) {
throw new AnnotationException( access + " is not a valid access type. Check you xml confguration." );
}
if ( ( AccessType.PROPERTY.equals( type ) && this.element instanceof Method ) ||
( AccessType.FIELD.equals( type ) && this.element instanceof Field ) ) {
return;
}
ad.setValue( "value", type );
annotationList.add( AnnotationFactory.create( ad ) );
}
}
private AssociationOverrides getAssociationOverrides(Element tree, XMLContext.Default defaults) {
List<AssociationOverride> attributes = (List<AssociationOverride>) buildAssociationOverrides( tree );
if ( defaults.canUseJavaAnnotations() ) {
@ -1299,7 +1312,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
if ( !current.getName().equals( "attribute-override" ) ) continue;
AnnotationDescriptor override = new AnnotationDescriptor( AttributeOverride.class );
copyStringAttribute( override, current, "name", true );
Element column = current != null ? current.element( "column" ) : null;
Element column = current.element( "column" );
override.setValue( "column", getColumn( column, true, current ) );
overrides.add( (AttributeOverride) AnnotationFactory.create( override ) );
}
@ -1345,22 +1358,25 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
}
}
private AccessType getAccessType(Element tree, XMLContext.Default defaults) {
private Access getAccessType(Element tree, XMLContext.Default defaults) {
String access = tree == null ? null : tree.attributeValue( "access" );
if ( "FIELD".equals( access ) || "PROPERTY".equals( access ) ) {
access = access.toLowerCase();
}
if ( access != null ) {
AnnotationDescriptor ad = new AnnotationDescriptor( AccessType.class );
ad.setValue( "value", access );
AnnotationDescriptor ad = new AnnotationDescriptor( Access.class );
AccessType type;
try {
type = AccessType.valueOf( access );
}
catch ( IllegalArgumentException e ) {
throw new AnnotationException( access + " is not a valid access type. Check you xml confguration." );
}
ad.setValue( "value", type );
return AnnotationFactory.create( ad );
}
else if ( defaults.canUseJavaAnnotations() && isJavaAnnotationPresent( AccessType.class ) ) {
AccessType annotation = getJavaAnnotation( AccessType.class );
return annotation;
else if ( defaults.canUseJavaAnnotations() && isJavaAnnotationPresent( Access.class ) ) {
return getJavaAnnotation( Access.class );
}
else if ( defaults.getAccess() != null ) {
AnnotationDescriptor ad = new AnnotationDescriptor( AccessType.class );
AnnotationDescriptor ad = new AnnotationDescriptor( Access.class );
ad.setValue( "value", defaults.getAccess() );
return AnnotationFactory.create( ad );
}
@ -1432,7 +1448,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
if ( clazzName == null ) {
throw new AnnotationException( "<entity-result> without entity-class. " + SCHEMA_VALIDATION );
}
Class clazz = null;
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
@ -1469,7 +1485,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
//FIXME there is never such a result-class, get rid of it?
String clazzName = subelement.attributeValue( "result-class" );
if ( StringHelper.isNotEmpty( clazzName ) ) {
Class clazz = null;
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
@ -1605,7 +1621,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
ann.setValue( "hints", queryHints.toArray( new QueryHint[queryHints.size()] ) );
String clazzName = subelement.attributeValue( "result-class" );
if ( StringHelper.isNotEmpty( clazzName ) ) {
Class clazz = null;
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
@ -1803,7 +1819,7 @@ public class JPAOverridenAnnotationReader implements AnnotationReader {
Attribute attr = element.attribute( "class" );
if ( attr != null ) {
AnnotationDescriptor ad = new AnnotationDescriptor( IdClass.class );
Class clazz = null;
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( attr.getValue(), defaults ),

View File

@ -28,9 +28,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.AccessType;
import org.dom4j.Document;
import org.dom4j.Element;
import org.hibernate.AnnotationException;
import org.hibernate.util.StringHelper;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@ -47,8 +52,10 @@ public class XMLContext {
private boolean hasContext = false;
/**
* Add a document and return the list of added classes names
* @param doc The xml document to add
* @return Add a xml document to this context and return the list of added class names.
*/
@SuppressWarnings( "unchecked" )
public List<String> addDocument(Document doc) {
hasContext = true;
List<String> addedClasses = new ArrayList<String>();
@ -70,7 +77,7 @@ public class XMLContext {
unitElement = defaultElement.element( "catalog" );
globalDefaults.setCatalog( unitElement != null ? unitElement.getTextTrim() : null );
unitElement = defaultElement.element( "access" );
globalDefaults.setAccess( unitElement != null ? unitElement.getTextTrim() : null );
setAccess( unitElement, globalDefaults );
unitElement = defaultElement.element( "cascade-persist" );
globalDefaults.setCascadePersist( unitElement != null ? Boolean.TRUE : null );
unitElement = defaultElement.element( "delimited-identifiers" );
@ -93,7 +100,7 @@ public class XMLContext {
unitElement = root.element( "catalog" );
entityMappingDefault.setCatalog( unitElement != null ? unitElement.getTextTrim() : null );
unitElement = root.element( "access" );
entityMappingDefault.setAccess( unitElement != null ? unitElement.getTextTrim() : null );
setAccess( unitElement, entityMappingDefault );
defaultElements.add( root );
List<Element> entities = (List<Element>) root.elements( "entity" );
@ -107,6 +114,26 @@ public class XMLContext {
return addedClasses;
}
private void setAccess(Element unitElement, Default defaultType) {
if ( unitElement != null ) {
String access = unitElement.getTextTrim();
setAccess( access, defaultType );
}
}
private void setAccess( String access, Default defaultType) {
AccessType type;
if ( access != null ) {
try {
type = AccessType.valueOf( access );
}
catch ( IllegalArgumentException e ) {
throw new AnnotationException( "Invalid access type " + access + " (check your xml configuration)" );
}
defaultType.setAccess( type );
}
}
private void addClass(List<Element> entities, String packageName, Default defaults, List<String> addedClasses) {
for (Element element : entities) {
String className = buildSafeClassName( element.attributeValue( "class" ), packageName );
@ -123,7 +150,7 @@ public class XMLContext {
localDefault.setMetadataComplete( Boolean.parseBoolean( metadataCompleteString ) );
}
String access = element.attributeValue( "access" );
if ( access != null ) localDefault.setAccess( access );
setAccess( access, localDefault );
defaultsOverriding.put( className, localDefault );
log.debug( "Adding XML overriding information for {}", className );
@ -135,6 +162,7 @@ public class XMLContext {
List<String> localAddedClasses = new ArrayList<String>();
Element listeners = element.element( "entity-listeners" );
if ( listeners != null ) {
@SuppressWarnings( "unchecked" )
List<Element> elements = (List<Element>) listeners.elements( "entity-listener" );
for (Element listener : elements) {
String listenerClassName = buildSafeClassName( listener.attributeValue( "class" ), packageName );
@ -181,7 +209,7 @@ public class XMLContext {
return xmlDefault;
}
public Element getXMLTree(String className, String methodName) {
public Element getXMLTree(String className ) {
return classOverriding.get( className );
}
@ -194,7 +222,7 @@ public class XMLContext {
}
public static class Default {
private String access;
private AccessType access;
private String packageName;
private String schema;
private String catalog;
@ -202,17 +230,12 @@ public class XMLContext {
private Boolean cascadePersist;
private Boolean delimitedIdentifier;
public String getAccess() {
public AccessType getAccess() {
return access;
}
protected void setAccess(String access) {
if ( "FIELD".equals( access ) || "PROPERTY".equals( access ) ) {
this.access = access.toLowerCase();
}
else {
this.access = access;
}
protected void setAccess(AccessType access) {
this.access = access;
}
public String getCatalog() {
@ -244,7 +267,7 @@ public class XMLContext {
}
public boolean canUseJavaAnnotations() {
return metadataComplete == null || !metadataComplete.booleanValue();
return metadataComplete == null || !metadataComplete;
}
protected void setMetadataComplete(Boolean metadataComplete) {

View File

@ -1,4 +1,4 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
//$Id$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -37,6 +37,8 @@ import org.hibernate.tuple.entity.PojoEntityTuplizer;
/**
* Tests verifying the correct behaviour for the usage of {@code @javax.persistence.Access}.
*
* @author Hardy Ferentschik
*/
public class AccessMappingTest extends TestCase {

View File

@ -0,0 +1,49 @@
// $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.test.annotations.access.xml;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
/**
* @author Hardy Ferentschik
*/
public class Crew {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -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.test.annotations.access.xml;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Driver {
@Id
@GeneratedValue
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -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.test.annotations.access.xml;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class RentalCar {
@Id
@GeneratedValue
private int id;
private Driver driver;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Driver getDriver() {
return driver;
}
public void setDriver(Driver driver) {
this.driver = driver;
}
}

View File

@ -0,0 +1,62 @@
// $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.test.annotations.access.xml;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Tourist {
@Id
@GeneratedValue
private long id;
private String name;
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String destination;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}

View File

@ -0,0 +1,29 @@
// $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.test.annotations.access.xml;
import javax.persistence.Entity;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Waiter extends Crew {
}

View File

@ -0,0 +1,173 @@
//$Id$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.annotations.access.xml;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.persistence.AccessType;
import junit.framework.TestCase;
import org.hibernate.EntityMode;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.property.BasicPropertyAccessor;
import org.hibernate.property.DirectPropertyAccessor;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.PojoEntityTuplizer;
/**
* Test verifying that it is possible to configure the access type via xml configuration.
*
* @author Hardy Ferentschik
*/
public class XmlAccessTest extends TestCase {
public void testAccessOnBasicXmlElement() throws Exception {
Class<?> classUnderTest = Tourist.class;
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add( classUnderTest );
List<String> configFiles = Collections.emptyList();
SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles );
// without any xml configuration we have field access
assertAccessType( factory, classUnderTest, AccessType.FIELD );
// now with an additional xml configuration file changing the default access type for Tourist using basic
configFiles = new ArrayList<String>();
configFiles.add("org/hibernate/test/annotations/access/xml/Tourist.xml");
factory = buildSessionFactory( classes, configFiles );
assertAccessType( factory, classUnderTest, AccessType.PROPERTY );
}
public void testAccessOnPersistenceUnitDefaultsXmlElement() throws Exception {
Class<?> classUnderTest = Tourist.class;
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add( classUnderTest );
List<String> configFiles = Collections.emptyList();
SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles );
// without any xml configuration we have field access
assertAccessType( factory, classUnderTest, AccessType.FIELD );
// now with an additional xml configuration file changing the default access type for Tourist using persitence unit defaults
configFiles = new ArrayList<String>();
configFiles.add( "org/hibernate/test/annotations/access/xml/Tourist2.xml" );
factory = buildSessionFactory( classes, configFiles );
assertAccessType( factory, classUnderTest, AccessType.PROPERTY );
}
public void testAccessOnEntityMappingsXmlElement() throws Exception {
Class<?> classUnderTest = Tourist.class;
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add( classUnderTest );
List<String> configFiles = Collections.emptyList();
SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles );
// without any xml configuration we have field access
assertAccessType( factory, classUnderTest, AccessType.FIELD );
// now with an additional xml configuration file changing the default access type for Tourist using default in entity-mappings
configFiles = new ArrayList<String>();
configFiles.add( "org/hibernate/test/annotations/access/xml/Tourist3.xml" );
factory = buildSessionFactory( classes, configFiles );
assertAccessType( factory, classUnderTest, AccessType.PROPERTY );
}
public void testAccessOnEntityXmlElement() throws Exception {
Class<?> classUnderTest = Tourist.class;
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add( classUnderTest );
List<String> configFiles = Collections.emptyList();
SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles );
// without any xml configuration we have field access
assertAccessType( factory, classUnderTest, AccessType.FIELD );
// now with an additional xml configuration file changing the default access type for Tourist using entity level config
configFiles = new ArrayList<String>();
configFiles.add( "org/hibernate/test/annotations/access/xml/Tourist4.xml" );
factory = buildSessionFactory( classes, configFiles );
assertAccessType( factory, classUnderTest, AccessType.PROPERTY );
}
public void testAccessOnMappedSuperClassXmlElement() throws Exception {
Class<?> classUnderTest = Waiter.class;
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add( classUnderTest );
classes.add(Crew.class);
List<String> configFiles = new ArrayList<String>();
configFiles.add( "org/hibernate/test/annotations/access/xml/Crew.xml" );
SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles );
assertAccessType( factory, classUnderTest, AccessType.FIELD );
}
public void testAccessOnAssociationXmlElement() throws Exception {
Class<?> classUnderTest = RentalCar.class;
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add( classUnderTest );
classes.add(Driver.class);
List<String> configFiles = new ArrayList<String>();
configFiles.add( "org/hibernate/test/annotations/access/xml/RentalCar.xml" );
SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles );
assertAccessType( factory, classUnderTest, AccessType.PROPERTY );
}
private SessionFactoryImplementor buildSessionFactory(List<Class<?>> classesUnderTest, List<String> configFiles) {
assert classesUnderTest != null;
assert configFiles != null;
AnnotationConfiguration cfg = new AnnotationConfiguration();
for ( Class<?> clazz : classesUnderTest ) {
cfg.addAnnotatedClass( clazz );
}
for ( String configFile : configFiles ) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( configFile );
cfg.addInputStream( is );
}
return ( SessionFactoryImplementor ) cfg.buildSessionFactory();
}
// uses the first getter of the tupelizer for the assertions
private void assertAccessType(SessionFactoryImplementor factory, Class<?> classUnderTest, AccessType accessType) {
EntityMetamodel metaModel = factory.getEntityPersister( classUnderTest.getName() )
.getEntityMetamodel();
PojoEntityTuplizer tuplizer = ( PojoEntityTuplizer ) metaModel.getTuplizer( EntityMode.POJO );
if ( AccessType.FIELD.equals( accessType ) ) {
assertTrue(
"Field access was expected.",
tuplizer.getGetter( 0 ) instanceof DirectPropertyAccessor.DirectGetter
);
}
else {
assertTrue(
"Property access was expected.",
tuplizer.getGetter( 0 ) instanceof BasicPropertyAccessor.BasicGetter
);
}
}
}