diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/AbstractEntity.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/AbstractEntity.java new file mode 100644 index 0000000000..850fc7a4a2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/AbstractEntity.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.type.dynamicparameterized; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.hibernate.annotations.TypeDef; + +/** + * @author Daniel Gredler + */ +@MappedSuperclass +@TypeDef(name = "string", typeClass = MyStringType.class, defaultForType = String.class) +public abstract class AbstractEntity { + + @Id + @Temporal(TemporalType.DATE) + @Column(name = "ID") + Date id; + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/DynamicParameterizedTypeTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/DynamicParameterizedTypeTest.java new file mode 100644 index 0000000000..ea7a9c14f2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/DynamicParameterizedTypeTest.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.type.dynamicparameterized; + +import java.util.Date; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Daniel Gredler + */ +public class DynamicParameterizedTypeTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { AbstractEntity.class, Entity1.class, Entity2.class }; + } + + @Test + public void testParameterValues() { + + Session s = openSession(); + Transaction tx = s.beginTransaction(); + + Entity1 entity1 = new Entity1(); + entity1.id = new Date( 0 ); + + Entity2 entity2 = new Entity2(); + entity2.id = new Date( 0 ); + + s.persist( entity1 ); + s.persist( entity2 ); + s.flush(); + s.clear(); + + entity1 = (Entity1) s.byId( Entity1.class ).load( entity1.id ); + entity2 = (Entity2) s.byId( Entity2.class ).load( entity2.id ); + + Assert.assertEquals( "ENTITY1.PROP1", entity1.entity1_Prop1 ); + Assert.assertEquals( "ENTITY1.PROP2", entity1.entity1_Prop2 ); + Assert.assertEquals( "ENTITY1.PROP3.FOO", entity1.entity1_Prop3 ); + Assert.assertEquals( "ENTITY1.PROP4.BAR", entity1.entity1_Prop4 ); + Assert.assertEquals( "ENTITY1.PROP5", entity1.entity1_Prop5 ); + Assert.assertEquals( "ENTITY1.PROP6", entity1.entity1_Prop6 ); + + Assert.assertEquals( "ENTITY2.PROP1", entity2.entity2_Prop1 ); + Assert.assertEquals( "ENTITY2.PROP2", entity2.entity2_Prop2 ); + Assert.assertEquals( "ENTITY2.PROP3", entity2.entity2_Prop3 ); + Assert.assertEquals( "ENTITY2.PROP4", entity2.entity2_Prop4 ); + Assert.assertEquals( "ENTITY2.PROP5.BLAH", entity2.entity2_Prop5 ); + Assert.assertEquals( "ENTITY2.PROP6.YEAH", entity2.entity2_Prop6 ); + + tx.rollback(); + s.close(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/Entity1.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/Entity1.java new file mode 100644 index 0000000000..c14f4c1db8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/Entity1.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.type.dynamicparameterized; + +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +import org.hibernate.annotations.Parameter; +import org.hibernate.annotations.Type; + +/** + * @author Daniel Gredler + */ +@Entity +@Table(name = "ENTITY1") +@Access(AccessType.FIELD) +public class Entity1 extends AbstractEntity { + + @Column(name = "PROP1") + String entity1_Prop1; + + @Column(name = "PROP2") + String entity1_Prop2; + + @Column(name = "PROP3") + @Type(type = "string", parameters = @Parameter(name = "suffix", value = "foo")) + String entity1_Prop3; + + @Column(name = "PROP4") + @Type(type = "string", parameters = @Parameter(name = "suffix", value = "bar")) + String entity1_Prop4; + + @Column(name = "PROP5") + @Type(type = "string") + String entity1_Prop5; + + @Column(name = "PROP6") + @Type(type = "string") + String entity1_Prop6; +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/Entity2.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/Entity2.java new file mode 100644 index 0000000000..2fd4b2ecc9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/Entity2.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.type.dynamicparameterized; + +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +import org.hibernate.annotations.Parameter; +import org.hibernate.annotations.Type; + +/** + * @author Daniel Gredler + */ +@Entity +@Table(name = "ENTITY2") +@Access(AccessType.FIELD) +public class Entity2 extends AbstractEntity { + + @Column(name = "PROP1") + @Type(type = "string") + String entity2_Prop1; + + @Column(name = "PROP2") + @Type(type = "string") + String entity2_Prop2; + + @Column(name = "PROP3") + String entity2_Prop3; + + @Column(name = "PROP4") + String entity2_Prop4; + + @Column(name = "PROP5") + @Type(type = "string", parameters = @Parameter(name = "suffix", value = "blah")) + String entity2_Prop5; + + @Column(name = "PROP6") + @Type(type = "string", parameters = @Parameter(name = "suffix", value = "yeah")) + String entity2_Prop6; +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/MyStringType.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/MyStringType.java new file mode 100644 index 0000000000..0b734676b8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/type/dynamicparameterized/MyStringType.java @@ -0,0 +1,151 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.type.dynamicparameterized; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; + +import org.hibernate.annotations.common.reflection.XProperty; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.type.StringType; +import org.hibernate.usertype.DynamicParameterizedType; +import org.hibernate.usertype.UserType; +import org.junit.Assert; + +/** + * Always saves "[table-name].[field-name]" or "[table-name].[field-name].[optional-suffix]" into the database; this + * makes it easier to verify that valid parameter values are being passed into {@link #setParameterValues(Properties)}. + * + * @author Daniel Gredler + */ +public class MyStringType implements UserType, DynamicParameterizedType { + + private String value; + + @Override + public void setParameterValues(Properties params) { + this.value = assertInternallyConsistent( params ); + } + + /** + * Verifies that the specified parameters are internally consistent and valid, and then returns the value that + * should be persisted to the database based on the input parameters ("[table-name].[field-name]" or + * "[table-name].[field-name].[optional-suffix]"), so that we can later check that the parameters were externally + * consistent. + */ + protected String assertInternallyConsistent(Properties params) { + + Boolean dynamic = Boolean.valueOf( params.getProperty( DynamicParameterizedType.IS_DYNAMIC ) ); + Assert.assertTrue( dynamic ); + + String returnedClass = params.getProperty( DynamicParameterizedType.RETURNED_CLASS ); + Assert.assertEquals( String.class.getName(), returnedClass ); + + Boolean primaryKey = Boolean.valueOf( params.getProperty( DynamicParameterizedType.IS_PRIMARY_KEY ) ); + Assert.assertFalse( primaryKey ); + + String accessType = params.getProperty( DynamicParameterizedType.ACCESS_TYPE ); + Assert.assertEquals( "field", accessType ); + + String entity = params.getProperty( DynamicParameterizedType.ENTITY ); + String propertyName = params.getProperty( DynamicParameterizedType.PROPERTY ); + XProperty xproperty = (XProperty) params.get( DynamicParameterizedType.XPROPERTY ); + Assert.assertEquals( propertyName, xproperty.getName() ); + Assert.assertEquals( entity, xproperty.getDeclaringClass().getName() ); + Assert.assertEquals( String.class.getName(), xproperty.getType().getName() ); + + String tableName = propertyName.toUpperCase().split( "_" )[0]; + String columnName = propertyName.toUpperCase().split( "_" )[1]; + ParameterType parameterType = (ParameterType) params.get( DynamicParameterizedType.PARAMETER_TYPE ); + Assert.assertEquals( 1, parameterType.getColumns().length ); + Assert.assertEquals( columnName, parameterType.getColumns()[0] ); + Assert.assertEquals( String.class, parameterType.getReturnedClass() ); + Assert.assertEquals( tableName, parameterType.getTable() ); + + String value = tableName + "." + columnName; + if ( params.containsKey( "suffix" ) ) { + value += "." + params.getProperty( "suffix" ).toUpperCase(); + } + + return value; + } + + @Override + public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException { + st.setString( index, this.value ); + } + + @Override + public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException { + return rs.getString( names[0] ); + } + + @Override + public int[] sqlTypes() { + return new int[] { StringType.INSTANCE.sqlType() }; + } + + @Override + public Class returnedClass() { + return String.class; + } + + @Override + public boolean equals(Object x, Object y) { + return ( x == null && y == null ) || ( x != null && y != null && x.equals( y ) ); + } + + @Override + public int hashCode(Object x) { + return x.hashCode(); + } + + @Override + public Object deepCopy(Object value) { + return value; + } + + @Override + public boolean isMutable() { + return false; + } + + @Override + public Serializable disassemble(Object value) { + return (Integer) value; + } + + @Override + public Object assemble(Serializable cached, Object owner) { + return cached; + } + + @Override + public Object replace(Object original, Object target, Object owner) { + return original; + } +}