changeset 104:a2089a730a2e

change Translater class to interface.
author kent
date Sat, 22 Dec 2007 21:10:46 +0900
parents dca742322984
children 6c209de0dd99
files src/sample/merge/Translater.java src/sample/merge/TranslaterImp0.java src/sample/merge/TranslaterImp1.java
diffstat 3 files changed, 347 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/src/sample/merge/Translater.java	Sat Dec 22 19:05:12 2007 +0900
+++ b/src/sample/merge/Translater.java	Sat Dec 22 21:10:46 2007 +0900
@@ -1,169 +1,33 @@
 package sample.merge;
 
-import java.util.LinkedList;
-
 import remoteeditor.command.REPCommand;
-import remoteeditor.network.REP;
 
-public class Translater {
-	//List <REPCommand> userList;
-	//List <REPCommand> tokenList;
-	private LinkedList<REPCommand> cmdList;
-	public int eid;
-	
-	public Translater(int _eid){
-		eid = _eid;
-		cmdList = new LinkedList<REPCommand>();
-	}
+public interface Translater {
 
 	/**
-	 * Translate cmd When the editor send REPCommand.
-	 * but now, Only adding cmd to the queue is available.
-	 * @param cmd
-	 * @return translated command.
+	 * Translate command When the editor send REPCommand to remote editor.
+	 * @param command which the editor want to send.
+	 * @return translated command which should be sent by the editor.
 	 */
-	public REPCommand transSendCmd(REPCommand cmd){
-		cmdList.add(cmd);
-		return cmd;
-	}
+	abstract public REPCommand transSendCmd(REPCommand cmd);
+
 	/**
-	 * Dequeue command cmd that was returned.
-	 * @param cmd
+	 * Inform translater about that the editor receive own command which it sent.
+	 * but in this case, you can use also transReceiveCmd()
+	 * @param command which the editor sent.
 	 */
-	public void catchOwnCommand(REPCommand cmd){
-		// ringである以上、戻ってきたコマンドは確実にキューの先頭にある事を期待している
-		REPCommand cmd0 = cmdList.poll();
-		assert cmd.eid==eid;
-		assert cmd0.seq!=cmd.seq;
-		// とりあえず今のところは何もしない事になっている
-	}
+	abstract public REPCommand[] catchOwnCommand(REPCommand cmd);
+	
 	/**
 	 * Translate Command cmd that was received from SeMa.
 	 * @param cmd the command to be translated.
-	 * @return translated commannd.
+	 * @return translated command.
 	 */
-	public REPCommand transReceiveCmd(REPCommand cmd){
-		if (cmd.eid==eid){
-			catchOwnCommand(cmd);
-			return null;
-		}
-		// 拡張for構文、順序は保証されるの? 保証されないとダメ。
-		for(REPCommand cmd0: cmdList){
-			if (cmd0.lineno>cmd.lineno) continue;
-			else if (cmd0.lineno==cmd.lineno){
-				// 既に送ったCommandと行番号が重なる限り、繰り返し変換する
-				cmd = translate(cmd,  cmd0);
-			}
-			// ずれたlinenoを合わせる
-			else if (cmd0.cmd==REP.REPCMD_INSERT) cmd.lineno++;
-			else if (cmd0.cmd==REP.REPCMD_DELETE) cmd.lineno--;
-		}
-		return cmd;
-	}
-
-	/*
-	 * 
-	 *  比較時に行番号が重なったときの処理は以下の表。
-	 *  なるべくテキストが残るようにしている。
-	 *  0   -- なにもしない
-	 *  +1  -- 行番号を +1
-	 *  INS -- コマンド id を 'REPCMD_INSERT' にする。
-	 *  NOP -- コマンドをNOP(何もしない)にする。
-	 *  ?*  -- TOKENがMasterを通っていなければ 
-	 *               REMOTE
-	 *       |  i  |  r  |  d
-	 *    ---|------------------
-	 *  U  i | +1* | +1  | +1
-	 *  S ---|------------------
-	 *  E  r |  0  | NOP*| NOP    
-	 *  R ---|------------------
-	 *     d |  0  | INS | NOP
-	 *
-	 * 
-	 */
-	private REPCommand translate(REPCommand Rcmd, REPCommand Lcmd){
-		assert Rcmd.lineno==Lcmd.lineno;
-		int Lird = Lcmd.cmd;
-		int Rird = Rcmd.cmd;
+	abstract public REPCommand[] transReceiveCmd(REPCommand cmd);
 
-		if (Lird==REP.REPCMD_INSERT){
-			if (Rird==REP.REPCMD_INSERT){
-				if (!Rcmd.throughMaster) Rcmd.lineno++;
-			}else if (Rird==REP.REPCMD_REPLACE){
-				Rcmd.lineno++;
-			}else if (Rird==REP.REPCMD_DELETE){
-				Rcmd.lineno++;
-			}
-		}else if (Lird==REP.REPCMD_REPLACE){
-			if (Rird==REP.REPCMD_INSERT){
-			}else if (Rird==REP.REPCMD_REPLACE){
-				if (!Rcmd.throughMaster) Rcmd.cmd=REP.REPCMD_NOP;
-			}else if (Rird==REP.REPCMD_DELETE){
-				Rcmd.cmd = REP.REPCMD_NOP;
-			}
-		}else if (Lird==REP.REPCMD_DELETE){
-			if (Rird==REP.REPCMD_INSERT){
-			}else if (Rird==REP.REPCMD_REPLACE){
-				Rcmd.cmd = REP.REPCMD_INSERT;
-			}else if (Rird==REP.REPCMD_DELETE){
-				Rcmd.cmd = REP.REPCMD_NOP;
-			}
-		}
-
-		return Rcmd;
-
-/*
-		// あとで整形しよう
-		if (Lcmd.cmd==REP.REPCMD_INSERT && Rcmd.cmd==REP.REPCMD_INSERT){
-			if (!Rcmd.throughMaster) Rcmd.lineno++;
-		}
-		if (Lcmd.cmd==REP.REPCMD_DELETE && Rcmd.cmd==REP.REPCMD_DELETE){
-			Rcmd.cmd = REP.REPCMD_NOP;
-		}
-		if (Lcmd.cmd==REP.REPCMD_REPLACE && Rcmd.cmd==REP.REPCMD_REPLACE){
-			if (!Rcmd.throughMaster) Rcmd.cmd=REP.REPCMD_NOP;
-		}
-
-		if (Lcmd.cmd==REP.REPCMD_INSERT && Rcmd.cmd==REP.REPCMD_DELETE){
-			Rcmd.lineno++;
-		}
-		if (Lcmd.cmd==REP.REPCMD_DELETE && Rcmd.cmd==REP.REPCMD_INSERT){
-		}
-
-		if (Lcmd.cmd==REP.REPCMD_REPLACE && Rcmd.cmd==REP.REPCMD_DELETE){
-			Rcmd.cmd = REP.REPCMD_NOP;
-		}
-		if (Lcmd.cmd==REP.REPCMD_DELETE && Rcmd.cmd==REP.REPCMD_REPLACE){
-			Rcmd.cmd = REP.REPCMD_INSERT;
-		}
-
-		if (Lcmd.cmd==REP.REPCMD_INSERT && Rcmd.cmd==REP.REPCMD_REPLACE){
-			Rcmd.lineno++;
-		}
-		if (Lcmd.cmd==REP.REPCMD_REPLACE && Rcmd.cmd==REP.REPCMD_INSERT){
-		}
-		return Rcmd;
-*/
-	}
-
-	public void setEid(int _eid){
-		eid = _eid;
-	}
-
-	/*
-	  old version ( not ring type)
-	  0  -- なにもしない
-	  +1 -- 行番号を +1
-	  i  -- コマンド id を 'i' にする。
-	  X  -- コマンドを削除(無視に)する。
-
-	              USER
-	       |  i   |  r   |  d
-	    ---|--------------------
-	  T  i | 0\+1 | 0\+1 | 0\+1
-	  O ---|--------------------
-	  K  r | +1\0 | 0\X  | i\X
-	  E ---|--------------------
-	  N  d | +1\0 | X\i  | X\X
-	*/
+	/**
+	 * set the editor's id.
+	 * @param editor's id.
+	 */
+	abstract public void setEid(int _eid);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sample/merge/TranslaterImp0.java	Sat Dec 22 21:10:46 2007 +0900
@@ -0,0 +1,172 @@
+package sample.merge;
+
+import java.util.LinkedList;
+
+import remoteeditor.command.REPCommand;
+import remoteeditor.network.REP;
+
+public class TranslaterImp0 implements Translater{
+	//List <REPCommand> userList;
+	//List <REPCommand> tokenList;
+	private LinkedList<REPCommand> cmdList;
+	public int eid;
+	
+	public TranslaterImp0(int _eid){
+		eid = _eid;
+		cmdList = new LinkedList<REPCommand>();
+	}
+
+	/**
+	 * Translate cmd When the editor send REPCommand.
+	 * but now, Only adding cmd to the queue is available.
+	 * @param cmd
+	 * @return translated command.
+	 */
+	public REPCommand transSendCmd(REPCommand cmd){
+		cmdList.add(cmd);
+		return cmd;
+	}
+	/**
+	 * Dequeue command cmd that was returned.
+	 * @param cmd
+	 */
+	public REPCommand[] catchOwnCommand(REPCommand cmd){
+		// ring縺ァ縺ゅk莉・荳翫∵綾縺」縺ヲ縺阪◆繧ウ繝槭Φ繝峨ッ遒コ螳溘↓繧ュ繝・繝シ縺ョ蜈磯ュ縺ォ縺ゅk莠九r譛溷セ縺励※縺繧
+		REPCommand cmd0 = cmdList.poll();
+		assert cmd.eid==eid;
+		assert cmd0.seq!=cmd.seq;
+		// 縺ィ繧翫≠縺医★莉翫ョ縺ィ縺薙m縺ッ菴輔b縺励↑縺莠九↓縺ェ縺」縺ヲ縺繧
+		return null;
+	}
+	/**
+	 * Translate Command cmd that was received from SeMa.
+	 * @param cmd the command to be translated.
+	 * @return translated commannd.
+	 */
+	public REPCommand[] transReceiveCmd(REPCommand cmd){
+		REPCommand cmds[];
+		if (cmd.eid==eid){
+			return catchOwnCommand(cmd);
+		}
+		// 諡。蠑オfor讒区枚縲鬆蠎上ッ菫晁ィシ縺輔l繧九ョ? 菫晁ィシ縺輔l縺ェ縺縺ィ繝繝。縲
+		for(REPCommand cmd0: cmdList){
+			if (cmd0.lineno>cmd.lineno) continue;
+			else if (cmd0.lineno==cmd.lineno){
+				// 譌「縺ォ騾√▲縺櫃ommand縺ィ陦檎分蜿キ縺碁阪↑繧矩剞繧翫∫ケー繧願ソ斐@螟画鋤縺吶k
+				cmd = translate(cmd,  cmd0);
+			}
+			// 縺壹l縺殕ineno繧貞粋繧上○繧
+			else if (cmd0.cmd==REP.REPCMD_INSERT) cmd.lineno++;
+			else if (cmd0.cmd==REP.REPCMD_DELETE) cmd.lineno--;
+		}
+		cmds = new REPCommand[1];
+		cmds[0] = cmd;
+		return cmds;
+	}
+
+	/*
+	 * 
+	 *  豈碑シ譎ゅ↓陦檎分蜿キ縺碁阪↑縺」縺溘→縺阪ョ蜃ヲ逅縺ッ莉・荳九ョ陦ィ縲
+	 *  縺ェ繧九∋縺上ユ繧ュ繧ケ繝医′谿九k繧医≧縺ォ縺励※縺繧九
+	 *  0   -- 縺ェ縺ォ繧ゅ@縺ェ縺
+	 *  +1  -- 陦檎分蜿キ繧 +1
+	 *  INS -- 繧ウ繝槭Φ繝 id 繧 'REPCMD_INSERT' 縺ォ縺吶k縲
+	 *  NOP -- 繧ウ繝槭Φ繝峨rNOP(菴輔b縺励↑縺)縺ォ縺吶k縲
+	 *  ?*  -- TOKEN縺勲aster繧帝壹▲縺ヲ縺縺ェ縺代l縺ー 
+	 *               REMOTE
+	 *       |  i  |  r  |  d
+	 *    ---|------------------
+	 *  U  i | +1* | +1  | +1
+	 *  S ---|------------------
+	 *  E  r |  0  | NOP*| NOP    
+	 *  R ---|------------------
+	 *     d |  0  | INS | NOP
+	 *
+	 * 
+	 */
+	private REPCommand translate(REPCommand Rcmd, REPCommand Lcmd){
+		assert Rcmd.lineno==Lcmd.lineno;
+		int Lird = Lcmd.cmd;
+		int Rird = Rcmd.cmd;
+
+		if (Lird==REP.REPCMD_INSERT){
+			if (Rird==REP.REPCMD_INSERT){
+				if (!Rcmd.throughMaster) Rcmd.lineno++;
+			}else if (Rird==REP.REPCMD_REPLACE){
+				Rcmd.lineno++;
+			}else if (Rird==REP.REPCMD_DELETE){
+				Rcmd.lineno++;
+			}
+		}else if (Lird==REP.REPCMD_REPLACE){
+			if (Rird==REP.REPCMD_INSERT){
+			}else if (Rird==REP.REPCMD_REPLACE){
+				if (!Rcmd.throughMaster) Rcmd.cmd=REP.REPCMD_NOP;
+			}else if (Rird==REP.REPCMD_DELETE){
+				Rcmd.cmd = REP.REPCMD_NOP;
+			}
+		}else if (Lird==REP.REPCMD_DELETE){
+			if (Rird==REP.REPCMD_INSERT){
+			}else if (Rird==REP.REPCMD_REPLACE){
+				Rcmd.cmd = REP.REPCMD_INSERT;
+			}else if (Rird==REP.REPCMD_DELETE){
+				Rcmd.cmd = REP.REPCMD_NOP;
+			}
+		}
+
+		return Rcmd;
+
+/*
+		// 縺ゅ→縺ァ謨エ蠖「縺励h縺
+		if (Lcmd.cmd==REP.REPCMD_INSERT && Rcmd.cmd==REP.REPCMD_INSERT){
+			if (!Rcmd.throughMaster) Rcmd.lineno++;
+		}
+		if (Lcmd.cmd==REP.REPCMD_DELETE && Rcmd.cmd==REP.REPCMD_DELETE){
+			Rcmd.cmd = REP.REPCMD_NOP;
+		}
+		if (Lcmd.cmd==REP.REPCMD_REPLACE && Rcmd.cmd==REP.REPCMD_REPLACE){
+			if (!Rcmd.throughMaster) Rcmd.cmd=REP.REPCMD_NOP;
+		}
+
+		if (Lcmd.cmd==REP.REPCMD_INSERT && Rcmd.cmd==REP.REPCMD_DELETE){
+			Rcmd.lineno++;
+		}
+		if (Lcmd.cmd==REP.REPCMD_DELETE && Rcmd.cmd==REP.REPCMD_INSERT){
+		}
+
+		if (Lcmd.cmd==REP.REPCMD_REPLACE && Rcmd.cmd==REP.REPCMD_DELETE){
+			Rcmd.cmd = REP.REPCMD_NOP;
+		}
+		if (Lcmd.cmd==REP.REPCMD_DELETE && Rcmd.cmd==REP.REPCMD_REPLACE){
+			Rcmd.cmd = REP.REPCMD_INSERT;
+		}
+
+		if (Lcmd.cmd==REP.REPCMD_INSERT && Rcmd.cmd==REP.REPCMD_REPLACE){
+			Rcmd.lineno++;
+		}
+		if (Lcmd.cmd==REP.REPCMD_REPLACE && Rcmd.cmd==REP.REPCMD_INSERT){
+		}
+		return Rcmd;
+*/
+	}
+
+	public void setEid(int _eid){
+		eid = _eid;
+	}
+
+	/*
+	  old version ( not ring type)
+	  0  -- 縺ェ縺ォ繧ゅ@縺ェ縺
+	  +1 -- 陦檎分蜿キ繧 +1
+	  i  -- 繧ウ繝槭Φ繝 id 繧 'i' 縺ォ縺吶k縲
+	  X  -- 繧ウ繝槭Φ繝峨r蜑企勁(辟。隕悶↓)縺吶k縲
+
+	              USER
+	       |  i   |  r   |  d
+	    ---|--------------------
+	  T  i | 0ツ・+1 | 0ツ・+1 | 0ツ・+1
+	  O ---|--------------------
+	  K  r | +1ツ・0 | 0ツ・X  | iツ・X
+	  E ---|--------------------
+	  N  d | +1ツ・0 | Xツ・i  | Xツ・X
+	*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sample/merge/TranslaterImp1.java	Sat Dec 22 21:10:46 2007 +0900
@@ -0,0 +1,157 @@
+package sample.merge;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Stack;
+
+import remoteeditor.command.REPCommand;
+import remoteeditor.network.REP;
+
+public class TranslaterImp1 implements Translater{
+	//List <REPCommand> userList;
+	//List <REPCommand> tokenList;
+	private LinkedList<REPCommand> sentCmds;
+	//private LinkedList<REPCommand> unMergedCmds;
+	private Stack<REPCommand> unMergedCmds;
+	public int eid;
+
+	public TranslaterImp1(int _eid){
+		eid = _eid;
+		sentCmds = new LinkedList<REPCommand>();
+		unMergedCmds = new Stack<REPCommand>();
+	}
+
+	/**
+	 * Translate cmd When the editor send REPCommand.
+	 * but now, Only adding cmd to the queue is available.
+	 * @param cmd
+	 * @return translated command.
+	 */
+	public REPCommand transSendCmd(REPCommand cmd){
+		sentCmds.add(cmd);
+		unMergedCmds.push(cmd);
+		return cmd;
+	}
+	/**
+	 * Dequeue command cmd that was returned.
+	 * @param cmd
+	 */
+	public REPCommand[] catchOwnCommand(REPCommand cmd){
+		ArrayList<REPCommand> returnCmds = new ArrayList<REPCommand>();
+		ArrayList<REPCommand> cmds = new ArrayList<REPCommand>();
+		// ring縺ァ縺ゅk莉・荳翫∵綾縺」縺ヲ縺阪◆繧ウ繝槭Φ繝峨ッ遒コ螳溘↓繧ュ繝・繝シsentCmds縺ョ蜈磯ュ縺ォ縺ゅk莠九r譛溷セ縺励※縺繧
+		//REPCommand cmd0 = sentCmds.poll();
+		//assert cmd0.seq!=cmd.seq;
+		assert cmd.eid==eid;
+
+		/* 繧ケ繧ソ繝繧ッ縺九i蜈ィ驛ィ蜿悶j蜃コ縺励※繝槭シ繧ク縺吶k 縺セ縺繝槭シ繧ク縺ァ縺阪↑縺繧縺、縺ッ縺セ縺溘せ繧ソ繝繧ッ縺ク謌サ縺  */
+		while ( !unMergedCmds.isEmpty() ){
+			REPCommand cmd0 = unMergedCmds.pop();
+			returnCmds.add( createUndo(cmd0) );
+			cmds.add(cmd0);
+		}
+		//if (cmds.size()==0) return null;
+		returnCmds.addAll( sortCmds(cmds) );
+		return returnCmds.toArray(new REPCommand[0]);
+	}
+
+	private REPCommand createUndo(REPCommand cmd){
+		//REPCommand retCmd = cmd.clone();
+		REPCommand retCmd = new REPCommand(cmd.cmd, cmd.sid, cmd.eid, cmd.seq, cmd.lineno, cmd.string.length(), cmd.string);
+
+		if (cmd.cmd==REP.REPCMD_INSERT) retCmd.cmd=REP.REPCMD_DELETE;
+		else if (cmd.cmd==REP.REPCMD_DELETE) retCmd.cmd=REP.REPCMD_INSERT;
+		return retCmd;
+	}
+
+	private ArrayList<REPCommand> sortCmds(ArrayList<REPCommand> cmds) {
+		ArrayList<REPCommand> sortedCmds = new ArrayList<REPCommand>();
+		REPCommand cmd0;
+		int prevEid=0;
+		int i,j;
+
+		/* EID,SEQ縺ョ菴弱>鬆縺ォ縲∝推EID豈弱↓1蛟九□縺鷹∈謚槭@cmds縺ォ譬シ邏  */
+		while ( null != (cmd0=getPrecedence(cmds, prevEid+1)) ){
+			sortedCmds.add(cmd0);
+			cmds.remove(cmd0);
+			prevEid = cmd0.eid;
+		}
+
+		/* lineno 縺ョ螟ァ縺阪>鬆縺ォ繧ス繝シ繝  */
+		for (i=0; i<sortedCmds.size(); i++){
+			int k=i;
+			for (j=i+1; j<sortedCmds.size(); j++){
+				if ( sortedCmds.get(k).lineno > sortedCmds.get(j).lineno ) continue;
+				else if ( sortedCmds.get(k).lineno < sortedCmds.get(j).lineno 
+						|| sortedCmds.get(k).eid > sortedCmds.get(j).eid )
+					   /* delete縺ィinsert縺ョ蝣エ蜷医↑縺ゥ縺ッeid縺ォ繧医i縺壹鬆蠎上r蠑キ蛻カ縺吶k蠢隕√′縺ゅk縺九b  */
+					k=j;
+			}
+			cmd0 = sortedCmds.get(i);
+			sortedCmds.set(i, sortedCmds.get(k));
+			sortedCmds.set(k, cmd0);
+		}
+		return sortedCmds;
+	}
+
+	/* search cmd. ordering by  min EID that is lower lowEid and min SEQ.  */
+	private REPCommand getPrecedence(ArrayList<REPCommand> cmds, int lowEid) {
+		int cEid, cSeq;
+		cEid=cSeq=Integer.MAX_VALUE;
+		REPCommand  ret=null;
+		for (int i=0; i<cmds.size(); i++){
+			REPCommand tmp = cmds.get(i);
+			if ( tmp.eid<lowEid ) continue;
+			else if ( tmp.eid>cEid ) continue;
+			else if ( tmp.eid==cEid ) {
+				if ( tmp.seq>cSeq ) continue;
+				cSeq=tmp.seq;
+				ret = tmp;
+			} else { /* tmp.eid<cEid */
+				cEid = tmp.eid;
+				cSeq = tmp.seq;
+				ret = tmp;
+			}
+			//if ( cEid>cmds.get(i) && cmds.get(i)>lowEid )
+		}
+		return ret;
+	}
+
+	/**
+	 * Translate Command cmd that was received from SeMa.
+	 * @param cmd the command to be translated.
+	 * @return translated commannd.
+	 */
+	public REPCommand[] transReceiveCmd(REPCommand cmd){
+		int i=0;
+		REPCommand cmds[];
+		if (cmd.eid==eid){
+			return catchOwnCommand(cmd);
+		}
+
+		for (REPCommand cmd0 : unMergedCmds){
+			if (cmd0.eid==cmd.eid) i++;
+		}
+
+		if ( sentCmds.size()<i ){
+			cmds = new REPCommand[2];
+			String str = "NO OPERATION";
+			cmds[0] = new REPCommand(REP.REPCMD_NOP, 0, eid, 0, 0, str.length(), str);
+			cmds[1] = cmd;
+			//unMergedCmds.push(cmds[0]);
+			unMergedCmds.push(cmd);
+			sentCmds.add(cmds[0]);
+			return cmds;
+		}
+
+		unMergedCmds.push(cmd); /* but.. */
+		cmds = new REPCommand[1];
+		cmds[0] = cmd;
+		return cmds;
+	}
+
+	public void setEid(int _eid){
+		eid = _eid;
+	}
+}