[hibernate-commits] Hibernate SVN: r17417 - validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Aug 25 12:07:55 EDT 2009


Author: hardy.ferentschik
Date: 2009-08-25 12:07:55 -0400 (Tue, 25 Aug 2009)
New Revision: 17417

Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java
Log:
HV-189

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-08-25 15:25:56 UTC (rev 17416)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java	2009-08-25 16:07:55 UTC (rev 17417)
@@ -17,20 +17,21 @@
 */
 package org.hibernate.validation.engine;
 
+import java.security.AccessController;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.security.AccessController;
 import javax.validation.MessageInterpolator;
 
 import org.slf4j.Logger;
 
+import org.hibernate.validation.util.GetClassLoader;
 import org.hibernate.validation.util.LoggerFactory;
-import org.hibernate.validation.util.GetClassLoader;
 
 /**
  * Resource bundle backed message interpolator.
@@ -59,10 +60,15 @@
 	private final Map<Locale, ResourceBundle> userBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>();
 
 	/**
-	 * Builtin resource bundles hashed against there locale.
+	 * Built-in resource bundles hashed against there locale.
 	 */
 	private final Map<Locale, ResourceBundle> defaultBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>();
 
+	/**
+	 * Step 1-3 of message interpolation can be cached. We do this in this map.
+	 */
+	private final Map<LocalisedMessage, String> resolvedMessages = new WeakHashMap<LocalisedMessage, String>();
+
 	public ResourceBundleMessageInterpolator() {
 		this( null );
 	}
@@ -87,7 +93,7 @@
 
 	public String interpolate(String message, Context context) {
 		// 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
+		// is immutable and uniquely built per Validation definition, the comparison has to be based on == and not equals though
 		return interpolateMessage( message, context.getConstraintDescriptor().getAttributes(), defaultLocale );
 	}
 
@@ -96,11 +102,11 @@
 	}
 
 	/**
-	 * Runs the message interpolation according to alogrithm specified in JSR 303.
+	 * Runs the message interpolation according to algorithm specified in JSR 303.
 	 * <br/>
 	 * Note:
 	 * <br/>
-	 * Lookups in user bundles is recursive whereas lookups in default bundle are not!
+	 * Look-ups in user bundles is recursive whereas look-ups in default bundle are not!
 	 *
 	 * @param message the message to interpolate
 	 * @param annotationParameters the parameters of the annotation for which to interpolate this message
@@ -109,30 +115,36 @@
 	 * @return the interpolated message.
 	 */
 	private String interpolateMessage(String message, Map<String, Object> annotationParameters, Locale locale) {
-		ResourceBundle userResourceBundle = findUserResourceBundle( locale );
-		ResourceBundle defaultResourceBundle = findDefaultResourceBundle( locale );
+		LocalisedMessage localisedMessage = new LocalisedMessage( message, locale );
+		String resolvedMessage = resolvedMessages.get( localisedMessage );
 
-		String userBundleResolvedMessage;
-		String resolvedMessage = message;
-		boolean evaluatedDefaultBundleOnce = false;
-		do {
-			// search the user bundle recursive (step1)
-			userBundleResolvedMessage = replaceVariables(
-					resolvedMessage, userResourceBundle, locale, true
-			);
+		// if the message is not already in the cache we have to run step 1-3 of the message resolution 
+		if ( resolvedMessage == null ) {
+			ResourceBundle userResourceBundle = findUserResourceBundle( locale );
+			ResourceBundle defaultResourceBundle = findDefaultResourceBundle( locale );
 
-			// exit condition - we have at least tried to vaidate against the default bundle and there was no
-			// further replacements
-			if ( evaluatedDefaultBundleOnce
-					&& !hasReplacementTakenPlace( userBundleResolvedMessage, resolvedMessage ) ) {
-				break;
-			}
+			String userBundleResolvedMessage;
+			resolvedMessage = message;
+			boolean evaluatedDefaultBundleOnce = false;
+			do {
+				// search the user bundle recursive (step1)
+				userBundleResolvedMessage = replaceVariables(
+						resolvedMessage, userResourceBundle, locale, true
+				);
 
-			// search the default bundle non recursive (step2)
-			resolvedMessage = replaceVariables( userBundleResolvedMessage, defaultResourceBundle, locale, false );
+				// exit condition - we have at least tried to validate against the default bundle and there was no
+				// further replacements
+				if ( evaluatedDefaultBundleOnce
+						&& !hasReplacementTakenPlace( userBundleResolvedMessage, resolvedMessage ) ) {
+					break;
+				}
 
-			evaluatedDefaultBundleOnce = true;
-		} while ( true );
+				// search the default bundle non recursive (step2)
+				resolvedMessage = replaceVariables( userBundleResolvedMessage, defaultResourceBundle, locale, false );
+				evaluatedDefaultBundleOnce = true;
+				resolvedMessages.put( localisedMessage, resolvedMessage );
+			} while ( true );
+		}
 
 		// resolve annotation attributes (step 4)
 		resolvedMessage = replaceAnnotationAttributes( resolvedMessage, annotationParameters );
@@ -165,7 +177,7 @@
 			rb = loadBundle( classLoader, locale, USER_VALIDATION_MESSAGES + " not found by thread local classloader" );
 		}
 		if ( rb == null ) {
-			action = GetClassLoader.fromClass(ResourceBundleMessageInterpolator.class);
+			action = GetClassLoader.fromClass( ResourceBundleMessageInterpolator.class );
 			classLoader = isSecured ? AccessController.doPrivileged( action ) : action.run();
 			rb = loadBundle(
 					classLoader,
@@ -286,4 +298,50 @@
 		escapedString = escapedString.replace( "$", "\\$" );
 		return escapedString;
 	}
+
+	class LocalisedMessage {
+		private final String message;
+		private final Locale locale;
+
+		LocalisedMessage(String message, Locale locale) {
+			this.message = message;
+			this.locale = locale;
+		}
+
+		public String getMessage() {
+			return message;
+		}
+
+		public Locale getLocale() {
+			return locale;
+		}
+
+		@Override
+		public boolean equals(Object o) {
+			if ( this == o ) {
+				return true;
+			}
+			if ( o == null || getClass() != o.getClass() ) {
+				return false;
+			}
+
+			LocalisedMessage that = ( LocalisedMessage ) o;
+
+			if ( locale != null ? !locale.equals( that.locale ) : that.locale != null ) {
+				return false;
+			}
+			if ( message != null ? !message.equals( that.message ) : that.message != null ) {
+				return false;
+			}
+
+			return true;
+		}
+
+		@Override
+		public int hashCode() {
+			int result = message != null ? message.hashCode() : 0;
+			result = 31 * result + ( locale != null ? locale.hashCode() : 0 );
+			return result;
+		}
+	}
 }



More information about the hibernate-commits mailing list