package au.net.causal.projo.prefs.memory;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import au.net.causal.projo.prefs.AbstractPreferenceNode;
import au.net.causal.projo.prefs.PreferenceKeyMetadata;
import au.net.causal.projo.prefs.PreferenceNode;
import au.net.causal.projo.prefs.PreferencesException;
import au.net.causal.projo.prefs.UnsupportedDataTypeException;
/**
* A completely in-memory implementation of a preference node that supports a single arbitrary back-end data type. The implementation is backed by a
* simple hash map.
* <p>
*
* This class is mostly useful for testing, especially with the arbitrary data type backend capability, which is useful for testing data transforms.
*
* @author prunge
*
* @param <D> the single data type supported for keys.
*/
public class InMemoryPreferenceNode<D> extends AbstractPreferenceNode
{
private final Map<String, InMemoryPreferenceNode<D>> childNodes = new HashMap<>();
private final Map<String, D> keyValueMap = new HashMap<>();
private final Class<D> valueDataType;
/**
* Creates an <code>InMemoryPreferenceNode</code> with the specified data type used for storing values.
*
* @param valueDataType the value data type.
*
* @throws NullPointerException if <code>valueDataType</code> is null.
*/
public InMemoryPreferenceNode(Class<D> valueDataType)
{
super(Collections.<Class<? extends Annotation>>emptySet());
if (valueDataType == null)
throw new NullPointerException("valueDataType == null");
this.valueDataType = valueDataType;
}
@Override
protected boolean isDataTypeSupportedImpl(PreferenceKeyMetadata<?> keyType) throws PreferencesException
{
if (valueDataType.equals(keyType.getDataType().getRawType()))
return(true);
return(false);
}
@Override
protected <T> T getValueImpl(String key, PreferenceKeyMetadata<T> metadata) throws UnsupportedDataTypeException, PreferencesException
{
if (!isDataTypeSupported(metadata))
throw new UnsupportedDataTypeException(metadata.getDataType());
D value = getNativeValue(key);
//Cast is safe because we only support one data type
return((T)value);
}
/**
* Retrieves the value stored under the specified key natively by the in-memory node.
*
* @param key the key.
*
* @return the value stored under the key.
*
* @throws NullPointerException if <code>key</code> is null.
*
* @see #putNativeValue(String, Object)
*/
public D getNativeValue(String key)
{
return(keyValueMap.get(key));
}
@Override
protected <T> void putValueImpl(String key, T value, PreferenceKeyMetadata<T> metadata) throws UnsupportedDataTypeException, PreferencesException
{
if (!isDataTypeSupported(metadata))
throw new UnsupportedDataTypeException(metadata.getDataType());
putNativeValue(key, valueDataType.cast(value));
}
/**
* Stores a value under the specified key using the native data type of the preference store.
*
* @param key the key store the value under.
* @param value the value to store. May be null.
*
* @throws NullPointerException if <code>key</code> is null.
*
* @see #getNativeValue(String)
*/
public void putNativeValue(String key, D value)
{
keyValueMap.put(key, value);
}
@Override
protected <T> void removeValueImpl(String key, PreferenceKeyMetadata<T> metadata) throws UnsupportedDataTypeException, PreferencesException
{
if (!isDataTypeSupported(metadata))
throw new UnsupportedDataTypeException(metadata.getDataType());
keyValueMap.remove(key);
}
@Override
public void removeAllValues() throws PreferencesException
{
keyValueMap.clear();
}
@Override
public PreferenceNode getChildNode(String name) throws PreferencesException
{
InMemoryPreferenceNode<D> childNode = childNodes.get(name);
if (childNode == null)
{
childNode = new InMemoryPreferenceNode<>(valueDataType);
childNodes.put(name, childNode);
}
return(childNode);
}
@Override
public void removeChildNode(String name) throws PreferencesException
{
childNodes.remove(name);
}
@Override
public Set<String> getKeyNames() throws PreferencesException
{
return(keyValueMap.keySet());
}
@Override
public Set<String> getNodeNames() throws PreferencesException
{
return(childNodes.keySet());
}
@Override
public String toString()
{
return(keyValueMap.toString());
}
@Override
public void flush() throws PreferencesException
{
//Nothing to do
}
@Override
public void close() throws PreferencesException
{
flush();
}
}