package greymerk.roguelike.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
/**
* Provides configuration information.
*/
public abstract class ConfigurationProvider implements Iterable<Configuration> {
private static final String true_regex="^\\s*(?:t(?:rue)?|y(?:es)?)\\s*$";
private static final String false_regex="^\\s*(?:f(?:alse)?|no?)\\s*$";
private static final String true_string="true";
private static final String false_string="false";
private Pattern true_pattern;
private Pattern false_pattern;
protected Hashtable<String,String> kvp;
protected ConfigurationProvider () {
kvp=new Hashtable<String,String>();
true_pattern=Pattern.compile(true_regex);
false_pattern=Pattern.compile(false_regex);
}
/**
* Checks to see whether a configuration
* setting exists.
*
* \param [in] key
* The key to check.
*
* \return
* \em true if \em key has associated
* data in the configuration store,
* \em false otherwise.
*/
public boolean ContainsKey (String key) {
// Null keys never exist
if (key==null) return false;
return kvp.get(key)!=null;
}
/**
* Gets a configuration setting,
* if it exists.
*
* \param [in] key
* The key whose associated configuration
* information is to be retrieved.
*
* \return
* The data associated with \em key,
* if it exists, \em null otherwise.
*/
public String Get (String key) {
// Guard against null keys
if (key==null) return null;
// Fetch
return kvp.get(key);
}
/**
* Gets a configuration setting, returning
* some default value if no default is
* specified.
*
* \param [in] key
* The key whose associated configuration
* information is to be retrieved.
* \param [in] fallback
* A value which shall be retrieved if
* no configuration is associated with
* \em key.
*
* \return
* The data associated with \em key, if
* it exists, otherwise \em fallback.
*/
public String Get (String key, String fallback) {
String value=Get(key);
return (value==null) ? fallback : value;
}
/**
* Gets a configuration setting as a double.
*
* \param [in] key
* The key whose associated configuration
* information is to be retrieved.
* \param [in] fallback
* The value which will be retrieved if
* \em key is not present, or if \em key
* could not be parsed to a double.
*
* \return
* Either the configuration associated
* with \em key, or \em fallback.
*/
public double GetDouble (String key, double fallback) {
String value=Get(key);
if (value==null) return fallback;
try {
return Double.parseDouble(value);
} catch (NumberFormatException e) { }
return fallback;
}
/**
* Gets a configuration setting as an integer.
*
* \param [in] key
* The key whose associated configuration
* information is to be retrieved.
* \param [in] fallback
* The value which will be retrieved if
* \em key is not present, or if \em key
* could not be parsed to an integer.
*
* \return
* Either the configuration associated with
* \em key, or \em fallback.
*/
public int GetInteger (String key, int fallback) {
String value=Get(key);
if (value==null) return fallback;
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) { }
return fallback;
}
/**
* Gets a configuration setting as a boolean.
*
* \param [in] key
* The key whose associated configuration
* information is to be retrieved.
* \param [in] fallback
* The value which will be retrieved if
* \em key is not present, or if \em key
* could not be parsed to an integer.
*
* \return
* Either the configuration associated with
* \em key, or \em fallback.
*/
public boolean GetBoolean (String key, boolean fallback) {
String value=Get(key);
if (value==null) return fallback;
if (true_pattern.matcher(value).find()) return true;
if (false_pattern.matcher(value).find()) return false;
return fallback;
}
public List<Integer> GetListInteger (String key, List<Integer> fallback) {
String value = Get(key);
if(value == null) return fallback;
String[] arrValues = value.split(",");
List<String> values = Arrays.asList(arrValues);
List<Integer> ints = new ArrayList<Integer>();
for (String s : values) {
try {
ints.add(Integer.parseInt(s));
} catch (NumberFormatException e) { }
}
return ints;
}
/**
* Sets a configuration, creating it if it
* does not exist, updating it otherwise.
*
* \param [in] key
* The key associated with the configuration
* to update or create.
* \param [in] value
* The value to associate with \em key.
*/
public void Set (String key, String value) {
// If the key is null, pass, that's
// meaningless
if (key==null) return;
// If the value is null, that's actually
// an attempt to remove a configuration
if (value==null) {
kvp.remove(key);
return;
}
// Otherwise we update/insert the
// configuration
kvp.put(key,value);
}
/**
* Sets a configuration, creating it if it
* does not exist, updating it otherwise.
*
* \param [in] key
* The key associated with the configuration
* to update or create.
* \param [in] value
* The value to associate with \em key.
*/
public void Set (String key, double value) {
Set(
key,
Double.toString(value)
);
}
/**
* Sets a configuration, creating it if it
* does not exist, updating it otherwise.
*
* \param [in] key
* The key associated with the configuration
* to update or create.
* \param [in] value
* The value to associate with \em key.
*/
public void Set (String key, int value) {
Set(
key,
Integer.toString(value)
);
}
/**
* Sets a configuration, creating it if it
* does not exist, updating it otherwise.
*
* \param [in] key
* The key associated with the configuration
* to update or create.
* \param [in] value
* The value to associate with \em key.
*/
public void Set (String key, boolean value) {
Set(
key,
value ? true_string : false_string
);
}
public void Set (String key, List<Integer> intList){
Set(key, StringUtils.join(intList, ","));
}
/**
* Unsets a configuration, removing it.
*
* If the requested configuration didn't
* exist, nothing happens.
*
* \param [in] key
* The key associated with the
* configuration to remote.
*/
public void Unset (String key) {
// If the key is null, pass, that's
// meaningless
if (key==null) return;
// Remove
kvp.remove(key);
}
/**
* Fetches an iterator which may be used
* to traverse the configurations in this
* provider in alphabetical order.
*
* \return
* An iterator.
*/
public Iterator<Configuration> iterator () {
Set<Map.Entry<String, String>> entries = new TreeSet<Map.Entry<String, String>>(new EntryAlphabetical());
entries.addAll(kvp.entrySet());
return new ConfigurationProviderIterator(entries.iterator());
}
private class EntryAlphabetical implements Comparator<Map.Entry<String, String>>{
@Override
public int compare(Entry<String, String> thing, Entry<String, String> other) {
return thing.getKey().compareTo(other.getKey());
}
}
}