Skip to main content
summaryrefslogtreecommitdiffstats
blob: 4ecdaac7bf74ef13cf12b264b5e3b8c418d96b5f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/****************************************************************************
 * Copyright (c) 2008 Mustafa K. Isik and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Mustafa K. Isik - initial API and implementation
 *****************************************************************************/

package org.eclipse.ecf.docshare.cola;

import org.eclipse.ecf.core.util.Trace;
import org.eclipse.ecf.internal.docshare.Activator;
import org.eclipse.ecf.internal.docshare.DocshareDebugOptions;

public class ColaInsertion implements TransformationStrategy {

	private static final long serialVersionUID = 5192625383622519749L;
	private static ColaInsertion INSTANCE;

	private ColaInsertion() {
		// default constructor is private to enforce singleton property via
		// static factory method
	}

	public static TransformationStrategy getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new ColaInsertion();
		}
		return INSTANCE;
	}

	/**
	 * Resolves two conflicting <code>ColaUpdateMessage</code>s by applying an appropriate operational transform.
	 * 
	 * If necessary, modifies <code>localAppliedMsg</code> as well to reflect knowledge of <code>remoteIncomingMsg</code> 
	 * in case more conflicting/further diverging remote messages arrive.  
	 * 
	 * @param remoteIncomingMsg message originating from remote site, generated on same document state as <code>localAppliedMsg</code>
	 * @param localAppliedMsg message already applied to local document, generation state corresponds to that of <code>remoteIncomingMsg</code>
	 * @param localMsgHighPrio determines insertion preference for same offsets, if true localAppliedMsg comes first
	 * @return operational transform of remote message, not conflicting with applied local message
	 */
	public ColaUpdateMessage getOperationalTransform(ColaUpdateMessage remoteIncomingMsg, ColaUpdateMessage localAppliedMsg, boolean localMsgHighPrio) {

		Trace.entering(Activator.PLUGIN_ID, DocshareDebugOptions.METHODS_ENTERING, this.getClass(), "getOperationalTransform", new Object[] {remoteIncomingMsg, localAppliedMsg, new Boolean(localMsgHighPrio)}); //$NON-NLS-1$

		ColaUpdateMessage remoteTransformedMsg = remoteIncomingMsg;

		if (localAppliedMsg.isInsertion()) {

			if (remoteTransformedMsg.getOffset() < localAppliedMsg.getOffset()) {
				//coopt(remote(low),local(high)) --> (remote(low),local(low + high))
				localAppliedMsg.setOffset(localAppliedMsg.getOffset() + remoteTransformedMsg.getOffset());
			} else if (remoteTransformedMsg.getOffset() == localAppliedMsg.getOffset()) {
				//coopt(remote(same),local(same))
				if (localMsgHighPrio) {
					//at owner --> (remote(high),local(same))
					remoteTransformedMsg.setOffset(remoteTransformedMsg.getOffset() + localAppliedMsg.getText().length());
				} else {
					//at participant --> (remote(same),local(high))
					localAppliedMsg.setOffset(localAppliedMsg.getOffset() + remoteTransformedMsg.getText().length());
				}
			} else if (remoteTransformedMsg.getOffset() > localAppliedMsg.getOffset()) {
				//coopt(remote(high),local(low)) --> (remote(low + high),local(low))
				remoteTransformedMsg.setOffset(remoteTransformedMsg.getOffset() + localAppliedMsg.getText().length());
			}
		}

		Trace.exiting(Activator.PLUGIN_ID, DocshareDebugOptions.METHODS_EXITING, this.getClass(), "getOperationalTransform", remoteTransformedMsg); //$NON-NLS-1$
		return remoteTransformedMsg;
	}
}

Back to the top