HHH-17466 Implement passthrough wrapping/unwrapping in LocaleJavaType

This commit is contained in:
Yoann Rodière 2023-11-27 10:41:40 +01:00
parent 87d24f157e
commit 6b5eb3f319
4 changed files with 111 additions and 4 deletions

View File

@ -91,6 +91,9 @@ public class LocaleJavaType extends AbstractClassJavaType<Locale> {
if ( value == null ) { if ( value == null ) {
return null; return null;
} }
if ( Locale.class.isAssignableFrom( type ) ) {
return (X) value;
}
if ( String.class.isAssignableFrom( type ) ) { if ( String.class.isAssignableFrom( type ) ) {
return (X) value.toString(); return (X) value.toString();
} }
@ -101,6 +104,9 @@ public class LocaleJavaType extends AbstractClassJavaType<Locale> {
if ( value == null ) { if ( value == null ) {
return null; return null;
} }
if ( value instanceof Locale ) {
return (Locale) value;
}
if (value instanceof CharSequence) { if (value instanceof CharSequence) {
return fromString( (CharSequence) value ); return fromString( (CharSequence) value );
} }

View File

@ -8,15 +8,24 @@ package org.hibernate.orm.test.mapping.type.java;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Blob; import java.sql.Blob;
import java.sql.Clob; import java.sql.Clob;
import java.util.TimeZone;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.testing.orm.junit.JiraKey;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
@ -37,6 +46,40 @@ public abstract class AbstractDescriptorTest<T> extends BaseUnitTestCase {
private final JavaType<T> typeDescriptor; private final JavaType<T> typeDescriptor;
protected final WrapperOptions wrapperOptions = new WrapperOptions() {
@Override
public SharedSessionContractImplementor getSession() {
return null;
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return null;
}
public boolean useStreamForLobBinding() {
return false;
}
@Override
public int getPreferredSqlTypeCodeForBoolean() {
return 0;
}
public LobCreator getLobCreator() {
return NonContextualLobCreator.INSTANCE;
}
public JdbcType remapSqlTypeDescriptor(JdbcType sqlTypeDescriptor) {
return sqlTypeDescriptor;
}
@Override
public TimeZone getJdbcTimeZone() {
return null;
}
};
public AbstractDescriptorTest(JavaType<T> typeDescriptor) { public AbstractDescriptorTest(JavaType<T> typeDescriptor) {
this.typeDescriptor = typeDescriptor; this.typeDescriptor = typeDescriptor;
} }
@ -56,9 +99,15 @@ public abstract class AbstractDescriptorTest<T> extends BaseUnitTestCase {
protected abstract boolean shouldBeMutable(); protected abstract boolean shouldBeMutable();
protected boolean isIdentityDifferentFromEquality() {
return true;
}
@Test @Test
public void testEquality() { public void testEquality() {
assertFalse( testData.originalValue == testData.copyOfOriginalValue ); if ( isIdentityDifferentFromEquality() ) {
assertFalse( testData.originalValue == testData.copyOfOriginalValue );
}
assertTrue( typeDescriptor.areEqual( testData.originalValue, testData.originalValue ) ); assertTrue( typeDescriptor.areEqual( testData.originalValue, testData.originalValue ) );
assertTrue( typeDescriptor.areEqual( testData.originalValue, testData.copyOfOriginalValue ) ); assertTrue( typeDescriptor.areEqual( testData.originalValue, testData.copyOfOriginalValue ) );
assertFalse( typeDescriptor.areEqual( testData.originalValue, testData.differentValue ) ); assertFalse( typeDescriptor.areEqual( testData.originalValue, testData.differentValue ) );
@ -72,6 +121,23 @@ public abstract class AbstractDescriptorTest<T> extends BaseUnitTestCase {
assertTrue( typeDescriptor.areEqual( testData.originalValue, consumed ) ); assertTrue( typeDescriptor.areEqual( testData.originalValue, consumed ) );
} }
/**
* Check that wrapping/unwrapping a value that already has the expected type
* does not fail and returns a value that is considered equal.
*/
@Test
@JiraKey("HHH-17466")
public void testPassThrough() {
assertTrue( typeDescriptor.areEqual(
testData.originalValue,
typeDescriptor.wrap( testData.originalValue, wrapperOptions )
) );
assertTrue( typeDescriptor.areEqual(
testData.originalValue,
typeDescriptor.unwrap( testData.originalValue, typeDescriptor.getJavaTypeClass(), wrapperOptions )
) );
}
@Test @Test
public void testMutabilityPlan() { public void testMutabilityPlan() {
assertTrue( shouldBeMutable() == typeDescriptor.getMutabilityPlan().isMutable() ); assertTrue( shouldBeMutable() == typeDescriptor.getMutabilityPlan().isMutable() );

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.orm.test.mapping.type.java; package org.hibernate.orm.test.mapping.type.java;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -23,6 +24,8 @@ import org.hibernate.type.descriptor.java.DataHelper;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.junit.Test; import org.junit.Test;
import org.assertj.core.api.Assertions;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -55,6 +58,16 @@ public class BlobDescriptorTest extends AbstractDescriptorTest<Blob> {
assertFalse( BlobJavaType.INSTANCE.areEqual( original, different ) ); assertFalse( BlobJavaType.INSTANCE.areEqual( original, different ) );
} }
@Override
public void testPassThrough() {
// blobs of the same internal value are not really comparable
// we'll just check that operations don't fail, not that the output is equal to the input
assertThatCode( () -> BlobJavaType.INSTANCE.wrap( original, wrapperOptions ) )
.doesNotThrowAnyException();
assertThatCode( () -> BlobJavaType.INSTANCE.unwrap( original, Blob.class, wrapperOptions ) )
.doesNotThrowAnyException();
}
@Test @Test
@Override @Override
public void testExternalization() { public void testExternalization() {

View File

@ -11,8 +11,8 @@ import static org.junit.Assert.assertEquals;
import java.util.Locale; import java.util.Locale;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.type.descriptor.java.LocaleJavaType; import org.hibernate.type.descriptor.java.LocaleJavaType;
import org.junit.Test; import org.junit.Test;
/** /**
@ -21,7 +21,29 @@ import org.junit.Test;
* @author Christian Beikov * @author Christian Beikov
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class LocaleJavaTypeDescriptorTest extends BaseUnitTestCase { public class LocaleJavaTypeDescriptorTest extends AbstractDescriptorTest<Locale> {
final Locale original = toLocale( "de", "DE", null );
final Locale copy = toLocale( "de", "DE", null );
final Locale different = toLocale( "de", null, null );
public LocaleJavaTypeDescriptorTest() {
super( LocaleJavaType.INSTANCE );
}
@Override
protected Data<Locale> getTestData() {
return new Data<>( original, copy, different );
}
@Override
protected boolean shouldBeMutable() {
return false;
}
@Override
protected boolean isIdentityDifferentFromEquality() {
return false;
}
@Test @Test
public void testConversionFromString() { public void testConversionFromString() {
@ -36,7 +58,7 @@ public class LocaleJavaTypeDescriptorTest extends BaseUnitTestCase {
assertEquals( Locale.ROOT, LocaleJavaType.INSTANCE.fromString( "" ) ); assertEquals( Locale.ROOT, LocaleJavaType.INSTANCE.fromString( "" ) );
} }
public Locale toLocale(String lang, String region, String variant) { private static Locale toLocale(String lang, String region, String variant) {
final Locale.Builder builder = new Locale.Builder(); final Locale.Builder builder = new Locale.Builder();
if ( StringHelper.isNotEmpty( lang ) ) { if ( StringHelper.isNotEmpty( lang ) ) {
builder.setLanguage( lang ); builder.setLanguage( lang );