[hibernate-commits] Hibernate SVN: r15911 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/engine and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Feb 6 07:20:43 EST 2009


Author: hardy.ferentschik
Date: 2009-02-06 07:20:43 -0500 (Fri, 06 Feb 2009)
New Revision: 15911

Added:
   validator/trunk/hibernate-validator/src/test/resources/ValidationMessages_es.properties
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
   validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties
Log:
BVAL-69 made message interpolation work with locales

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java	2009-02-06 10:38:22 UTC (rev 15910)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java	2009-02-06 12:20:43 UTC (rev 15911)
@@ -17,6 +17,7 @@
 */
 package org.hibernate.validation.engine;
 
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
@@ -45,48 +46,64 @@
 	 * Regular expression used to do message interpolation.
 	 */
 	private static final Pattern messagePattern = Pattern.compile( "\\{([\\w\\.]+)\\}" );
-	private ResourceBundle defaultResourceBundle;
-	private ResourceBundle userResourceBundle;
 
+	/**
+	 * The default locale for the current user.
+	 */
+	private final Locale defaultLocale;
+
+	private final Map<Locale, ResourceBundle> userBundlesMap = new HashMap<Locale, ResourceBundle>();
+
+	private final Map<Locale, ResourceBundle> defaultBundlesMap = new HashMap<Locale, ResourceBundle>();
+
 	public ResourceBundleMessageInterpolator() {
-		userResourceBundle = getFileBasedResourceBundle();
-		defaultResourceBundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES );
+		this( null );
 	}
 
 	public ResourceBundleMessageInterpolator(ResourceBundle resourceBundle) {
+
+		defaultLocale = Locale.getDefault();
+
 		if ( resourceBundle == null ) {
-			userResourceBundle = getFileBasedResourceBundle();
+			ResourceBundle bundle = getFileBasedResourceBundle( defaultLocale );
+			userBundlesMap.put( defaultLocale, bundle );
+
 		}
 		else {
-			this.userResourceBundle = resourceBundle;
+			userBundlesMap.put( defaultLocale, resourceBundle );
 		}
-		defaultResourceBundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES );
+
+		defaultBundlesMap.put( defaultLocale, ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES, defaultLocale ) );
 	}
 
 	public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value) {
 		// probably no need for caching, but it could be done by parameters since the map
 		// is immutable and uniquely built per Validation definition, the comparaison has to be based on == and not equals though
-		return replace( message, constraintDescriptor.getParameters() );
+		return replace( message, constraintDescriptor.getParameters(), defaultLocale );
 	}
 
 	public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value, Locale locale) {
-		throw new UnsupportedOperationException( "Interpolation for Locale. Has to be done." );
+		return replace( message, constraintDescriptor.getParameters(), locale );
 	}
 
 	/**
 	 * Search current thread classloader for the resource bundle. If not found, search validator (this) classloader.
 	 *
+	 * @param locale The locale of the bundle to load.
+	 *
 	 * @return the resource bundle or <code>null</code> if none is found.
 	 */
