Skip to content

Instantly share code, notes, and snippets.

@CliveEvans
Created June 30, 2010 09:14
Show Gist options
  • Save CliveEvans/458435 to your computer and use it in GitHub Desktop.
Save CliveEvans/458435 to your computer and use it in GitHub Desktop.
AbstractConfiguration
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;
}
@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());
}
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);
}
}
}
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){};
}
}
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();
}
}
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);
}
}
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();
}
}
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