throw new BadSync("", entity.getId(), remoteOp.getAgentId());
}
boolean first = true;
boolean appliedRemoteOp = false;
OTOperation applyOver = remoteOp;
if (localOps.isEmpty()) {
createOperation(remoteOp).apply(entity);
return remoteOp;
}
else {
final LogQuery query = transactionLog.getEffectiveStateForRevision(remoteOp.getRevision() + 1);
entity.getState().syncStateFrom(query.getEffectiveState());
OTLogUtil.log("REWIND",
"<<FOR TRANSFORM OVER: " + remoteOp + ";rev=" + remoteOp.getRevision() + ">>",
"-",
engine.getName(),
remoteOp.getRevision() + 1,
"\"" + entity.getState().get() + "\"");
final OTOperation firstOp = localOps.get(0);
final List<OTOperation> remoteOps = transactionLog.getRemoteOpsSinceRevision(applyOver.getAgentId(), firstOp.getRevision());
if (!remoteOps.isEmpty()) {
OTOperation firstPrevRemoteOp = remoteOps.get(0);
while (firstPrevRemoteOp.getTransformedFrom() != null) {
firstPrevRemoteOp = firstPrevRemoteOp.getTransformedFrom().getRemoteOp();
}
final LogQuery query2 = transactionLog.getEffectiveStateForRevision(firstPrevRemoteOp.getRevision() + 1);
entity.getState().syncStateFrom(query2.getEffectiveState());
for (final OTOperation operation : query2.getLocalOpsNeedsMerge()) {
operation.apply(entity, true);
}
applyOver = translateFrom(remoteOp, remoteOps.get(remoteOps.size() - 1));
OTLogUtil.log("CTRNSFRM", "FOR: " + remoteOp + "->" + applyOver,
"-", engine.getName(), remoteOp.getRevision() + 1, "\"" + entity.getState().get() + "\"");
createOperation(applyOver).apply(entity);
return applyOver;
}
for (final OTOperation localOp : localOps) {
if (first) {
first = false;
if (applyOver.getRevisionHash().equals(localOp.getRevisionHash()) || localOp.isResolvedConflict()) {
applyOver = transform(applyOver, localOp);
}
else {
applyOver = transform(applyOver,
transform(localOp.getTransformedFrom().getLocalOp(),
localOp.getTransformedFrom().getRemoteOp()));
}
}
else {
final OTOperation ot = transform(localOp, applyOver, false);
final boolean changedLocally = !localOp.equals(ot);
if (changedLocally) {
localOp.removeFromCanonHistory();
entity.decrementRevisionCounter();
}
if (!appliedRemoteOp && changedLocally) {
applyOver.apply(entity);
appliedRemoteOp = true;
}
applyOver = transform(applyOver, ot);
ot.apply(entity, !changedLocally);
if (changedLocally) {
localOp.removeFromCanonHistory();
localOp.setOuterPath(ot);
}