package com.sandwich.util.io;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UTFDataFormatException;
/**
* Handles persistence to/from a filesystem, and makes assumption instances of T
* are mutated after retrieval. Their mutations are saved to file on app
* shutdown automatically.
*
* @param <T>
*/
public class DataFileHelper<T> {
private File dataFile;
private T lastRetrieval;
private T defaultState;
public DataFileHelper(File dataFile, T defaultState){
this.dataFile = dataFile;
if(!dataFile.exists()){
dataFile.getParentFile().mkdirs();
write(defaultState);
}
this.defaultState = defaultState;
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
if(lastRetrieval != null){
write(lastRetrieval);
}
}
}));
}
@SuppressWarnings("unchecked")
public T read(){
ObjectInputStream objectInputStream = null;
try {
File dataFile = getDataFile();
if(!dataFile.exists()){
return null;
}
objectInputStream = new ObjectInputStream(new FileInputStream(dataFile));
if(dataFile.exists()){
try {
return lastRetrieval = (T)objectInputStream.readObject();
}catch(UTFDataFormatException x){
createNewFile(dataFile);
return defaultState;
}catch(EOFException x){
createNewFile(dataFile);
return defaultState;
}
}else{
return null;
}
} catch (Exception e) {
try{
if(objectInputStream != null){
objectInputStream.close();
}
}catch(Exception e2){
throw new RuntimeException(e2);
}
throw new RuntimeException(e);
} finally {
if(objectInputStream != null){
try {
objectInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
private void createNewFile(File dataFile) throws IOException {
dataFile.delete();
dataFile.createNewFile();
write(defaultState);
}
public void write(T state){
ObjectOutputStream objectOutputStream = null;
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream(getDataFile()));
objectOutputStream.writeObject(state);
} catch (Exception e) {
try{
if(objectOutputStream != null){
objectOutputStream.close();
}
}catch(Exception e2){
throw new RuntimeException(e2);
}
throw new RuntimeException(e);
} finally {
if(objectOutputStream != null){
try {
objectOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
private File getDataFile() {
return dataFile;
}
}