package au.net.causal.projo.prefs.transform;
import java.io.File;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import au.net.causal.projo.prefs.DataTypeSupport;
import au.net.causal.projo.prefs.PreferenceKeyMetadata;
import au.net.causal.projo.prefs.PreferencesException;
import au.net.causal.projo.prefs.TransformDataTypeSupportChain;
import au.net.causal.projo.prefs.TransformGetChain;
import au.net.causal.projo.prefs.TransformPutChain;
import au.net.causal.projo.prefs.TransformRemoveChain;
import au.net.causal.projo.prefs.TransformResult;
import com.google.common.reflect.TypeToken;
/**
* Transforms {@link File} objects to {@link Path} objects.
* <p>
*
* In combination with {@link PathToStringTransformer}, gives preference stores the ability to store both {@link File}s and {@link Path}s so long
* as the underlying store supports storing strings.
*
* @author prunge
*/
public class FileToPathTransformer implements PreferenceTransformer
{
@Override
public <T> TransformResult<T> applyGet(String key, PreferenceKeyMetadata<T> keyMetadata, TransformGetChain chain) throws PreferencesException
{
if (!isSupported(keyMetadata, chain))
return(null);
//Read as string from underlying store, convert to Long and pass up
Path storeValue = chain.getValue(key, keyMetadata.withDataType(Path.class));
File fValue;
if (storeValue == null)
fValue = null;
else
{
try
{
fValue = storeValue.toFile();
}
catch (UnsupportedOperationException e)
{
//May occur if the path is not from the local file system and the path does not support creating Files
throw new PreferencesException("Path '" + storeValue + "' cannot be converted to File.", e);
}
}
//Safe because isSupported() ensured that T is only of File type
@SuppressWarnings("unchecked")
TransformResult<T> result = new TransformResult<>((T)fValue);
return(result);
}
@Override
public <T> boolean applyPut(String key, T value, PreferenceKeyMetadata<T> keyMetadata, TransformPutChain chain) throws PreferencesException
{
if (!isSupported(keyMetadata, chain))
return(false);
//The value must be of File type if we get here
File fValue = (File)value;
//Convert to Path
Path pValue;
if (fValue == null)
pValue = null;
else
{
try
{
pValue = fValue.toPath();
}
catch (InvalidPathException e)
{
throw new PreferencesException("Could not convert file '" + fValue + "' to a Path.", e);
}
}
chain.putValue(key, pValue, keyMetadata.withDataType(Path.class));
return(true);
}
@Override
public <T> boolean applyRemove(String key, PreferenceKeyMetadata<T> keyMetadata, TransformRemoveChain chain) throws PreferencesException
{
if (!isSupported(keyMetadata, chain))
return(false);
chain.removeValue(key, keyMetadata.withDataType(Path.class));
return(true);
}
@Override
public DataTypeSupport applyDataTypeSupport(PreferenceKeyMetadata<?> keyMetadata, TransformDataTypeSupportChain chain) throws PreferencesException
{
if (!keyMetadata.getDataType().equals(TypeToken.of(File.class)))
return(null);
if (!chain.isDataTypeSupported(keyMetadata.withDataType(Path.class)))
return(null);
return(DataTypeSupport.ADD_SUPPORT);
}
/**
* Supported when:
*
* <ul>
* <li>key is of {@link File} type</li>
* <li>{@link File} type is not supported natively by the store</li>
* <li>{@link Path} is supported by the chain</li>
* </ul>
*/
private boolean isSupported(PreferenceKeyMetadata<?> keyMetadata, TransformDataTypeSupportChain chain)
throws PreferencesException
{
if (!keyMetadata.getDataType().equals(TypeToken.of(File.class)))
return(false);
if (chain.isDataTypeSupportedNatively(keyMetadata.withDataType(File.class)))
return(false);
if (!chain.isDataTypeSupported(keyMetadata.withDataType(Path.class)))
return(false);
return(true);
}
}