package org.eclipse.ecf.tests.sync; import java.util.Random; import org.eclipse.ecf.sync.IModelChange; import org.eclipse.ecf.sync.IModelChangeMessage; import org.eclipse.ecf.sync.IModelSynchronizationStrategy; import org.eclipse.ecf.sync.ModelUpdateException; import org.eclipse.ecf.sync.SerializationException; import org.eclipse.ecf.sync.doc.DocumentChangeMessage; import org.eclipse.ecf.sync.doc.IDocumentChange; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; public class SharedDocClient extends Thread { private String name; private IDocument document; private SimpleQueue localQueue; private SimpleQueue otherQueue; private IModelSynchronizationStrategy syncStrategy; private Random random = new Random(); public SharedDocClient(String name, IModelSynchronizationStrategy syncStrategy, String startText) { this.name = name; this.syncStrategy = syncStrategy; this.document = new Document(startText); this.localQueue = new SimpleQueue(); } public void start() { Thread localThread = new Thread(new Runnable() { public void run() { while (!localQueue.isStopped()) { sleep(500, 2000); localQueue.enqueue(new Runnable() { public void run() { processLocalChange(getLocalDocumentChange()); } }); } } }); localThread.setDaemon(true); localThread.start(); super.start(); } public SimpleQueue getQueue() { return this.localQueue; } public void setOtherQueue(SimpleQueue otherQueue) { this.otherQueue = otherQueue; } public String getDocumentText() { return document.get(); } private void sleep(int minimum, int max) { try { Thread.sleep(minimum + random.nextInt(max - minimum)); } catch (InterruptedException e) { // return } } public void run() { while (true) { Object o = localQueue.dequeue(); if (o == null) return; if (o instanceof Runnable) ((Runnable) o).run(); if (o instanceof byte[]) { processRemoteMessage((byte[]) o); } } } private void processLocalChange(IDocumentChange localChange) { if (localChange != null) { synchronized (this.getClass()) { applyChangeToLocalDocument(true, localChange); // Then register with local synchronizer IModelChangeMessage[] changeMessages = syncStrategy .registerLocalChange(localChange); // Then 'send' to other deliverChangeToOther(changeMessages); } } } private void applyChangeToLocalDocument(boolean local, IDocumentChange change) { System.out.println(name + ";doc=" + document.get()); System.out.println(name + (local ? ";localChange" : ";remoteChange") + ";" + change); try { change.applyToModel(document); } catch (ModelUpdateException e) { e.printStackTrace(); } System.out.println(name + ";doc=" + document.get()); } private void processRemoteMessage(byte[] msg) { if (msg != null) { try { synchronized (this.getClass()) { IModelChange change = syncStrategy.deserializeRemoteChange(msg); System.out.println(name + ";received="+change); IDocumentChange[] documentChanges = (IDocumentChange[]) syncStrategy .transformRemoteChange(change); for (int i = 0; i < documentChanges.length; i++) { applyChangeToLocalDocument(false, documentChanges[i]); } } } catch (SerializationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void deliverChangeToOther(IModelChangeMessage[] changeMessages) { for (int i = 0; i < changeMessages.length; i++) { try { System.out.println(name + ";sending=" + changeMessages[i]); otherQueue.enqueue(changeMessages[i].serialize()); } catch (SerializationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private IDocumentChange getLocalDocumentChange() { final int offset = random.nextInt(document.getLength()); final int length = random.nextInt(2); final String text = (random.nextInt(2) == 0) ? "" : ">"; return new DocumentChangeMessage(offset, length, text); } public void close() { localQueue.close(); } }