package com.mastfrog.acteur.mongo;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.util.Providers;
import com.mastfrog.acteur.Closables;
import com.mastfrog.acteur.Event;
import com.mastfrog.acteur.HttpEvent;
import com.mastfrog.acteur.ResponseWriter;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import java.util.Map;
import org.bson.types.ObjectId;
/**
*
* @author Tim Boudreau
*/
public class CursorWriter extends ResponseWriter {
private final DBCursor cursor;
private final boolean closeConnection;
private final MapFilter filter;
@Inject
public CursorWriter(final DBCursor cursor, Closables clos, HttpEvent evt, Provider<MapFilter> filter) {
this(cursor, !evt.isKeepAlive(), filter);
clos.add(cursor);
}
public CursorWriter(DBCursor cursor, HttpEvent evt, Closables closables) {
this(cursor, closables, evt, Providers.of(NO_FILTER));
}
public CursorWriter(DBCursor cursor, boolean closeConnection, Provider<MapFilter> filter) {
this.cursor = cursor;
this.closeConnection = closeConnection;
MapFilter mf;
try {
mf = filter.get();
} catch (IllegalStateException ex) {
mf = null;
}
this.filter = mf;
}
@Override
@SuppressWarnings("unchecked")
public Status write(Event<?> evt, Output out, int iter) throws Exception {
try {
if (iter == 0) {
out.write("[\n");
}
boolean hasNext = cursor.hasNext();
if (hasNext) {
DBObject ob = cursor.next();
Map<String, Object> m = ob.toMap();
if (m.get("_id") instanceof ObjectId) {
ObjectId oid = (ObjectId) m.get("_id");
m.put("_id", oid.toString());
}
if (filter != null) {
out.writeObject(filter.filter(m));
} else {
out.writeObject(m);
}
hasNext = cursor.hasNext();
}
if (!hasNext) {
out.write("\n]\n");
cursor.close();
if (closeConnection) {
// out.future().addListener(ChannelFutureListener.CLOSE);
}
} else {
out.write(",\n");
}
return hasNext ? Status.NOT_DONE : Status.DONE;
} catch (Exception e) {
try {
out.channel().close();
} finally {
cursor.close();
}
throw e;
}
}
@ImplementedBy(MapFilterImpl.class)
public static interface MapFilter {
public Map<String, Object> filter(Map<String, Object> m);
}
public static final MapFilter NO_FILTER = new MapFilterImpl();
static class MapFilterImpl implements MapFilter {
public Map<String, Object> filter(Map<String, Object> m) {
return m;
}
}
public static class Factory {
private final Provider<Closables> clos;
private final Provider<HttpEvent> evt;
@Inject
Factory(Provider<Closables> clos, Provider<HttpEvent> evt) {
this.clos = clos;
this.evt = evt;
}
public CursorWriter create(DBCursor cursor, MapFilter filter) {
return new CursorWriter(cursor, clos.get(), evt.get(), Providers.of(filter));
}
public CursorWriter create(DBCursor cursor) {
return new CursorWriter(cursor, clos.get(), evt.get(), Providers.of(NO_FILTER));
}
}
}