-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #243 from sialcasa/234_global_resource_bundle
#234 global resource bundle
- Loading branch information
Showing
20 changed files
with
516 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
124 changes: 124 additions & 0 deletions
124
mvvmfx/src/main/java/de/saxsys/mvvmfx/internal/viewloader/ResourceBundleManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package de.saxsys.mvvmfx.internal.viewloader; | ||
|
||
import eu.lestard.doc.Internal; | ||
import sun.util.ResourceBundleEnumeration; | ||
|
||
import java.util.Enumeration; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Iterator; | ||
import java.util.ListResourceBundle; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.ResourceBundle; | ||
import java.util.Set; | ||
|
||
/** | ||
* @author manuel.mauky | ||
*/ | ||
@Internal | ||
public class ResourceBundleManager { | ||
|
||
private static final ResourceBundleManager SINGLETON = new ResourceBundleManager(); | ||
private ResourceBundle globalResourceBundle; | ||
|
||
ResourceBundleManager() { | ||
} | ||
|
||
public static ResourceBundleManager getInstance() { | ||
return SINGLETON; | ||
} | ||
|
||
public void setGlobalResourceBundle(ResourceBundle resourceBundle) { | ||
this.globalResourceBundle = resourceBundle; | ||
} | ||
|
||
public ResourceBundle getGlobalResourceBundle() { | ||
return globalResourceBundle; | ||
} | ||
|
||
|
||
/** | ||
* Merges the provided ResourceBundle with the global one (if any). | ||
* | ||
* The global resourceBundle has a lower priority then the provided one. If there is the same key defined in the | ||
* global and the provided resourceBundle, the value from the provided resourceBundle will be used. | ||
* | ||
* @param resourceBundle | ||
* a resourceBundle that will be merged. | ||
* @return the merged resourceBundle or null, if there is no global resource bundle and not given resource bundle. | ||
*/ | ||
public ResourceBundle mergeWithGlobal(ResourceBundle resourceBundle) { | ||
if (globalResourceBundle == null) { | ||
if (resourceBundle == null) { | ||
return null; | ||
} else { | ||
return resourceBundle; | ||
} | ||
} else { | ||
if (resourceBundle == null) { | ||
return globalResourceBundle; | ||
} else { | ||
return merge(resourceBundle, globalResourceBundle); | ||
} | ||
} | ||
} | ||
|
||
private ResourceBundle merge(ResourceBundle highPriority, ResourceBundle lowPriority) { | ||
return new MergedResourceBundle(highPriority, lowPriority); | ||
} | ||
|
||
private static class MergedResourceBundle extends ResourceBundle { | ||
private ResourceBundle highPriority; | ||
private ResourceBundle lowPriority; | ||
|
||
public MergedResourceBundle(ResourceBundle highPriority, ResourceBundle lowPriority) { | ||
Objects.nonNull(highPriority); | ||
Objects.nonNull(lowPriority); | ||
this.highPriority = highPriority; | ||
this.lowPriority = lowPriority; | ||
} | ||
|
||
@Override | ||
protected Object handleGetObject(String key) { | ||
if (highPriority.containsKey(key)) { | ||
return highPriority.getObject(key); | ||
} | ||
|
||
if (lowPriority.containsKey(key)) { | ||
return lowPriority.getObject(key); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
@Override | ||
public Enumeration<String> getKeys() { | ||
return new MergedEnumeration(highPriority.keySet(), lowPriority.keySet()); | ||
} | ||
} | ||
|
||
private static class MergedEnumeration implements Enumeration<String> { | ||
|
||
final Iterator<String> iterator; | ||
|
||
public MergedEnumeration(Set<String> highPriority, Set<String> lowPriority) { | ||
Set<String> allElements = new HashSet<>(); | ||
allElements.addAll(highPriority); | ||
allElements.addAll(lowPriority); | ||
|
||
iterator = allElements.iterator(); | ||
} | ||
|
||
@Override | ||
public boolean hasMoreElements() { | ||
return iterator.hasNext(); | ||
} | ||
|
||
@Override | ||
public String nextElement() { | ||
return iterator.next(); | ||
} | ||
} | ||
|
||
} |
117 changes: 117 additions & 0 deletions
117
mvvmfx/src/test/java/de/saxsys/mvvmfx/internal/viewloader/ResourceBundleManagerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package de.saxsys.mvvmfx.internal.viewloader; | ||
|
||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import java.util.ListResourceBundle; | ||
import java.util.MissingResourceException; | ||
import java.util.ResourceBundle; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.fail; | ||
|
||
/** | ||
* @author manuel.mauky | ||
*/ | ||
public class ResourceBundleManagerTest { | ||
|
||
private static final String KEY_COMMON = "key_common"; | ||
private static final String KEY_GLOBAL_SPECIFIC = "key_global"; | ||
private static final String KEY_OTHER_SPECIFIC = "key_other"; | ||
|
||
private static final String VALUE_1_GLOBAL = "global1"; | ||
private static final String VALUE_2_GLOBAL = "global2"; | ||
|
||
private static final String VALUE_1_OTHER = "other1"; | ||
private static final String VALUE_2_OTHER = "other2"; | ||
|
||
|
||
private ResourceBundleManager manager; | ||
|
||
private ResourceBundle global; | ||
private ResourceBundle other; | ||
|
||
@Before | ||
public void setup(){ | ||
manager = new ResourceBundleManager(); | ||
|
||
global = new ListResourceBundle() { | ||
@Override | ||
protected Object[][] getContents() { | ||
return new Object[][] { | ||
{ KEY_COMMON, VALUE_1_GLOBAL}, | ||
{ KEY_GLOBAL_SPECIFIC, VALUE_2_GLOBAL} | ||
}; | ||
} | ||
}; | ||
|
||
other = new ListResourceBundle() { | ||
@Override | ||
protected Object[][] getContents() { | ||
return new Object[][] { | ||
{ KEY_COMMON, VALUE_1_OTHER}, | ||
{ KEY_OTHER_SPECIFIC, VALUE_2_OTHER} | ||
}; | ||
} | ||
}; | ||
} | ||
|
||
|
||
@Test | ||
public void globalAndOtherExist() { | ||
|
||
manager.setGlobalResourceBundle(global); | ||
|
||
final ResourceBundle merged = manager.mergeWithGlobal(other); | ||
|
||
// the common value is used from the other bundle. | ||
assertThat(merged.getString(KEY_COMMON)).isEqualTo(VALUE_1_OTHER); | ||
|
||
// merged bundle contains specific values from both bundles | ||
assertThat(merged.getString(KEY_GLOBAL_SPECIFIC)).isEqualTo(VALUE_2_GLOBAL); | ||
assertThat(merged.getString(KEY_OTHER_SPECIFIC)).isEqualTo(VALUE_2_OTHER); | ||
} | ||
|
||
|
||
@Test | ||
public void noGlobalDefined() { | ||
|
||
final ResourceBundle merged = manager.mergeWithGlobal(other); | ||
|
||
assertThat(merged.getString(KEY_COMMON)).isEqualTo(VALUE_1_OTHER); | ||
|
||
assertThat(merged.getString(KEY_OTHER_SPECIFIC)).isEqualTo(VALUE_2_OTHER); | ||
|
||
expectMissingResource(merged, KEY_GLOBAL_SPECIFIC); | ||
} | ||
|
||
@Test | ||
public void otherBundleIsNull() { | ||
manager.setGlobalResourceBundle(global); | ||
|
||
final ResourceBundle merged = manager.mergeWithGlobal(null); | ||
|
||
assertThat(merged.getString(KEY_COMMON)).isEqualTo(VALUE_1_GLOBAL); | ||
|
||
assertThat(merged.getString(KEY_GLOBAL_SPECIFIC)).isEqualTo(VALUE_2_GLOBAL); | ||
expectMissingResource(merged, KEY_OTHER_SPECIFIC); | ||
} | ||
|
||
@Test | ||
public void bothBundlesAreNull() { | ||
final ResourceBundle merged = manager.mergeWithGlobal(null); | ||
|
||
assertThat(merged).isNull(); | ||
} | ||
|
||
|
||
private void expectMissingResource(ResourceBundle bundle, String key) { | ||
try { | ||
bundle.getString(key); | ||
fail("Expected MissingResourceException"); | ||
} catch (MissingResourceException e){ | ||
assertThat(e).hasMessageContaining(key); | ||
} | ||
} | ||
|
||
} |
51 changes: 51 additions & 0 deletions
51
mvvmfx/src/test/java/de/saxsys/mvvmfx/resourcebundle/global/GlobalResourceBundleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package de.saxsys.mvvmfx.resourcebundle.global; | ||
|
||
import de.saxsys.javafx.test.JfxRunner; | ||
import de.saxsys.mvvmfx.FluentViewLoader; | ||
import de.saxsys.mvvmfx.MvvmFX; | ||
import de.saxsys.mvvmfx.ViewTuple; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import java.util.ResourceBundle; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
/** | ||
* Test global resource bundles. See https://github.com/sialcasa/mvvmFX/issues/234. | ||
* | ||
* @author manuel.mauky | ||
*/ | ||
@RunWith(JfxRunner.class) | ||
public class GlobalResourceBundleTest { | ||
|
||
|
||
private ResourceBundle global; | ||
private ResourceBundle other; | ||
|
||
@Before | ||
public void setup(){ | ||
global = ResourceBundle.getBundle(this.getClass().getPackage().getName() + ".global"); | ||
other = ResourceBundle.getBundle(this.getClass().getPackage().getName() + ".other"); | ||
} | ||
|
||
@Test | ||
public void test() { | ||
MvvmFX.setGlobalResourceBundle(global); | ||
|
||
final ViewTuple<TestView, TestViewModel> viewTuple = FluentViewLoader.fxmlView(TestView.class).resourceBundle(other).load(); | ||
final TestView codeBehind = viewTuple.getCodeBehind(); | ||
|
||
assertThat(codeBehind.resources).isNotNull(); | ||
|
||
assertThat(codeBehind.global_label.getText()).isEqualTo("global"); | ||
assertThat(codeBehind.other_label.getText()).isEqualTo("other"); | ||
|
||
// both "global" and "other" are containing the key "label". | ||
// in this case "other" has the higher priority and overwrites the value defined in "global" | ||
assertThat(codeBehind.label.getText()).isEqualTo("other"); | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.