Repository: wicket Updated Branches: refs/heads/wicket-7.x f71a2d33c -> 2b12b8971
WICKET-6193 Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/2b12b897 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/2b12b897 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/2b12b897 Branch: refs/heads/wicket-7.x Commit: 2b12b897120c66272dabaa3f9093cb05ce981b90 Parents: f71a2d3 Author: Tobias Soloschenko <[email protected]> Authored: Sat Jul 2 00:23:34 2016 +0200 Committer: Tobias Soloschenko <[email protected]> Committed: Sat Jul 2 00:26:35 2016 +0200 ---------------------------------------------------------------------- .../loader/NestedStringResourceLoader.java | 181 +++++++++++++++++++ ...ingResourceLoaderTest$MyValidator.properties | 4 + ...ResourceLoaderTest$MyValidator_nl.properties | 4 + .../loader/NestedStringResourceLoaderTest.java | 33 ++++ .../src/docs/guide/i18n/i18n_3.gdoc | 1 + 5 files changed, 223 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/2b12b897/wicket-core/src/main/java/org/apache/wicket/resource/loader/NestedStringResourceLoader.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/resource/loader/NestedStringResourceLoader.java b/wicket-core/src/main/java/org/apache/wicket/resource/loader/NestedStringResourceLoader.java new file mode 100644 index 0000000..dab0b92 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/resource/loader/NestedStringResourceLoader.java @@ -0,0 +1,181 @@ +package org.apache.wicket.resource.loader; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.wicket.Application; +import org.apache.wicket.Component; +import org.apache.wicket.resource.loader.IStringResourceLoader; +import org.apache.wicket.settings.ResourceSettings; +import org.apache.wicket.util.string.AppendingStringBuffer; + +/** + * Creates a nested string resource loader which resolves nested keys.<br> + * <br> + * Example: + * + * <pre> + * <code> + * List<IStringResourceLoader> loaders = getResourceSettings().getStringResourceLoaders(); + * // Add more loaders here + * NestedStringResourceLoader element = new NestedStringResourceLoader(loaders,Pattern.compile("#\\(([^ ]*?)\\)")); + * loaders.clear(); + * loaders.add(element); + * </code> + * </pre> + * + * @author Sven Meier + * @author Tobias Soloschenko + * + */ +public class NestedStringResourceLoader implements IStringResourceLoader +{ + private Pattern pattern; + + private List<IStringResourceLoader> loaders; + + private ResourceSettings resourceSettings; + + /** + * Creates a nested string resource loader + * + * @param loaders + * the loaders to be added in a chain + * @param pattern + * the pattern for nested keys. Example for <b>#(key)</b> is the pattern: + * <b>Pattern.compile("#\\(([^ ]*?)\\)");</b> + */ + public NestedStringResourceLoader(List<IStringResourceLoader> loaders, Pattern pattern) + { + this.loaders = new ArrayList<>(loaders); + this.pattern = pattern; + this.resourceSettings = Application.get().getResourceSettings(); + } + + @Override + public String loadStringResource(Component component, String key, Locale locale, String style, + String variation) + { + return loadNestedStringResource(component, key, locale, style, variation); + } + + @Override + public String loadStringResource(Class<?> clazz, String key, Locale locale, String style, + String variation) + { + return loadNestedStringResource(clazz, key, locale, style, variation); + } + + /** + * loads nested string resources + * + * @param scope + * the scope to find the key + * @param key + * the actual key + * @param locale + * the locale + * @param style + * the style + * @param variation + * the variation + * @return the load string + */ + private String loadNestedStringResource(Object scope, String key, Locale locale, String style, + String variation) + { + Class<?> clazz = null; + Component component = null; + if (scope instanceof Component) + { + component = (Component)scope; + } + else + { + clazz = (Class<?>)scope; + } + + Iterator<IStringResourceLoader> iter = loaders.iterator(); + String value = null; + while (iter.hasNext() && (value == null)) + { + IStringResourceLoader loader = iter.next(); + value = component != null + ? loader.loadStringResource(component, key, locale, style, variation) + : loader.loadStringResource(clazz, key, locale, style, variation); + } + + if (value == null) + { + return handleMissingKey(key, locale, style, component, value); + } + + StringBuffer output = new StringBuffer(); + Matcher matcher = pattern.matcher(value); + // Search for other nested keys to replace + while (matcher.find()) + { + String nestedKey = matcher.group(1); + String replacedPlaceHolder = component != null + ? loadNestedStringResource(component, nestedKey, locale, style, variation) + : loadNestedStringResource(clazz, nestedKey, locale, style, variation); + + replacedPlaceHolder = handleMissingKey(nestedKey, locale, style, component, + replacedPlaceHolder); + matcher.appendReplacement(output, replacedPlaceHolder); + } + matcher.appendTail(output); + return output.toString(); + } + + /** + * Handles a missing key + * + * @param nestedKey + * the key which is going to be handled + * @param locale + * the actual locale + * @param style + * the style + * @param component + * the component + * + * @param replacedPlaceHolder + * @return the replacedPlaceholder + */ + private String handleMissingKey(String nestedKey, Locale locale, String style, + Component component, String replacedPlaceHolder) + { + if (replacedPlaceHolder == null) + { + if (resourceSettings.getThrowExceptionOnMissingResource()) + { + AppendingStringBuffer message = new AppendingStringBuffer( + "Unable to find property: '"); + message.append(nestedKey); + message.append('\''); + + if (component != null) + { + message.append(" for component: "); + message.append(component.getPageRelativePath()); + message.append(" [class=").append(component.getClass().getName()).append(']'); + } + message.append(". Locale: ").append(locale).append(", style: ").append(style); + + throw new MissingResourceException(message.toString(), + (component != null ? component.getClass().getName() : ""), nestedKey); + } + else + { + replacedPlaceHolder = "[Warning: Property for '" + nestedKey + "' not found]"; + } + } + return replacedPlaceHolder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/2b12b897/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator.properties ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator.properties b/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator.properties index 96b9483..4841a02 100644 --- a/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator.properties +++ b/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator.properties @@ -1,2 +1,6 @@ error=${label} is invalid + +key1=This is an +key2=assembled nested key. +nested=#(key1) #(key2) http://git-wip-us.apache.org/repos/asf/wicket/blob/2b12b897/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator_nl.properties ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator_nl.properties b/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator_nl.properties index f876ea2..d869396 100644 --- a/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator_nl.properties +++ b/wicket-core/src/test/java/org/apache/wicket/resource/loader/ClassStringResourceLoaderTest$MyValidator_nl.properties @@ -1,2 +1,6 @@ error=${label} is niet goed + +key1=This is an +key2=assembled nested key. +nested=#(key1) #(key2) http://git-wip-us.apache.org/repos/asf/wicket/blob/2b12b897/wicket-core/src/test/java/org/apache/wicket/resource/loader/NestedStringResourceLoaderTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/loader/NestedStringResourceLoaderTest.java b/wicket-core/src/test/java/org/apache/wicket/resource/loader/NestedStringResourceLoaderTest.java new file mode 100644 index 0000000..3a6b18b --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/resource/loader/NestedStringResourceLoaderTest.java @@ -0,0 +1,33 @@ +package org.apache.wicket.resource.loader; + +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.wicket.Component; +import org.apache.wicket.resource.loader.ClassStringResourceLoaderTest.MyValidator; +import org.apache.wicket.util.tester.WicketTestCase; +import org.junit.Test; + +/** + * Tests the nested string resource loader + */ +public class NestedStringResourceLoaderTest extends WicketTestCase +{ + + /** + * Tests the nested string resource loader + */ + @Test + public void testNestedStrings(){ + List<IStringResourceLoader> loaders = tester.getApplication().getResourceSettings().getStringResourceLoaders(); + ClassStringResourceLoader classStringResourceLoader = new ClassStringResourceLoader(MyValidator.class); + loaders.add(classStringResourceLoader); + NestedStringResourceLoader nestedStringResourceLoader = new NestedStringResourceLoader(loaders,Pattern.compile("#\\(([^ ]*?)\\)")); + loaders.clear(); + loaders.add(nestedStringResourceLoader); + + assertEquals("This is an assembled nested key.", + nestedStringResourceLoader.loadStringResource((Component)null, "nested", null, null, null)); + } + +} http://git-wip-us.apache.org/repos/asf/wicket/blob/2b12b897/wicket-user-guide/src/docs/guide/i18n/i18n_3.gdoc ---------------------------------------------------------------------- diff --git a/wicket-user-guide/src/docs/guide/i18n/i18n_3.gdoc b/wicket-user-guide/src/docs/guide/i18n/i18n_3.gdoc index 2d6fc36..04a1453 100644 --- a/wicket-user-guide/src/docs/guide/i18n/i18n_3.gdoc +++ b/wicket-user-guide/src/docs/guide/i18n/i18n_3.gdoc @@ -85,6 +85,7 @@ Wicket implements the default lookup algorithm using the strategy pattern. The c # *ClassStringResourceLoader:* searches into bundles of a given class. By default the target class is the application class. # *ValidatorStringResourceLoader:* searches for resources into validator's bundles. A list of validators is provided by the form component that failed validation. # *InitializerStringResourceLoader:* this resource allows internationalization to interact with the initialization mechanism of the framework that will be illustrated in [paragraph 18.3|guide:advanced_3]. +# *NestedStringResourceLoader:* allows to replace nested Strings and can be chained up with other resource loader Developer can customize lookup algorithm removing default resource loaders or adding custom implementations to the list of the resource loaders in use. This task can be accomplished using method getStringResourceLoaders of setting class @org.apache.wicket.settings.ResourceSettings@:
