On Tue, Dec 1, 2009 at 6:42 AM, Daniel Paull <[email protected]> wrote: > > The example provided by the OP is perfectly valid and will happen in > reality, especially in high latency conditions or when users can work > off line. > > The whole point of transforming one operation past the other is to > account for the way they interfere with each other. In the case in > question, both operations try to delete the same characters. The > inclusion transform accounts for this by detecting the overlapping > range of delete characters and will make the transformed operation > delete no characters. > > It should be noted that the OT Functions shown on the Wikipedia page > are vastly simplified compared to any serious OT implementation as > they only deal with single character inserts (and does not tackle > deletes at all!). Once you start to deal with ranges, the way inserts > and deletes interact gets quite complex. > > BTW, I find it very strange that the API has functions like > deleteCharacters("15"). I would have expected something like > deleteCharacters( int i1, int i2 ) where [i1, i2) defines a half open > interval of characters to be deleted.
All the individual ops are applied to a document from beginning to end, that is, the individual ops are listed in ascending order of the items in a document to which they apply. Which is why there is a retain(itemCount) operation. -joe -- Joe Gregorio Developer Advocate, Google Wave > > Cheers, > > Dan > > > On Dec 1, 6:36 pm, Brett Morgan <[email protected]> wrote: >> All, >> >> I've been thinking some more about this code, and I've realised that it >> probably should have thrown an exception when I applied the second edit >> against the untransformed intermediate document. The code is faced with the >> fact that the current document has "16", while the inbound edit's delete has >> "15" in it, and yet it still composes. I can see in >> Composer.CharactersPostTaget#deleteCharacters(String) where it should error >> out, but it doesn't compare the inbound characters to be deleted against the >> characters in the document. >> >> I understand this shouldn't be a problem in proper usage of Composer, but >> given the fact that there are people who aren't aware of the preconditions >> now attempting to integrate this code, maybe we should increase the >> defensive protections in this code base. Or is the run time cost of these >> protections in the inner code loops too high? >> >> brett >> >> On Mon, Nov 30, 2009 at 7:10 PM, Brett Morgan <[email protected]>wrote: >> >> >> >> >> >> > Jelke, >> >> > Here's my attempt at implementing your situation using the base wave >> > primitives - BufferedDocOp, Composer and Transformer: >> >> > public class Main { >> >> > public static void main(String[] args) throws OperationException { >> > // A server document. It contains "15" >> > final BufferedDocOp serverInitial = new >> > DocOpBuilder().characters("15").build(); >> > dump("server initial state", serverInitial); >> >> > // First client submits an edit against "15", replacing it with >> > "16" >> > final BufferedDocOp client1edit = new >> > DocOpBuilder().deleteCharacters("15").characters("16").build(); >> > dump("client 1's edit", client1edit); >> >> > // As this is the first edit against "15" the server has seen, it >> > will >> > // compose without issue >> > final BufferedDocOp serverIntermediate = >> > Composer.compose(serverInitial, client1edit); >> > dump("server intermediate state", serverIntermediate); >> >> > // Second client submits an edit against "15", replacing it with >> > "17" >> > final BufferedDocOp client2edit = new >> > DocOpBuilder().deleteCharacters("15").characters("17").build(); >> >> > // Composing directly, without transformation >> > BufferedDocOp untransformedServerState = >> > Composer.compose(serverIntermediate, client2edit); >> > dump("untransformed server state", untransformedServerState); >> >> > // Transforming the server history stack (which contains >> > client1edit) against the new edit >> > final OperationPair<BufferedDocOp> transformed = >> > Transformer.transform(client2edit, client1edit); >> > dump("transformed client state", transformed.clientOp()); >> > dump("transformed server state", transformed.serverOp()); >> >> > final BufferedDocOp serverFinal = >> > Composer.compose(serverIntermediate, transformed.clientOp()); >> > dump("transformed + composed server final state", serverFinal); >> >> > } >> >> > private static void dump(String context, BufferedDocOp op) { >> > System.out.println(context + ": " + DocOpUtil.toConciseString(op)); >> > } >> >> > } >> >> > Here is the resulting output: >> >> > server initial state: ++"15"; >> > client 1's edit: --"15"; ++"16"; >> > server intermediate state: ++"16"; >> > untransformed server state: ++"17"; >> > transformed client state: ++"17"; __2; >> > transformed server state: __2; ++"16"; >> > transformed + composed server final state: ++"1716"; >> >> > Transforming the second edit against the history stack is required so that >> > the deletes of the two deletes are merged. >> >> > hth, >> >> > brett >> >> > On Mon, Nov 30, 2009 at 12:05 AM, Jelke J. van Hoorn >> > <[email protected]>wrote: >> >> >> Hi, >> >> >> I was looking the "under the hood" vidieo of Google IO 2009. And I'm >> >> wondering what happens in the following situation: >> >> >> On the server a piece of text is lets say "15" and two clients alter >> >> the same piece in "16" and "17" respectively. >> >> What would be the outcome of the transforms? There is no unambigeous >> >> way to cope with this edit I think. >> >> >> Grtz Jelke >> >> >> -- >> >> >> You received this message because you are subscribed to the Google Groups >> >> "Wave Protocol" group. >> >> To post to this group, send email to [email protected]. >> >> To unsubscribe from this group, send email to >> >> [email protected]<wave-protocol%2bunsubscr...@goog >> >> legroups.com> >> >> . >> >> For more options, visit this group at >> >>http://groups.google.com/group/wave-protocol?hl=en. >> >> > -- >> > Brett Morganhttp://domesticmouse.livejournal.com/ >> >> -- >> Brett Morganhttp://domesticmouse.livejournal.com/ > > -- > > You received this message because you are subscribed to the Google Groups > "Wave Protocol" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/wave-protocol?hl=en. > > > -- You received this message because you are subscribed to the Google Groups "Wave Protocol" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/wave-protocol?hl=en.
