Skip to content

Commit d224991

Browse files
beikovbrmeyer
authored andcommitted
HHH-8491 Improved implementation for locale string parsing
1 parent 0695299 commit d224991

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleTypeDescriptor.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
/**
3333
* Descriptor for {@link Locale} handling.
34-
*
34+
*
3535
* @author Steve Ebersole
3636
*/
3737
public class LocaleTypeDescriptor extends AbstractTypeDescriptor<Locale> {
@@ -59,22 +59,52 @@ public String toString(Locale value) {
5959
}
6060

6161
public Locale fromString(String string) {
62-
// TODO : Ultimately switch to Locale.Builder for this. However, Locale.Builder is Java 7
63-
64-
final StringTokenizer tokens = new StringTokenizer( string, "_" );
65-
final String language = tokens.hasMoreTokens() && string.charAt(0) != '_' ? tokens.nextToken() : "";
66-
final String country = tokens.hasMoreTokens() && string.charAt(string.indexOf(language) + language.length() + 1) != '_' ? tokens.nextToken() : "";
67-
68-
// Need to account for allowable '_' within the variant. The underscore within the variant delimits "subtags".
69-
// Technically the reference spec (IETF BCP 47) also allows dash ("-") as a variant subtag delimiter.
70-
// Note that this code block supports both approaches...
71-
String variant = "";
72-
String sep = "";
73-
while ( tokens.hasMoreTokens() ) {
74-
variant += sep + tokens.nextToken();
75-
sep = "_";
62+
// TODO : Ultimately switch to Locale.Builder for this. However, Locale.Builder is Java 7
63+
64+
if ( string == null || string.isEmpty() ) {
65+
return null;
66+
}
67+
68+
int found = 0, position = 0;
69+
char[] chars = string.toCharArray();
70+
71+
for ( int i = 0; i < chars.length; i++ ) {
72+
// We just look for separators
73+
if ( chars[i] == '_' ) {
74+
switch ( found ) {
75+
case 0:
76+
// On the first separator we know that we have at least a language
77+
string = new String( chars, position, i - position );
78+
position = i + 1;
79+
break;
80+
case 1:
81+
// On the second separator we have to check whether there are more chars available for variant
82+
if ( chars.length > i + 1 ) {
83+
// There is a variant so add it to the constructor
84+
return new Locale( string, new String( chars, position, i - position ), new String( chars,
85+
i + 1, chars.length - i - 1 ) );
86+
}
87+
else {
88+
// No variant given, we just have language and country
89+
return new Locale( string, new String( chars, position, i - position ), "" );
90+
}
91+
}
92+
93+
found++;
94+
}
7695
}
77-
return new Locale( language, country, variant );
96+
97+
switch ( found ) {
98+
case 0:
99+
// No separator found, there is only a language
100+
return new Locale( string );
101+
case 1:
102+
// Only one separator found, there is a language and a country
103+
return new Locale( string, new String( chars, position, chars.length - position ) );
104+
}
105+
106+
// Should never happen
107+
return null;
78108
}
79109

80110
@SuppressWarnings({ "unchecked" })

0 commit comments

Comments
 (0)