diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleTypeDescriptor.java index e12f28312f..72bfe2ddc7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleTypeDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleTypeDescriptor.java @@ -59,10 +59,15 @@ public class LocaleTypeDescriptor extends AbstractTypeDescriptor { } public Locale fromString(String string) { - StringTokenizer tokens = new StringTokenizer( string, "_" ); - String language = tokens.hasMoreTokens() && string.charAt(0) != '_' ? tokens.nextToken() : ""; - String country = tokens.hasMoreTokens() && string.charAt(string.indexOf(language) + language.length() + 1) != '_' ? tokens.nextToken() : ""; - // Need to account for allowable '_' within the variant + // TODO : Ultimately switch to Locale.Builder for this. However, Locale.Builder is Java 7 + + final StringTokenizer tokens = new StringTokenizer( string, "_" ); + final String language = tokens.hasMoreTokens() && string.charAt(0) != '_' ? tokens.nextToken() : ""; + final String country = tokens.hasMoreTokens() && string.charAt(string.indexOf(language) + language.length() + 1) != '_' ? tokens.nextToken() : ""; + + // Need to account for allowable '_' within the variant. The underscore within the variant delimits "subtags". + // Technically the reference spec (IETF BCP 47) also allows dash ("-") as a variant subtag delimiter. + // Note that this code block supports both approaches... String variant = ""; String sep = ""; while ( tokens.hasMoreTokens() ) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/type/descriptor/java/LocaleTypeDescriptorTest.java b/hibernate-core/src/test/java/org/hibernate/test/type/descriptor/java/LocaleTypeDescriptorTest.java index 8584106acc..0c1da5b205 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/type/descriptor/java/LocaleTypeDescriptorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/type/descriptor/java/LocaleTypeDescriptorTest.java @@ -42,15 +42,16 @@ import static org.junit.Assert.assertEquals; * @author Steve Ebersole */ public class LocaleTypeDescriptorTest extends BaseUnitTestCase { + @Test public void testConversionFromString() { assertEquals( toLocale( "de", null, null ), LocaleTypeDescriptor.INSTANCE.fromString( "de" ) ); assertEquals( toLocale( "de", "DE", null ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE" ) ); assertEquals( toLocale( null, "DE", null ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE" ) ); - assertEquals( toLocale( null, null, "ch" ), LocaleTypeDescriptor.INSTANCE.fromString( "__ch" ) ); - assertEquals( toLocale( null, "DE", "ch" ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE_ch" ) ); - assertEquals( toLocale( "de", null, "ch" ), LocaleTypeDescriptor.INSTANCE.fromString( "de__ch" ) ); - assertEquals( toLocale( "de", "DE", "ch" ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE_ch" ) ); + assertEquals( toLocale( null, null, "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "__ch123" ) ); + assertEquals( toLocale( null, "DE", "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "_DE_ch123" ) ); + assertEquals( toLocale( "de", null, "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "de__ch123" ) ); + assertEquals( toLocale( "de", "DE", "ch123" ), LocaleTypeDescriptor.INSTANCE.fromString( "de_DE_ch123" ) ); } public Locale toLocale(String lang, String region, String variant) {