Skip to content

Commit c4dfc46

Browse files
committed
HV-1748 Generalize the ability to define the supported locales
While not used to initialize the resource bundles, it can be used for advanced locale resolution via Locale.LanguageRange.
1 parent 2c43b79 commit c4dfc46

11 files changed

+224
-110
lines changed

engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
package org.hibernate.validator;
88

99
import java.time.Duration;
10+
import java.util.Arrays;
11+
import java.util.HashSet;
1012
import java.util.Locale;
1113
import java.util.Set;
1214

@@ -372,6 +374,34 @@ public interface BaseHibernateValidatorConfiguration<S extends BaseHibernateVali
372374
@Incubating
373375
S propertyNodeNameProvider(PropertyNodeNameProvider propertyNodeNameProvider);
374376

377+
/**
378+
* Allows setting the list of the locales supported by this ValidatorFactory.
379+
* <p>
380+
* Can be used for advanced locale resolution and/or to force the initialization of the resource bundles at
381+
* bootstrap.
382+
* <p>
383+
* If not set, defaults to a singleton containing {@link Locale#getDefault()}.
384+
*
385+
* @since 6.1.1
386+
*/
387+
@Incubating
388+
S locales(Set<Locale> locales);
389+
390+
/**
391+
* Allows setting the list of the locales supported by this ValidatorFactory.
392+
* <p>
393+
* Can be used for advanced locale resolution and/or to force the initialization of the resource bundles at
394+
* bootstrap.
395+
* <p>
396+
* If not set, defaults to a singleton containing {@link Locale#getDefault()}.
397+
*
398+
* @since 6.1.1
399+
*/
400+
@Incubating
401+
default S locales(Locale... locales) {
402+
return locales( new HashSet<>( Arrays.asList( locales ) ) );
403+
}
404+
375405
/**
376406
* Allows setting the default locale used to interpolate the constraint violation messages.
377407
* <p>

engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibe
2525
@Incubating
2626
PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set<Class<?>> beanClassesToInitialize);
2727

28+
/**
29+
* @deprecated Planned for removal, use {@link BaseHibernateValidatorConfiguration#locales(Set)} instead.
30+
*/
2831
@Incubating
32+
@Deprecated
2933
PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set<Locale> locales);
3034

3135
@Incubating

engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
4747
import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy;
4848
import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper;
49+
import org.hibernate.validator.internal.util.CollectionHelper;
4950
import org.hibernate.validator.internal.util.Contracts;
5051
import org.hibernate.validator.internal.util.Version;
5152
import org.hibernate.validator.internal.util.logging.Log;
@@ -71,6 +72,7 @@
7172
* @author Gunnar Morling
7273
* @author Kevin Pollet &lt;kevin.pollet@serli.com&gt; (C) 2011 SERLI
7374
* @author Chris Beckey &lt;cbeckey@paypal.com&gt;
75+
* @author Guillaume Smet
7476
*/
7577
public abstract class AbstractConfigurationImpl<T extends BaseHibernateValidatorConfiguration<T>>
7678
implements BaseHibernateValidatorConfiguration<T>, ConfigurationState {
@@ -113,6 +115,7 @@ public abstract class AbstractConfigurationImpl<T extends BaseHibernateValidator
113115
private Duration temporalValidationTolerance;
114116
private Object constraintValidatorPayload;
115117
private GetterPropertySelectionStrategy getterPropertySelectionStrategy;
118+
private Set<Locale> locales = Collections.emptySet();
116119
private Locale defaultLocale = Locale.getDefault();
117120
private LocaleResolver localeResolver;
118121

@@ -338,6 +341,14 @@ public T getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterP
338341
return thisAsT();
339342
}
340343

344+
@Override
345+
public T locales(Set<Locale> locales) {
346+
Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "locales" ) );
347+
348+
this.locales = locales;
349+
return thisAsT();
350+
}
351+
341352
@Override
342353
public T defaultLocale(Locale defaultLocale) {
343354
Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "defaultLocale" ) );
@@ -543,8 +554,9 @@ public ClassLoader getExternalClassLoader() {
543554
@Override
544555
public final MessageInterpolator getDefaultMessageInterpolator() {
545556
if ( defaultMessageInterpolator == null ) {
546-
defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), getAllLocalesToInitialize(),
547-
defaultLocale, ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ) );
557+
defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), getAllSupportedLocales(),
558+
defaultLocale, ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ),
559+
preloadResourceBundles() );
548560
}
549561

