Use the contents of this package for so-called operational transformations. This can be used to synchronize the states of a number of clients with a single server. The synchronization is performed asynchronously. The construction of the transformation function guarantees to lead to eventual consistency across clients and server. Read more about the general background of the algorithm on which this is based here.
To establish a server to which clients can connect, first decide how your state is encoded on which the operations will perform changes to transition from one state to the next. Then, design your operations class. The trickiest part comes next. You have to define a transformer that maps a pair of your operations to another pair of operations of the same type. The transformer has to implement the {@link com.sap.sailing.operationaltransformation.Transformer} interface, in particular the {@link com.sap.sailing.operationaltransformation.Transformer#transform} method. The transformation function assumes that both input operations have been applied to the same state, one on a client, the other one on the server. The resulting operation for the client applied on the client must lead to a state equal to the state reached on the server by applying the resulting operation for the server to the server's state.
Put formally, if t is a transformer, and
if we have s_c as the state on the client and s_s as the state
on the server, and c as the operation that was executed in state s_c on the
client, and s as the operation executed on the server in state s_s, then the
following condition must hold:
t.transform(c, s).getClientOp().applyTo(c.applyTo(s_c)).equals( t.transform(c, s).getServerOp().applyTo(s.applyTo(s_s)))
You can create servers and clients, e.g., as follows:
server = new {@link com.sap.runlet.operationaltransformation.PeerImpl PeerImpl}(
"Server", new MyTransformer(), /* initial state */ new MyStateType(...), /* server */ true);
client1 = new {@link com.sap.runlet.operationaltransformation.PeerImpl PeerImpl}("Client1", new MyTransformer(), server);
client2 = new {@link com.sap.runlet.operationaltransformation.PeerImpl PeerImpl}("Client2", new MyTransformer(), server);
After that, you can start sending operations to the clients using the
{@link com.sap.runlet.operationaltransformation.Peer#apply} method as follows:
client1.{@link com.sap.runlet.operationaltransformation.Peer#apply apply}(new MyOperationType(...));
client2.{@link com.sap.runlet.operationaltransformation.Peer#apply apply}(new MyOperationType(...));
...
and those changes will eventually get synchronized across all clients and the server. You can
obtain the current state of a peer using the {@link com.sap.runlet.operationaltransformation.Peer#getCurrentState}
operation.
Consider using {@link com.sap.sailing.operationaltransformation.OperationalTransformer} as the basis for your transformation
logic. It generically works with {@link com.sap.sailing.operationaltransformation.OperationWithTransformationSupport} if you
can afford to have your operation classes implement the transformation logic. The benefit of doing so is that adding more
operations requires you to consider the transformation logic.