boolean checkConditions) {
T oldDoc = readDocument(collection, update.getId());
if (oldDoc == null) {
if (!update.isNew() || !allowCreate) {
throw new MicroKernelException("Document does not exist: " + update.getId());
}
T doc = collection.newDocument(this);
if (checkConditions && !UpdateUtils.checkConditions(doc, update)) {
return null;
}
update.increment(MODCOUNT, 1);
UpdateUtils.applyChanges(doc, update, comparator);
doc.seal();
insertDocument(collection, doc);
} else {
T doc = applyChanges(collection, oldDoc, update, checkConditions);
if (doc == null) {
return null;
}
int retries = 5; // TODO
boolean success = false;
while (!success && retries > 0) {
success = updateDocument(collection, doc, (Long) oldDoc.get(MODCOUNT));
if (!success) {
// retry with a fresh document
retries -= 1;
oldDoc = readDocument(collection, update.getId());
doc = applyChanges(collection, oldDoc, update, checkConditions);
if (doc == null) {
return null;
}
}
}
if (!success) {
throw new MicroKernelException("failed update (race?)");
}
}
return oldDoc;
}