Created
June 30, 2010 09:14
-
-
Save CliveEvans/458435 to your computer and use it in GitHub Desktop.
AbstractConfiguration
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
private List<AbstractConfigurationEntry<?>> entries = new ArrayList<AbstractConfigurationEntry<?>>(); | |
/** | |
* | |
* {@link AbstractConfiguration} now uses reflection to build its list of entries<p> | |
* You no longer need to call define to add your {@link AbstractConfigurationEntry}s to the list to be validated<p> | |
* | |
* This method will be removed in the next version | |
* | |
*/ | |
@Deprecated | |
protected static <T extends AbstractConfigurationEntry<?>> T define(T entry) { | |
return entry; | |
} |
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
@Test | |
public void shouldBeAbleToCreateTwoDifferentConfigurationsInOneJVM() throws Exception { | |
new ConfigurationExample(propertiesConfig); | |
PropertiesConfiguration secondPropertiesConfig = new PropertiesConfiguration(); | |
secondPropertiesConfig.addProperty("different.key", "value"); | |
SecondConfiguration secondConfiguration = new SecondConfiguration(secondPropertiesConfig); | |
assertEquals("value", secondConfiguration.getDifferentEntry()); | |
} |
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
public abstract class AbstractConfiguration { | |
private static List<AbstractConfigurationEntry<?>> entries = new ArrayList<AbstractConfigurationEntry<?>>(); | |
protected static <T extends AbstractConfigurationEntry<?>> T define(T entry) { | |
entries.add(entry); | |
return entry; | |
} | |
public AbstractConfiguration(Configuration configuration) throws ConfigurationException { | |
populateEntries(configuration); | |
} | |
private void populateEntries(Configuration configuration) throws ConfigurationException { | |
List<String> problemMessages = initialiseEntries(configuration); | |
if (! problemMessages.isEmpty()) { | |
String errorMessage = buildExceptionMessage(problemMessages); | |
throw new ConfigurationException(errorMessage); | |
} | |
} | |
} |
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
public class AbstractConfigurationTest { | |
private PropertiesConfiguration propertiesConfig; | |
@Rule | |
public ExpectedException expectedException = ExpectedException.none(); | |
@Before | |
public void setup() throws Exception { | |
propertiesConfig = new PropertiesConfiguration(); | |
} | |
@After | |
public void after() { | |
AbstractConfiguration.clearEntries(); | |
} | |
@Test | |
public void shouldSetEntryValue() throws Exception { | |
StringConfigurationEntry entry = AbstractConfiguration.define(new StringConfigurationEntry("entry")); | |
propertiesConfig.setProperty("entry", "value"); | |
new AbstractConfiguration(propertiesConfig){}; | |
assertEquals("value", entry.getValue()); | |
} | |
@Test | |
public void shouldErrorIfExtraKeysInConfigFile() throws Exception { | |
expectedException.expect(ConfigurationException.class); | |
expectedException.expectMessage("Key [shouldnt] with value [behere] is not defined"); | |
AbstractConfiguration.define(new StringConfigurationEntry("entry")); | |
propertiesConfig.setProperty("entry", "value"); | |
propertiesConfig.setProperty("shouldnt", "behere"); | |
new AbstractConfiguration(propertiesConfig){}; | |
} | |
@Test | |
public void shouldLeaveDefaultValueInPlaceIfPropertyIsMissing() throws Exception { | |
StringConfigurationEntry entry = AbstractConfiguration.define(new StringConfigurationEntry("entry", "default")); | |
new AbstractConfiguration(propertiesConfig){}; | |
assertEquals("default", entry.getValue()); | |
} | |
@Test | |
public void shouldThrowConfigurationExceptionAnyIfPropertyIsInvalid() throws Exception { | |
expectedException.expect(ConfigurationException.class); | |
expectedException.expectMessage("Configuration is invalid, the following problems were detected:\n\tmy.entry value [] is not valid"); | |
AbstractConfiguration.define(new StringConfigurationEntry("my.entry", "default")); | |
propertiesConfig.setProperty("my.entry", ""); | |
new AbstractConfiguration(propertiesConfig){}; | |
} | |
@Test | |
public void shouldThrowConfigurationExceptionIfAnyMandatoryEntryIsMissing() throws Exception { | |
expectedException.expect(ConfigurationException.class); | |
expectedException.expectMessage("Configuration is invalid, the following problems were detected:\n\trequired key [my.entry] not found"); | |
AbstractConfiguration.define(new StringConfigurationEntry("my.entry")); | |
new AbstractConfiguration(propertiesConfig){}; | |
} | |
} |
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
private static class ConfigurationExample extends AbstractConfiguration { | |
private static final StringConfigurationEntry ENTRY_WITH_DEFAULT = define(new StringConfigurationEntry("entry.that.defaults", "default")); | |
private static final StringConfigurationEntry ENTRY_WITHOUT_DEFAULT = define(new StringConfigurationEntry("entry")); | |
private static final IntegerConfigurationEntry INTEGER_ENTRY = define(new IntegerConfigurationEntry("integer")); | |
public ConfigurationExample(Configuration configuration) throws ConfigurationException { | |
super(configuration); | |
} | |
public ConfigurationExample(Properties properties) throws ConfigurationException { | |
super(properties); | |
} | |
public String getEntryWithoutDefault() { | |
return ENTRY_WITHOUT_DEFAULT.getValue(); | |
} | |
public String getEntryWithDefault() { | |
return ENTRY_WITH_DEFAULT.getValue(); | |
} | |
public Integer getIntegerEntry() { | |
return INTEGER_ENTRY.getValue(); | |
} | |
} |
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
private void populateEntries(Configuration configuration) throws ConfigurationException { | |
buildEntriesList(); | |
List<String> problemMessages = initialiseEntries(configuration); | |
if (! problemMessages.isEmpty()) { | |
String errorMessage = buildExceptionMessage(problemMessages); | |
throw new ConfigurationException(errorMessage); | |
} | |
} | |
private void buildEntriesList() { | |
for (Field field : this.getClass().getDeclaredFields()) { | |
if(isAConfigurationEntry(field) ) { | |
addFieldToEntries(field); | |
} | |
} | |
} | |
@SuppressWarnings("unchecked") | |
private boolean isAConfigurationEntry(Field field) { | |
Type type = field.getGenericType(); | |
if (type instanceof Class) { | |
return AbstractConfigurationEntry.class.isAssignableFrom((Class) type); | |
} | |
return false; | |
} | |
private void addFieldToEntries(Field field) { | |
field.setAccessible(true); | |
try { | |
AbstractConfigurationEntry<?> fieldObject = (AbstractConfigurationEntry<?>)field.get(null); | |
entries.add(fieldObject ); | |
} catch (IllegalAccessException e) { | |
throw new RuntimeException(e); | |
} | |
} |
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
private static class SecondConfiguration extends AbstractConfiguration { | |
private static final StringConfigurationEntry DIFFERENT_ENTRY = define(new StringConfigurationEntry("different.key")); | |
public SecondConfiguration(Configuration configuration) throws ConfigurationException { | |
super(configuration); | |
} | |
public String getDifferentEntry(){ | |
return DIFFERENT_ENTRY.getValue(); | |
} | |
} |
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
private ConfigurationExample configurationExample; | |
@Before | |
public void setup() throws Exception { | |
propertiesConfig = new PropertiesConfiguration(); | |
propertiesConfig.setProperty("entry", "value"); | |
} | |
@Test | |
public void shouldSetEntryValue() throws Exception { | |
propertiesConfig.setProperty("entry", "not the value in setup"); | |
configurationExample = new ConfigurationExample(propertiesConfig); | |
assertEquals("not the value in setup", configurationExample.getEntryWithoutDefault()); | |
} | |
@Test | |
public void shouldErrorIfExtraKeysInConfigFile() throws Exception { | |
expectedException.expect(ConfigurationException.class); | |
expectedException.expectMessage("Key [shouldnt] with value [behere] is not defined"); | |
propertiesConfig.setProperty("entry", "value"); | |
propertiesConfig.setProperty("shouldnt", "behere"); | |
new ConfigurationExample(propertiesConfig); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment