diff --git a/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java b/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java index 29d2e81416..b585cd5fc8 100644 --- a/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java +++ b/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java @@ -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(); joins = new HashMap>(); classTypes = new HashMap(); generatorTables = new HashMap(); @@ -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 names ) { // if we have some extends we need to check if those classes possibly could be inside the // same hbm.xml file... diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAMetadataProvider.java b/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAMetadataProvider.java index e2ed42d319..6449bb2798 100644 --- a/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAMetadataProvider.java +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAMetadataProvider.java @@ -61,7 +61,7 @@ public class JPAMetadataProvider implements MetadataProvider { } defaults.put( EntityListeners.class, entityListeners ); for ( Element element : xmlContext.getAllDocuments() ) { - + @SuppressWarnings( "unchecked" ) List elements = element.elements( "sequence-generator" ); List sequenceGenerators = ( List ) defaults.get( SequenceGenerator.class ); if ( sequenceGenerators == null ) { diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverridenAnnotationReader.java b/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverridenAnnotationReader.java index 95caf1e4d8..0c2f47db88 100644 --- a/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverridenAnnotationReader.java +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/JPAOverridenAnnotationReader.java @@ -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 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 annotationList = new ArrayList( annotations.length + 5 ); annotationsMap = new HashMap( 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 annotationList = new ArrayList( annotations.length + 5 ); annotationsMap = new HashMap( 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 annotationList, Annotation element) { - if ( element != null ) { - annotationList.add( element ); + private Annotation addIfNotNull(List 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 annotationList, Element element, XMLContext.Default defaults) { + private void getOrderBy(List 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 annotationList, Element element, XMLContext.Default defaults) { + private void getMapKey(List 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 annotationList, Element element, XMLContext.Default defaults) { + private void buildJoinColumns(List 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 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 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 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 attributes = (List) 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( " 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 ), diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java b/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java index 17e04ad96e..f5f3c9fd2c 100644 --- a/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/reflection/XMLContext.java @@ -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 addDocument(Document doc) { hasContext = true; List addedClasses = new ArrayList(); @@ -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 entities = (List) 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 entities, String packageName, Default defaults, List 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 localAddedClasses = new ArrayList(); Element listeners = element.element( "entity-listeners" ); if ( listeners != null ) { + @SuppressWarnings( "unchecked" ) List elements = (List) 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) { diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java b/annotations/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java index 1d59a22e8d..8b4e6638a5 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/jpa/AccessMappingTest.java @@ -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 { diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Crew.java b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Crew.java new file mode 100644 index 0000000000..5d19aebeee --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Crew.java @@ -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; + } +} + + diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Driver.java b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Driver.java new file mode 100644 index 0000000000..9b4ddd7f23 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Driver.java @@ -0,0 +1,50 @@ +// $Id:$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.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; + } +} \ No newline at end of file diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/xml/RentalCar.java b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/RentalCar.java new file mode 100644 index 0000000000..d59b8f55bd --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/RentalCar.java @@ -0,0 +1,50 @@ +// $Id:$ +/* +* JBoss, Home of Professional Open Source +* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.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; + } +} \ No newline at end of file diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Tourist.java b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Tourist.java new file mode 100644 index 0000000000..e0610b98d2 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Tourist.java @@ -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; + } +} + + diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Waiter.java b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Waiter.java new file mode 100644 index 0000000000..229e80afd5 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/Waiter.java @@ -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 { +} + + diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java new file mode 100644 index 0000000000..9a5579c1a9 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/xml/XmlAccessTest.java @@ -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> classes = new ArrayList>(); + classes.add( classUnderTest ); + List 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(); + 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> classes = new ArrayList>(); + classes.add( classUnderTest ); + List 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(); + 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> classes = new ArrayList>(); + classes.add( classUnderTest ); + List 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(); + 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> classes = new ArrayList>(); + classes.add( classUnderTest ); + List 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(); + 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> classes = new ArrayList>(); + classes.add( classUnderTest ); + classes.add(Crew.class); + List configFiles = new ArrayList(); + 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> classes = new ArrayList>(); + classes.add( classUnderTest ); + classes.add(Driver.class); + List configFiles = new ArrayList(); + configFiles.add( "org/hibernate/test/annotations/access/xml/RentalCar.xml" ); + SessionFactoryImplementor factory = buildSessionFactory( classes, configFiles ); + assertAccessType( factory, classUnderTest, AccessType.PROPERTY ); + } + + private SessionFactoryImplementor buildSessionFactory(List> classesUnderTest, List 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 + ); + } + } +} \ No newline at end of file