-	private ResourceBundle getFileBasedResourceBundle() {
+	private ResourceBundle getFileBasedResourceBundle(Locale locale) {
 		ResourceBundle rb = null;
 		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 		if ( classLoader != null ) {
-			rb = loadBundle( classLoader, USER_VALIDATION_MESSAGES + " not found by thread local classloader" );
+			rb = loadBundle( classLoader, locale, USER_VALIDATION_MESSAGES + " not found by thread local classloader" );
 		}
 		if ( rb == null ) {
 			rb = loadBundle(
-					this.getClass().getClassLoader(), USER_VALIDATION_MESSAGES + " not found by validator classloader"
+					this.getClass().getClassLoader(),
+					locale,
+					USER_VALIDATION_MESSAGES + " not found by validator classloader"
 			);
 		}
 		if ( log.isDebugEnabled() ) {
@@ -100,10 +117,10 @@
 		return rb;
 	}
 
-	private ResourceBundle loadBundle(ClassLoader classLoader, String message) {
+	private ResourceBundle loadBundle(ClassLoader classLoader, Locale locale, String message) {
 		ResourceBundle rb = null;
 		try {
-			rb = ResourceBundle.getBundle( USER_VALIDATION_MESSAGES, Locale.getDefault(), classLoader );
+			rb = ResourceBundle.getBundle( USER_VALIDATION_MESSAGES, locale, classLoader );
 		}
 		catch ( MissingResourceException e ) {
 			log.trace( message );
@@ -111,22 +128,25 @@
 		return rb;
 	}
 
-	private String replace(String message, Map<String, Object> parameters) {
+	private String replace(String message, Map<String, Object> parameters, Locale locale) {
 		Matcher matcher = messagePattern.matcher( message );
 		StringBuffer sb = new StringBuffer();
 		while ( matcher.find() ) {
-			matcher.appendReplacement( sb, resolveParameter( matcher.group( 1 ), parameters ) );
+			matcher.appendReplacement( sb, resolveParameter( matcher.group( 1 ), parameters, locale ) );
 		}
 		matcher.appendTail( sb );
 		return sb.toString();
 	}
 
-	private String resolveParameter(String token, Map<String, Object> parameters) {
+	private String resolveParameter(String token, Map<String, Object> parameters, Locale locale) {
 		Object variable = parameters.get( token );
 		if ( variable != null ) {
 			return variable.toString();
 		}
 
+		ResourceBundle userResourceBundle = findUserResourceBundle( locale );
+		ResourceBundle defaultResourceBundle = findDefaultResourceBundle( locale );
+
 		StringBuffer buffer = new StringBuffer();
 		String string = null;
 		try {
@@ -146,8 +166,28 @@
 		}
 		if ( string != null ) {
 			// call resolve recusively!
-			buffer.append( replace( string, parameters ) );
+			buffer.append( replace( string, parameters, locale ) );
 		}
 		return buffer.toString();
 	}
+
+	private ResourceBundle findDefaultResourceBundle(Locale locale) {
+		if ( defaultBundlesMap.containsKey( locale ) ) {
+			return defaultBundlesMap.get( locale );
+		}
+
+		ResourceBundle bundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES, locale );
+		defaultBundlesMap.put( locale, bundle );
+		return bundle;
+	}
+
+	private ResourceBundle findUserResourceBundle(Locale locale) {
+		if ( userBundlesMap.containsKey( locale ) ) {
+			return userBundlesMap.get( locale );
+		}
+
+		ResourceBundle bundle = getFileBasedResourceBundle( locale );
+		userBundlesMap.put( locale, bundle );
+		return bundle;
+	}
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java	2009-02-06 10:38:22 UTC (rev 15910)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java	2009-02-06 12:20:43 UTC (rev 15911)
@@ -20,6 +20,7 @@
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.ResourceBundle;
@@ -57,7 +58,7 @@
 
 	@Test
 	public void testSuccessfulInterpolation() {
-		ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl(
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
 				notNull, new Class<?>[] { }, new BuiltinConstraints()
 		);
 
@@ -80,7 +81,7 @@
 
 	@Test
 	public void testUnSuccessfulInterpolation() {
-		ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl(
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
 				notNull, new Class<?>[] { }, new BuiltinConstraints()
 		);
 		String expected = "foo";  // missing {}
@@ -94,7 +95,7 @@
 
 	@Test
 	public void testUnkownTokenInterpolation() {
-		ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl(
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
 				notNull, new Class<?>[] { }, new BuiltinConstraints()
 		);
 		String expected = "{bar}";  // unkown token {}
@@ -104,20 +105,60 @@
 
 	@Test
 	public void testDefaultInterpolation() {
-		ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl(
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
 				notNull, new Class<?>[] { }, new BuiltinConstraints()
 		);
 		String expected = "may not be null";
 		String actual = interpolator.interpolate( notNull.message(), descriptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
 
-		descriptor = new ConstraintDescriptorImpl( size, new Class<?>[] { }, new BuiltinConstraints() );
+		ConstraintDescriptorImpl<Size> sizeDescriptor = new ConstraintDescriptorImpl<Size>(
+				size, new Class<?>[] { }, new BuiltinConstraints()
+		);
 		expected = "size must be between -2147483648 and 2147483647";  // unkown token {}
-		actual = interpolator.interpolate( size.message(), descriptor, null );
+		actual = interpolator.interpolate( size.message(), sizeDescriptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
 	}
 
+	@Test
+	public void testMessageInterpolationWithLocale() {
+		interpolator = new ResourceBundleMessageInterpolator();
 
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
+				notNull, new Class<?>[] { }, new BuiltinConstraints()
+		);
+
+		String expected = "kann nicht null sein";
+		String actual = interpolator.interpolate( notNull.message(), descriptor, null, Locale.GERMAN );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
+	@Test
+	public void testFallbackToDefaultLocale() {
+		interpolator = new ResourceBundleMessageInterpolator();
+
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
+				notNull, new Class<?>[] { }, new BuiltinConstraints()
+		);
+
+		String expected = "may not be null";
+		String actual = interpolator.interpolate( notNull.message(), descriptor, null, Locale.JAPAN );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
+	@Test
+	public void testUserResourceBundle() {
+		interpolator = new ResourceBundleMessageInterpolator();
+
+		ConstraintDescriptorImpl<NotNull> descriptor = new ConstraintDescriptorImpl<NotNull>(
+				notNull, new Class<?>[] { }, new BuiltinConstraints()
+		);
+
+		String expected = "no puede ser null";
+		String actual = interpolator.interpolate( notNull.message(), descriptor, null, new Locale( "es", "ES" ) );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
 	class TestResources extends ResourceBundle implements Enumeration<String> {
 		private Map<String, String> testResources;
 		Iterator<String> iter;

Added: validator/trunk/hibernate-validator/src/test/resources/ValidationMessages_es.properties
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/ValidationMessages_es.properties	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/resources/ValidationMessages_es.properties	2009-02-06 12:20:43 UTC (rev 15911)
@@ -0,0 +1 @@
+validator.notNull=no puede ser null
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties	2009-02-06 10:38:22 UTC (rev 15910)
+++ validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties	2009-02-06 12:20:43 UTC (rev 15911)
@@ -1,11 +1,2 @@
 # $Id: ValidationMessages.properties 15846 2009-02-02 11:56:15Z hardy.ferentschik $
-validator.notNull=may not be null
-validator.size=size must be between {min} and {max}
-validator.length=length must be between {min} and {max}
-validator.notEmpty=may not be empty
-validator.pattern=must match "{regex}"
-validator.min=must be greater than {value}
-validator.max=must be less than {value}
-validator.null=must be null
-validator.past=must be in the past
-validator.future=must be in the future
+validator.notNull=kann nicht null sein




More information about the hibernate-commits mailing list