550562
return defaultMessageInterpolator;
@@ -564,7 +576,7 @@ public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() {
564576
public final ResourceBundleLocator getDefaultResourceBundleLocator() {
565577
if ( defaultResourceBundleLocator == null ) {
566578
defaultResourceBundleLocator = new PlatformResourceBundleLocator(
567-
ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, getAllLocalesToInitialize() );
579+
ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, preloadResourceBundles(), getAllSupportedLocales() );
568580
}
569581

570582
return defaultResourceBundleLocator;
@@ -714,12 +726,14 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad
714726
if ( externalClassLoader != null ) {
715727
PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator(
716728
ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES,
717-
getAllLocalesToInitialize(),
729+
preloadResourceBundles(),
730+
getAllSupportedLocales(),
718731
externalClassLoader
719732
);
720733
PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator(
721734
ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES,
722-
getAllLocalesToInitialize(),
735+
preloadResourceBundles(),
736+
getAllSupportedLocales(),
723737
externalClassLoader,
724738
true
725739
);
@@ -733,9 +747,10 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad
733747
return new ResourceBundleMessageInterpolator(
734748
userResourceBundleLocator,
735749
contributorResourceBundleLocator,
736-
getAllLocalesToInitialize(),
750+
getAllSupportedLocales(),
737751
defaultLocale,
738-
ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader )
752+
ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ),
753+
preloadResourceBundles()
739754
);
740755
}
741756
finally {
@@ -747,15 +762,22 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad
747762
}
748763
}
749764

750-
protected final Locale getDefaultLocale() {
751-
return defaultLocale;
752-
}
765+
private Set<Locale> getAllSupportedLocales() {
766+
if ( locales.isEmpty() ) {
767+
return Collections.singleton( defaultLocale );
768+
}
769+
if ( locales.contains( defaultLocale ) ) {
770+
return locales;
771+
}
753772

754-
protected Set<Locale> getAllLocalesToInitialize() {
755-
// By default, we return an empty set meaning that we will dynamically initialize the locales.
756-
return Collections.emptySet();
773+
Set<Locale> allLocales = CollectionHelper.newHashSet( locales.size() + 1 );
774+
allLocales.addAll( locales );
775+
allLocales.add( defaultLocale );
776+
return allLocales;
757777
}
758778

779+
protected abstract boolean preloadResourceBundles();
780+
759781
@SuppressWarnings("unchecked")
760782
protected T thisAsT() {
761783
return (T) this;

engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* @author Gunnar Morling
2121
* @author Kevin Pollet &lt;kevin.pollet@serli.com&gt; (C) 2011 SERLI
2222
* @author Chris Beckey &lt;cbeckey@paypal.com&gt;
23+
* @author Guillaume Smet
2324
*/
2425
public class ConfigurationImpl extends AbstractConfigurationImpl<HibernateValidatorConfiguration> implements HibernateValidatorConfiguration, ConfigurationState {
2526

@@ -30,4 +31,9 @@ public ConfigurationImpl(BootstrapState state) {
3031
public ConfigurationImpl(ValidationProvider<?> provider) {
3132
super( provider );
3233
}
34+
35+
@Override
36+
protected boolean preloadResourceBundles() {
37+
return false;
38+
}
3339
}

engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES;
1010

11-
import java.util.Collections;
1211
import java.util.Locale;
1312
import java.util.Set;
1413

@@ -31,13 +30,6 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl<
3130

3231
private BeanMetaDataClassNormalizer beanMetaDataClassNormalizer;
3332

34-
/**
35-
* Locales to initialize eagerly.
36-
* <p>
37-
* We will always include the default locale in the final list.
38-
*/
39-
private Set<Locale> localesToInitialize = Collections.emptySet();
40-
4133
public PredefinedScopeConfigurationImpl(BootstrapState state) {
4234
super( state );
4335
}
@@ -59,7 +51,7 @@ public Set<Class<?>> getBeanClassesToInitialize() {
5951
@Override
6052
public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set<Locale> localesToInitialize) {
6153
Contracts.assertNotNull( localesToInitialize, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) );
62-
this.localesToInitialize = localesToInitialize;
54+
locales( localesToInitialize );
6355
return thisAsT();
6456
}
6557

@@ -74,14 +66,7 @@ public BeanMetaDataClassNormalizer getBeanMetaDataClassNormalizer() {
7466
}
7567

7668
@Override
77-
protected Set<Locale> getAllLocalesToInitialize() {
78-
if ( localesToInitialize.isEmpty() ) {
79-
return Collections.singleton( getDefaultLocale() );
80-
}
81-
82-
Set<Locale> allLocales = CollectionHelper.newHashSet( localesToInitialize.size() + 1 );
83-
allLocales.addAll( localesToInitialize );
84-
allLocales.add( getDefaultLocale() );
85-
return Collections.unmodifiableSet( allLocales );
69+
protected boolean preloadResourceBundles() {
70+
return true;
8671
}
8772
}

0 commit comments

Comments
 (0)