package org.atlasapi.persistence.logging;
import static com.metabroadcast.common.persistence.mongo.MongoBuilders.where;
import static com.metabroadcast.common.persistence.mongo.MongoConstants.ID;
import static com.metabroadcast.common.persistence.mongo.MongoConstants.NATURAL;
import java.util.List;
import org.atlasapi.persistence.logging.AdapterLogEntry.ExceptionSummary;
import org.atlasapi.persistence.logging.AdapterLogEntry.Severity;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.metabroadcast.common.base.Maybe;
import com.metabroadcast.common.persistence.mongo.DatabasedMongo;
import com.metabroadcast.common.persistence.translator.TranslatorUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
public class MongoLoggingAdapter implements AdapterLog, LogReader {
private static final String DESCRIPTION_KEY = "description";
private static final String TIMESTAMP_KEY = "timestamp";
private static final String SOURCE_KEY = "source";
private static final String URI_KEY = "uri";
private static final String EXCEPTION_KEY = "exception";
private static final String CAUSE_TRACE = "trace";
private static final String CAUSE_MESSAGE = "message";
private static final String CAUSE_CLASS_NAME = "className";
private static final String CAUSE_PARENT = "cause";
private static final String SEVERITY_KEY = "severity";
private final DBCollection log;
public MongoLoggingAdapter(DatabasedMongo db) {
log = db.collection("logging");
}
@Override
public void record(AdapterLogEntry entry) {
log.insert(toDbObject(entry));
}
public Iterable<AdapterLogEntry> read() {
return Iterables.transform(log.find().sort(new BasicDBObject(NATURAL, -1)), new Function<DBObject, AdapterLogEntry>() {
@Override
public AdapterLogEntry apply(DBObject dbo) {
return fromDbObject(dbo);
}
});
}
private DBObject toDbObject(AdapterLogEntry entry) {
DBObject dbo = new BasicDBObject();
dbo.put(ID, entry.id());
dbo.put(DESCRIPTION_KEY, entry.description());
dbo.put(URI_KEY, entry.uri());
dbo.put(SEVERITY_KEY, entry.severity().toString());
dbo.put(SOURCE_KEY, entry.classNameOfSource());
TranslatorUtils.fromDateTime(dbo, TIMESTAMP_KEY, entry.timestamp());
if (entry.exceptionSummary() != null) {
dbo.put(EXCEPTION_KEY, toDbObject(entry.exceptionSummary()));
}
return dbo;
}
private DBObject toDbObject(ExceptionSummary summary) {
DBObject dbo = new BasicDBObject();
dbo.put(CAUSE_CLASS_NAME, summary.className());
dbo.put(CAUSE_MESSAGE, summary.message());
TranslatorUtils.fromList(dbo, summary.trace(), CAUSE_TRACE);
ExceptionSummary current = summary.cause();
DBObject parentDbo = dbo;
while (current != null) {
DBObject parent = toDbObject(current);
parentDbo.put(CAUSE_PARENT, parent);
current = current.cause();
parentDbo = parent;
}
return dbo;
}
private ExceptionSummary exceptionSummaryfromDbObject(DBObject dbo) {
List<String> trace = TranslatorUtils.toList(dbo, CAUSE_TRACE);
String message = (String) dbo.get(CAUSE_MESSAGE);
String className = (String) dbo.get(CAUSE_CLASS_NAME);
return new ExceptionSummary(className, message, trace, causeFrom(dbo));
}
private ExceptionSummary causeFrom(DBObject dbo) {
if (!dbo.containsField(CAUSE_PARENT)) {
return null;
}
return exceptionSummaryfromDbObject((DBObject) dbo.get(CAUSE_PARENT));
}
private AdapterLogEntry fromDbObject(DBObject dbo) {
Severity severity = Severity.valueOf((String) dbo.get(SEVERITY_KEY));
AdapterLogEntry logEntry = new AdapterLogEntry((String) dbo.get(ID), severity, TranslatorUtils.toDateTime(dbo, TIMESTAMP_KEY))
.withDescription((String) dbo.get(DESCRIPTION_KEY))
.withUri((String) dbo.get(URI_KEY))
.withSourceClassName((String) dbo.get(SOURCE_KEY));
if (dbo.containsField(EXCEPTION_KEY)) {
logEntry.withException(exceptionSummaryfromDbObject((DBObject) dbo.get(EXCEPTION_KEY)));
}
return logEntry;
}
@Override
public AdapterLogEntry requireById(String id) {
Maybe<DBObject> found = Maybe.firstElementOrNothing(where().idEquals(id).find(log));
if (found.hasValue()) {
return fromDbObject(found.requireValue());
}
throw new EntryExpiredException(id);
}
}