package openeye.storage;
import com.google.common.base.Throwables;
import com.google.gson.Gson;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class GsonSessionStorage<T> implements IAppendableStorage<T> {
private static final DateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss");
private final File archiveFile;
private ZipOutputStream archiveStream;
protected final Class<? extends T> cls;
protected final Gson gson;
private final String ext;
private int counter;
public GsonSessionStorage(File dir, String ext, Class<? extends T> cls, Gson gson) {
this.ext = ext;
this.gson = gson;
this.cls = cls;
final String name = generateId() + ".zip";
archiveFile = new File(dir, name);
}
private static String generateId() {
synchronized (FORMATTER) {
return FORMATTER.format(new Date());
}
}
@Override
public IDataSource<T> createNew() {
return createNew("data");
}
private ZipOutputStream archiveStream() throws IOException {
if (archiveStream == null) {
OutputStream stream = new FileOutputStream(archiveFile);
archiveStream = new ZipOutputStream(stream);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
if (archiveStream != null) archiveStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
return archiveStream;
}
@Override
public IDataSource<T> createNew(String id) {
final String fullId = String.format("%s-%04d.%s", id, counter++, ext);
return new GsonStreamSource<T>(fullId, cls, gson) {
@Override
public void delete() {
throw new UnsupportedOperationException();
}
@Override
protected InputStream createInputStream() {
throw new UnsupportedOperationException();
}
@Override
protected void afterWrite(Writer writer) throws IOException {
writer.flush();
final ZipOutputStream archiveStream = archiveStream();
archiveStream.closeEntry();
archiveStream.flush();
}
@Override
protected OutputStream createOutputStream() {
try {
ZipOutputStream stream = archiveStream();
stream.putNextEntry(new ZipEntry(fullId));
return stream;
} catch (Throwable t) {
throw Throwables.propagate(t);
}
}
@Override
protected String description() {
return String.format("%s in archive %s", fullId, archiveFile);
}
@Override
protected boolean sourceExists() {
return false;
}
};
}
}