package com.koushikdutta.ion;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.async.future.SimpleFuture;
import com.koushikdutta.async.http.ResponseCacheMiddleware;
import com.koushikdutta.async.http.libcore.DiskLruCache;
import com.koushikdutta.async.parser.AsyncParser;
import com.koushikdutta.async.parser.DocumentParser;
import com.koushikdutta.async.parser.StringParser;
import com.koushikdutta.async.stream.InputStreamDataEmitter;
import com.koushikdutta.async.stream.OutputStreamDataSink;
import com.koushikdutta.ion.gson.GsonParser;
import com.koushikdutta.ion.gson.GsonSerializer;
import org.w3c.dom.Document;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by koush on 11/17/13.
*/
public class DiskLruCacheStore {
Ion ion;
DiskLruCache cache;
DiskLruCacheStore(Ion ion, DiskLruCache cache) {
this.ion = ion;
this.cache = cache;
}
private <T> Future<T> put(final String rawKey, final T value, final AsyncParser<T> parser) {
final SimpleFuture<T> ret = new SimpleFuture<T>();
Ion.getIoExecutorService().execute(new Runnable() {
@Override
public void run() {
final DiskLruCache.Editor editor;
try {
final String key = ResponseCacheMiddleware.toKeyString("ion-store:" + rawKey);
editor = cache.edit(key);
}
catch (Exception e) {
ret.setComplete(e);
return;
}
final OutputStream out;
try {
out = editor.newOutputStream(0);
for (int i = 1; i < cache.getValueCount(); i++) {
editor.newOutputStream(i).close();
}
}
catch (Exception e) {
try {
editor.abort();
}
catch (Exception ex) {
}
ret.setComplete(e);
return;
}
if (editor == null) {
ret.setComplete(new Exception("unable to edit"));
return;
}
parser.write(new OutputStreamDataSink(ion.getServer(), out), value, new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
if (ex == null) {
try {
out.close();
editor.commit();
ret.setComplete(value);
return;
}
catch (Exception e) {
ex = e;
}
}
try {
editor.abort();
}
catch (Exception e) {
}
ret.setComplete(ex);
}
});
}
});
return ret;
}
public Future<String> putString(String key, String value) {
return put(key, value, new StringParser());
}
public Future<JsonObject> putJsonObject(String key, JsonObject value) {
return put(key, value, new GsonParser<JsonObject>());
}
public Future<Document> putDocument(String key, Document value) {
return put(key, value, new DocumentParser());
}
public Future<JsonArray> putJsonArray(String key, JsonArray value) {
return put(key, value, new GsonParser<JsonArray>());
}
/*
public Future<InputStream> putInputStream(InputStream value) {
throw new AssertionError("not implemented");
}
public Future<byte[]> putByteArray(byte[] bytes) {
throw new AssertionError("not implemented");
}
*/
public <T> Future<T> put(String key, T value, Class<T> clazz) {
return put(key, value, new GsonSerializer<T>(ion.configure().getGson(), clazz));
}
public <T> Future<T> put(String key, T value, TypeToken<T> token) {
return put(key, value, new GsonSerializer<T>(ion.configure().getGson(), token));
}
private <T> Future<T> get(final String rawKey, final AsyncParser<T> parser) {
final SimpleFuture<T> ret = new SimpleFuture<T>();
Ion.getIoExecutorService().execute(new Runnable() {
@Override
public void run() {
try {
final String key = ResponseCacheMiddleware.toKeyString("ion-store:" + rawKey);
final DiskLruCache.Snapshot snapshot = cache.get(key);
if (snapshot == null) {
ret.setComplete((T)null);
return;
}
InputStream inputStream = snapshot.getInputStream(0);
InputStreamDataEmitter emitter = new InputStreamDataEmitter(ion.getServer(), inputStream);
parser.parse(emitter).setCallback(new FutureCallback<T>() {
@Override
public void onCompleted(Exception e, T result) {
snapshot.close();
if (e != null)
ret.setComplete(e);
else
ret.setComplete(result);
}
});
}
catch (Exception e) {
}
}
});
return ret;
}
public Future<String> getString(String key) {
return get(key, new StringParser());
}
public Future<JsonObject> getJsonObject(String key) {
return get(key, new GsonParser<JsonObject>());
}
public Future<JsonArray> getJsonArray(String key) {
return get(key, new GsonParser<JsonArray>());
}
public Future<Document> getDocument(String key) {
return get(key, new DocumentParser());
}
public <T> Future<T> get(String key, Class<T> clazz) {
return get(key, new GsonSerializer<T>(ion.configure().getGson(), clazz));
}
public <T> Future<T> get(String key, TypeToken<T> token) {
return get(key, new GsonSerializer<T>(ion.configure().getGson(), token));
}
public Future<String> remove(final String key) {
final SimpleFuture<String> ret = new SimpleFuture<String>();
Ion.getIoExecutorService().execute(new Runnable() {
@Override
public void run() {
try {
cache.remove(key);
ret.setComplete(key);
}
catch (Exception e) {
ret.setComplete(e);
}
}
});
return ret;
}
}