package net.sf.openrocket.util; import java.math.BigDecimal; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import java.util.Set; public class Config { private LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(); public void put(String key, String value) { validateType(value); map.put(key, value); } public void put(String key, Number value) { validateType(value); map.put(key, clone(value)); } public void put(String key, Boolean value) { validateType(value); map.put(key, value); } public void put(String key, List<?> value) { validateType(value); map.put(key, clone(value)); } public void put(String key, Object value) { validateType(value); map.put(key, clone(value)); } public Object get(String key, Object def) { return get(key, def, Object.class); } public Boolean getBoolean(String key, Boolean def) { return get(key, def, Boolean.class); } public Integer getInt(String key, Integer def) { Number number = get(key, null, Number.class); if (number == null) { return def; } else { return number.intValue(); } } public Long getLong(String key, Long def) { Number number = get(key, null, Number.class); if (number == null) { return def; } else { return number.longValue(); } } public Double getDouble(String key, Double def) { Number number = get(key, null, Number.class); if (number == null) { return def; } else { return number.doubleValue(); } } public String getString(String key, String def) { return get(key, def, String.class); } public List<?> getList(String key, List<?> def) { return get(key, def, List.class); } public boolean containsKey(String key) { return map.containsKey(key); } public Set<String> keySet() { return Collections.unmodifiableMap(map).keySet(); } @Override public Config clone() { Config copy = new Config(); for (Entry<String, Object> entry : map.entrySet()) { copy.map.put(entry.getKey(), clone(entry.getValue())); } return copy; } @SuppressWarnings("unchecked") private <T> T get(String key, T def, Class<T> type) { Object value = map.get(key); if (type.isInstance(value)) { return (T) value; } else { return def; } } private void validateType(Object value) { if (value == null) { throw new NullPointerException("Attempting to add null value to Config object"); } else if (value instanceof Boolean) { // ok } else if (value instanceof Number) { // ok } else if (value instanceof String) { // ok } else if (value instanceof List<?>) { List<?> list = (List<?>) value; for (Object v : list) { validateType(v); } } else { throw new IllegalArgumentException("Attempting to add value of type " + value.getClass() + " to Config object, value=" + value); } } private Object clone(Object value) { if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long || value instanceof Float || value instanceof Double || value instanceof Boolean || value instanceof String) { // immutable return value; } else if (value instanceof Number) { return new BigDecimal(value.toString()); } else if (value instanceof List<?>) { List<?> list = (List<?>) value; ArrayList<Object> copy = new ArrayList<Object>(list.size()); for (Object o : list) { copy.add(clone(o)); } return copy; } else { throw new IllegalStateException("Config contained value = " + value + " type = " + ((value != null) ? value.getClass() : "null")); } } }