changeset 324:e235998427a6 before-merge-fix

try to fix merger
author kono
date Sat, 11 Oct 2008 16:31:03 +0900
parents 1e605880d49e
children be0831086e63
files rep/Editor.java rep/EditorPlus.java rep/SessionManager.java rep/translater/Translate.java rep/translater/Translater.java rep/translater/TranslaterImp1.java rep/translator/Translate.java rep/translator/Translator.java rep/translator/TranslatorImpl.java
diffstat 9 files changed, 445 insertions(+), 440 deletions(-) [+]
line wrap: on
line diff
--- a/rep/Editor.java	Fri Oct 10 18:04:09 2008 +0900
+++ b/rep/Editor.java	Sat Oct 11 16:31:03 2008 +0900
@@ -5,11 +5,11 @@
 import rep.channel.REPSocketChannel;
 import rep.handler.PacketSet;
 import rep.optimizers.*;
-import rep.translater.TranslaterImp1;
+import rep.translator.TranslatorImpl;
 
 public class Editor extends Forwarder {
 
-	private TranslaterImp1 translater;
+	private TranslatorImpl translator;
 	private List<REPCommand> sentList = new LinkedList<REPCommand>();
 	// REPCommands we are going to send to the next editor
 	private REPCommandOptimizer optimizer;
@@ -21,7 +21,7 @@
 		super(manager);
 		this.manager = manager;
 		eid = editorNo;
-		translater = new TranslaterImp1(eid);
+		translator = new TranslatorImpl(eid);
 		if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ
 		else            optimizer = new NullOptimizer();         //なにもしないけどOptimizer.
 		
@@ -33,9 +33,9 @@
 		setHostAndPort(channel);
 	}
 
-	public void translate(Forwarder nextEditor, REPCommand command){
+	public void translate(Editor nextEditor, REPCommand command){
 		if(command.eid == nextEditor.getEID()){
-			if(checkReturnedCommand(command)){
+			if(nextEditor.checkReturnedCommand(command)){
 				// エディタからのコマンドが元のエディタに戻ってきた
 				// START_MERGE を送る
 				REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,"");
@@ -43,31 +43,30 @@
 				// Session Manager 側で、このeditorへの他のeditorからの
 				// 入力を止めて、merge にそなえる。merge は、eidtor 側から
 				// ACKが来てから始まる。
-				translater.startMerge(cmd);
+				translator.startMerge(cmd);
 				return;
 			} else assert(false);
 		} else if(command.eid == eid){
 				//エディタからの新たな編集コマンド
 				sentList.add(command);
 				assert(sentList.size()<limit);
-				translater.transSendCmd(command);
+				translator.transSendCmd(command);
 				nextEditor.send(command);
 				return;
 		}else if(command.eid == REP.MERGE_EID.id){
 			//マージコマンドが返ってきた
-			if(translater.checkMergeConflict(command)){
+			if(translator.checkMergeConflict(command)){
 				//マージ中にエディタからの割り込みがあった場合
-				if (optimizedSend(translater.getMergeAgain())) {
+				if (optimizedSend(translator.getMergeAgain())) {
+					endMerge();
 					return;
 				}
-			}
-			if(!isMerging()) {
+			} else
 				endMerge();
-			}
 		}else{
 			//他のエディタからの編集コマンド
 			if(!isMerging()) {
-				translater.transReceiveCmd(nextEditor,command);
+				translator.transReceiveCmd(nextEditor,command);
 				return;
 			}
 			manager.addWaitingCommand(new PacketSet(getChannel(), this, command));
@@ -76,11 +75,11 @@
 	}
 	
 	boolean merge(REPCommand command) {
-		REPCommand prev = translater.prev();
+		REPCommand prev = translator.prev();
 		if(prev==null) return false;
 		assert(prev.eid==command.eid);
 		//マージして送信
-		return translater.catchOwnCommand(this);
+		return translator.catchOwnCommand(this);
 	}
 
 	boolean checkReturnedCommand(REPCommand command) {
@@ -93,7 +92,7 @@
 				}
 				return true;
 			}else{
-				System.err.println("Editor.checkReturnedCommand() : command = " + command);
+				System.out.println("Editor.checkReturnedCommand() : command = " + command);
 				assert(false);
 			}
 		}
@@ -122,7 +121,7 @@
 	@Override
 	public void setEID(int eid) {
 		this.eid = eid;
-		translater.setEid(eid);
+		translator.setEid(eid);
 	}
 	
 	public String toString(){
@@ -130,14 +129,9 @@
 	}
 
 	public boolean isMerging() {
-		return translater.isMerging();
+		return translator.isMerging();
 	}
-	public boolean hasSession() {
-		return sid != -1;
-	}
-	public void setSID(int sessionID) {
-		sid   = sessionID;
-	}
+
 	
 	/**
 	 * Sent optimized merged command list
@@ -157,8 +151,10 @@
 	}
 
 	void endMerge() {
+		if(translator.isMerging()) return;
 		REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,eid,sid,seq(),0,"");
 		send(mergeEnd);
+		translator.endMerge();
 	}
 
 	@Override
@@ -171,14 +167,14 @@
 		case REPCMD_INSERT:
 		case REPCMD_NOP:
 		{
-			translate(next, receivedCommand);
+			translate((Editor)next, receivedCommand);
 			break;
 		}
 
 		case SMCMD_START_MERGE_ACK:
 		{
 			// マージの処理と次のエディタへコマンドを送信する処理
-			translater.mergeAck();
+			translator.mergeAck();
 			if (!merge(receivedCommand)) {
 				// nothing to do, send END_MERGE
 				endMerge();
--- a/rep/EditorPlus.java	Fri Oct 10 18:04:09 2008 +0900
+++ b/rep/EditorPlus.java	Sat Oct 11 16:31:03 2008 +0900
@@ -35,6 +35,10 @@
 	public int getSID() {
 		return sid;
 	}
+
+	public boolean hasSession() {
+		return sid != -1;
+	}
 	
 	public String toString(){
 		return ("Editor:" + eid);
--- a/rep/SessionManager.java	Fri Oct 10 18:04:09 2008 +0900
+++ b/rep/SessionManager.java	Sat Oct 11 16:31:03 2008 +0900
@@ -205,6 +205,7 @@
 		if (sessionManagerCommand(channel, receivedCommand)) return;
 		Session s = getSession(receivedCommand.sid);
 		Editor e = s.getEditor(channel);
+		// if(e==null) throw new IOException();
 		e.manage(receivedCommand);
 	}
 
@@ -547,9 +548,10 @@
 			System.out.println("SessionManager.selectSession():editor = " + editor);
 			return;
 		}
+		if (editor.hasSession()) return;
 		REPSocketChannel<REPCommand> channel = editor.getChannel();
 
-		System.out.println("SessionManager.session.hasOnwer="+session.hasOwner());
+		// System.out.println("SessionManager.session.hasOnwer="+session.hasOwner());
 		if(session.hasOwner()){
 			editor.setEID(session.newEid());
 			editor.setSID(sid);
@@ -611,7 +613,7 @@
 
 
 	public void addWriteQueue(PacketSet packetSet) {
-		writeQueue.add(packetSet);
+		writeQueue.addLast(packetSet);
 		assert(writeQueue.size()<packetLimit) ;
 	}
 
--- a/rep/translater/Translate.java	Fri Oct 10 18:04:09 2008 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-package rep.translater;
-
-import java.util.List;
-
-import rep.REPCommand;
-import rep.REP;
-
-public class Translate {
-	List <REPCommand> userList;
-	List <REPCommand> tokenList;
-	private boolean REP_IGNORE = true;
-	public int myeid;
-	
-	public Translate(){
-		
-	}
-	
-	//public Translate(List<REPCommand> userList, List<REPCommand> tokenList){
-	//	this.userList = userList;
-	//	this.tokenList = tokenList;
-		//merge();
-	//}
-
-
-
-	public Translate(List<REPCommand> userCmdList, List<REPCommand> tokenCmdList) {
-		this.userList = userCmdList;
-		this.tokenList = tokenCmdList;
-	}
-
-	public void addUserList(REPCommand usercmd){
-		userList.add(usercmd);
-	}
-	public void addTokenList(REPCommand tokencmd){
-		if(tokencmd.eid == myeid){
-			tokenList.clear();
-			userList.remove(0);
-		}else{
-			tokenList.add(tokencmd);
-		}
-	}
-	
-	void merge(){
-		REPCommand h_pricmd;
-		REPCommand l_pricmd;
-//		Iterator userListIterator = userList.iterator();
-//		while(userListIterator.hasNext()){
-		for(REPCommand userCmd:userList){
-			//Iterator tokenListIterator = tokenList.iterator();
-			//Rep_Cmd userCmd = (Rep_Cmd)userListIterator.next();
-			if(userCmd.stat) continue;     /* �폜�����(�\��)��REP�R�}���h�̔�r�͖��� */
-			//while(tokenListIterator.hasNext()){
-			for(REPCommand tokenCmd:tokenList){
-//				Rep_Cmd tokenCmd =(Rep_Cmd)tokenListIterator.next();
-				if(tokenCmd.eid == myeid) {
-					if(tokenCmd.seq == userCmd.seq){
-					tokenCmd.stat = REP_IGNORE;
-					userCmd.stat = REP_IGNORE;
-					}
-				}
-				if(tokenCmd.stat == REP_IGNORE) continue;     /* �폜�����(�\��)��REP�R�}���h�̔�r�͖��� */
-				if(userCmd.stat == REP_IGNORE) break;
-				if(userCmd.lineno < tokenCmd.lineno) {     /* UsersLineNumber < TokensLineNumber */
-					if(userCmd.cmd == REP.REPCMD_INSERT){
-						tokenCmd.lineno++;
-					}else if(userCmd.cmd == REP.REPCMD_DELETE){
-						tokenCmd.lineno--;
-					}
-				}else if(userCmd.lineno > tokenCmd.lineno){     /* UsersLineNumber > TokensLineNumber */
-					if(tokenCmd.cmd == REP.REPCMD_INSERT){
-						userCmd.lineno++;
-					}else if(tokenCmd.cmd == REP.REPCMD_DELETE){
-						userCmd.lineno--;
-					}
-				}else if(userCmd.lineno == tokenCmd.lineno){     /* UsersLineNumber == TokensLineNumber */
-					/*
-	                 * �s�ԍ����d�Ȃ��REP�R�}���h�̋������N����̂ŁA
-	                 * �ǂ��炩�����Ȃ��Ƃ����Ȃ��B
-	                 * uid �����������D��(h_pricmd��)���A
-	                 * uid ���傫����(l_pricmd)��ύX����B
-	                 */
-					if(userCmd.eid < tokenCmd.eid){
-						h_pricmd = userCmd;
-						l_pricmd = tokenCmd;
-					}else {
-						h_pricmd = tokenCmd;
-						l_pricmd = userCmd;
-					}
-					if(h_pricmd.cmd == REP.REPCMD_INSERT){
-						l_pricmd.lineno++;
-					}else if(l_pricmd.cmd == REP.REPCMD_REPLACE){
-						if(l_pricmd.cmd == REP.REPCMD_INSERT){
-	                        /* h_pricmd ���D�悳��,l_pricmd �͍폜(������)���� */
-							l_pricmd.stat = REP_IGNORE;
-						}else if(l_pricmd.cmd == REP.REPCMD_DELETE){
-							/*
-	                         * l_pricmd ���ł͂��ł�delete����Ă���̂ŁA
-	                         * h_pricmd �� REP_REPLACE_CMD -> REP_INSERT_CMD �֕ύX�B
-	                         */
-							h_pricmd.cmd = REP.REPCMD_INSERT;
-							l_pricmd.stat = REP_IGNORE;
-						}
-					}else if(h_pricmd.cmd == REP.REPCMD_DELETE){
-	                    if (l_pricmd.cmd == REP.REPCMD_INSERT) {
-	                        h_pricmd.lineno++;
-	                    } else if(l_pricmd.cmd == REP.REPCMD_REPLACE){
-	                        /*
-	                         * h_pricmd ���ł͂��ł�delete����Ă���̂ŁA
-	                         * l_pricmd ���� REP_REPLACE_CMD -> REP_INSERT_CMD �֕ύX�B
-	                         */
-	                        l_pricmd.cmd = REP.REPCMD_INSERT;
-	                        h_pricmd.stat= REP_IGNORE;
-	                    } else {  /* l_pricmd->cmd == REP_DELETE_LINE_CMD */
-	                        /*
-	                         * ����ƍ폜����s���d�Ȃ�̂ŁA
-	                         * ����̃R�}���h�𖳎��ɂ���B
-	                         * �����ł͂��łɂ��̍s�͍폜����Ă���B
-	                         */
-	                        h_pricmd.stat = REP_IGNORE;
-	                        l_pricmd.stat = REP_IGNORE;
-	                        break;
-	                    }
-					}
-				}
-			}
-		}
-//		Iterator userListIterator = userList.iterator();
-//		while(userListIterator.hasNext()){
-//			//Iterator tokenListIterator = tokenList.iterator();
-//			REPCommand userCmd = (REPCommand)userListIterator.next();
-//			if(userCmd.stat == REP_IGNORE){
-//				userListIterator.remove();
-//			}
-//		}
-//
-//		Iterator tokenListIterator = tokenList.iterator();
-//		while(tokenListIterator.hasNext()){
-//			REPCommand tokenCmd = (REPCommand)tokenListIterator.next();
-//			if(tokenCmd.stat == REP_IGNORE){
-//				tokenListIterator.remove();
-//			}
-//		}
-	}
-
-	public void setMyEID(int myeid2) {
-		// TODO Auto-generated method stub
-		myeid = myeid2;
-	}
-}
--- a/rep/translater/Translater.java	Fri Oct 10 18:04:09 2008 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-package rep.translater;
-
-import rep.Editor;
-import rep.Forwarder;
-import rep.REPCommand;
-
-public interface Translater {
-
-	/**
-	 * 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.
-	 */
-	abstract public REPCommand transSendCmd(REPCommand 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.
-	 */
-	abstract public boolean catchOwnCommand(Editor editor);
-	
-	/**
-	 * Translate Command cmd that was received from SeMa.
-	 * @param cmd the command to be translated.
-	 * @return translated command.
-	 */
-	abstract public void transReceiveCmd(Forwarder nextEditor,REPCommand cmd);
-
-	/**
-	 * set the editor's id.
-	 * @param editor's id.
-	 */
-	abstract public void setEid(int _eid);
-}
--- a/rep/translater/TranslaterImp1.java	Fri Oct 10 18:04:09 2008 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-package rep.translater;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.LinkedList;
-import java.util.Stack;
-import java.util.TreeSet;
-
-import rep.Editor;
-import rep.Forwarder;
-import rep.REPCommand;
-import rep.REP;
-
-public class TranslaterImp1 implements Translater{
-	public int eid;
-	/*
-	 * queue が5つもいるって、あまりに馬鹿げてる。
-	 */
-	private LinkedList<REPCommand> sentCmds;
-	private Stack<REPCommand> unMergedCmds;
-	private LinkedList<REPCommand> undoReplaceList;
-	private LinkedList<REPCommand> sentMergedList;
-	private LinkedList<REPCommand> mergeAgainList;
-
-	public TranslaterImp1(int _eid){
-		eid = _eid;
-		sentCmds = new LinkedList<REPCommand>();
-		unMergedCmds = new Stack<REPCommand>();
-		undoReplaceList = new LinkedList<REPCommand>();
-		mergeAgainList = new LinkedList<REPCommand>();
-		sentMergedList = new LinkedList<REPCommand>();
-	}
-
-	/**
-	 * New command from an editor
-	 * The command is sent to the next editor
-	 * @param cmd
-	 * @return translated command.
-	 */
-	public REPCommand transSendCmd(REPCommand cmd){
-		sentCmds.add(cmd);
-		unMergedCmds.push(cmd);
-		
-		//マージ中にユーザから割り込みがあった場合
-		if(isMerging()){
-			mergeAgainList.add(cmd);
-		}
-		
-		return cmd;
-	}
-	/**
-	 * My command is returned from the session ring. At this
-	 * stage writeQueue is empty, our editor is waiting for me.
-	 * Start merge process.
-	 * @param cmd
-	 */
-	public boolean catchOwnCommand(Editor editor){
-		LinkedList<REPCommand> output = new LinkedList<REPCommand>();
-		LinkedList<REPCommand> cmds = new LinkedList<REPCommand>();
-				//スタック上にあるコマンドを全部undoコマンドにする
-		while ( !unMergedCmds.isEmpty() ){
-			REPCommand cmd0 = unMergedCmds.pop();
-			output.add( createUndo(cmd0) );
-			cmds.add(cmd0);
-		}
-
-		/* 必要な分だけソートして返却用のリストに追加  */
-		output.addAll( sortCmds(cmds) );
-
-		/* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる  */
-		output.addAll(cmds);
-		for(REPCommand c: cmds) {
-			output.add(c);
-			unMergedCmds.push(c);
-		}
-		return editor.optimizedSend(output);
-	}
-
-	public REPCommand prev() {
-		return sentCmds.poll();
-	}
-
-	private REPCommand createUndo(REPCommand cmd){
-		REPCommand retCmd = new REPCommand(cmd);
-		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;
-	}
-
-	class REPCommandComparator implements Comparator<REPCommand>{
-
-		public int compare(REPCommand o1, REPCommand o2) {
-			
-			if ( o2.lineno > o1.lineno ) return 1;
-			else if ( o2.lineno < o1.lineno 
-					|| o2.eid > o1.eid )
-				return -1;
-
-			return 1;
-		}
-		
-	}
-	
-	private Collection<REPCommand> sortCmds(LinkedList<REPCommand> cmds) {
-		TreeSet<REPCommand> sortedCmds1 = new TreeSet<REPCommand>(new REPCommandComparator());
-		int top;
-		int prevEid=-1;
-		while ( -1 != (top=getPrecedence(cmds, prevEid+1)) ){
-			REPCommand tmp = cmds.remove(top); 
-			sortedCmds1.add(tmp);
-			prevEid = tmp.eid;
-		}
-		
-		return sortedCmds1;
-	}
-
-	/* search cmd. ordering by  min EID that is lower lowEid and min SEQ.  */
-	private int getPrecedence(LinkedList<REPCommand> cmds, int lowEid) {
-		int cEid, cSeq;
-		cEid=cSeq=Integer.MAX_VALUE;
-		int ret=-1;
-		for (int i=0; i<cmds.size(); i++){
-			REPCommand c = cmds.get(i);
-			if ( c.eid<lowEid ) continue;
-			else if ( c.eid>cEid ) continue;
-			else if ( c.eid==cEid ) {
-				if ( c.seq>cSeq ) continue;
-				cSeq=c.seq;
-				ret = i;
-			} else { /* tmp.eid<cEid */
-				cEid = c.eid;
-				cSeq = c.seq;
-				ret = i;
-			}
-		}
-		return ret;
-	}
-
-	/**
-	 * Translate Command cmd that was received from SeMa.
-	 * @param cmd the command to be translated.
-	 * @return translated commannd.
-	 */
-	public void transReceiveCmd(Forwarder nextEditor,REPCommand cmd){
-		assert (cmd.eid != eid);
-		// nop command の挿入は Editor 側で行って、こちら側ではやらない
-		unMergedCmds.push(cmd);
-		nextEditor.send(cmd);
-	}
-
-	public void setEid(int _eid){
-		eid = _eid;
-	}
-
-	public Stack<REPCommand> getList() {
-		// TODO Auto-generated method stub
-		return unMergedCmds;
-	}
-
-	public LinkedList<REPCommand> getSentCmds() {
-		// TODO Auto-generated method stub
-		return sentCmds;
-	}
-
-	public void setUndoCommand(REPCommand command) {
-		// TODO Auto-generated method stub
-		undoReplaceList.add(command);
-	}
-
-	public boolean checkMergeConflict(REPCommand command) {
-		// sentMergedList.remove();
-		
-		if(mergeAgainList.size() > 0){
-			mergeAgainList.add(command);
-			if(sentMergedList.size() == 0){
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	public LinkedList<REPCommand> getMergeAgain() {
-		LinkedList<REPCommand> returnCommand = new LinkedList<REPCommand>();
-		for(int i = 0; i < mergeAgainList.size(); i++){
-			//eid = REP.MEGE_EID
-			returnCommand.add(createUndo(mergeAgainList.get(mergeAgainList.size() - i -1)));
-		}
-		for(REPCommand command : mergeAgainList){
-			if(command.eid == REP.MERGE_EID.id){
-				returnCommand.add(command);
-			}
-		}
-		for(REPCommand command : mergeAgainList){
-			if(command.eid == eid){
-				command.eid = REP.MERGE_EID.id;
-				returnCommand.add(command);
-			}
-		}
-		mergeAgainList.clear();
-		sentMergedList = returnCommand;
-		return returnCommand;
-	}
-
-	public boolean isFinished() {
-		if(unMergedCmds.size() > 0) return false;
-		if(sentMergedList.size() > 0) return false;
-		if(sentCmds.size() > 0) return false;
-		return true;
-	}
-
-	public boolean isMerging() {
-		if(sentMergedList.size() > 0) return true;
-		return false;
-	}
-
-	public void startMerge(REPCommand cmd) {
-		sentMergedList.add(cmd);
-		
-	}
-
-	public void mergeAck() {
-		sentMergedList.remove();
-	}
-
-
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/translator/Translate.java	Sat Oct 11 16:31:03 2008 +0900
@@ -0,0 +1,149 @@
+package rep.translator;
+
+import java.util.List;
+
+import rep.REPCommand;
+import rep.REP;
+
+public class Translate {
+	List <REPCommand> userList;
+	List <REPCommand> tokenList;
+	private boolean REP_IGNORE = true;
+	public int myeid;
+	
+	public Translate(){
+		
+	}
+	
+	//public Translate(List<REPCommand> userList, List<REPCommand> tokenList){
+	//	this.userList = userList;
+	//	this.tokenList = tokenList;
+		//merge();
+	//}
+
+
+
+	public Translate(List<REPCommand> userCmdList, List<REPCommand> tokenCmdList) {
+		this.userList = userCmdList;
+		this.tokenList = tokenCmdList;
+	}
+
+	public void addUserList(REPCommand usercmd){
+		userList.add(usercmd);
+	}
+	public void addTokenList(REPCommand tokencmd){
+		if(tokencmd.eid == myeid){
+			tokenList.clear();
+			userList.remove(0);
+		}else{
+			tokenList.add(tokencmd);
+		}
+	}
+	
+	void merge(){
+		REPCommand h_pricmd;
+		REPCommand l_pricmd;
+//		Iterator userListIterator = userList.iterator();
+//		while(userListIterator.hasNext()){
+		for(REPCommand userCmd:userList){
+			//Iterator tokenListIterator = tokenList.iterator();
+			//Rep_Cmd userCmd = (Rep_Cmd)userListIterator.next();
+			if(userCmd.stat) continue;     /* �폜�����(�\��)��REP�R�}���h�̔�r�͖��� */
+			//while(tokenListIterator.hasNext()){
+			for(REPCommand tokenCmd:tokenList){
+//				Rep_Cmd tokenCmd =(Rep_Cmd)tokenListIterator.next();
+				if(tokenCmd.eid == myeid) {
+					if(tokenCmd.seq == userCmd.seq){
+					tokenCmd.stat = REP_IGNORE;
+					userCmd.stat = REP_IGNORE;
+					}
+				}
+				if(tokenCmd.stat == REP_IGNORE) continue;     /* �폜�����(�\��)��REP�R�}���h�̔�r�͖��� */
+				if(userCmd.stat == REP_IGNORE) break;
+				if(userCmd.lineno < tokenCmd.lineno) {     /* UsersLineNumber < TokensLineNumber */
+					if(userCmd.cmd == REP.REPCMD_INSERT){
+						tokenCmd.lineno++;
+					}else if(userCmd.cmd == REP.REPCMD_DELETE){
+						tokenCmd.lineno--;
+					}
+				}else if(userCmd.lineno > tokenCmd.lineno){     /* UsersLineNumber > TokensLineNumber */
+					if(tokenCmd.cmd == REP.REPCMD_INSERT){
+						userCmd.lineno++;
+					}else if(tokenCmd.cmd == REP.REPCMD_DELETE){
+						userCmd.lineno--;
+					}
+				}else if(userCmd.lineno == tokenCmd.lineno){     /* UsersLineNumber == TokensLineNumber */
+					/*
+	                 * �s�ԍ����d�Ȃ��REP�R�}���h�̋������N����̂ŁA
+	                 * �ǂ��炩�����Ȃ��Ƃ����Ȃ��B
+	                 * uid �����������D��(h_pricmd��)���A
+	                 * uid ���傫����(l_pricmd)��ύX����B
+	                 */
+					if(userCmd.eid < tokenCmd.eid){
+						h_pricmd = userCmd;
+						l_pricmd = tokenCmd;
+					}else {
+						h_pricmd = tokenCmd;
+						l_pricmd = userCmd;
+					}
+					if(h_pricmd.cmd == REP.REPCMD_INSERT){
+						l_pricmd.lineno++;
+					}else if(l_pricmd.cmd == REP.REPCMD_REPLACE){
+						if(l_pricmd.cmd == REP.REPCMD_INSERT){
+	                        /* h_pricmd ���D�悳��,l_pricmd �͍폜(������)���� */
+							l_pricmd.stat = REP_IGNORE;
+						}else if(l_pricmd.cmd == REP.REPCMD_DELETE){
+							/*
+	                         * l_pricmd ���ł͂��ł�delete����Ă���̂ŁA
+	                         * h_pricmd �� REP_REPLACE_CMD -> REP_INSERT_CMD �֕ύX�B
+	                         */
+							h_pricmd.cmd = REP.REPCMD_INSERT;
+							l_pricmd.stat = REP_IGNORE;
+						}
+					}else if(h_pricmd.cmd == REP.REPCMD_DELETE){
+	                    if (l_pricmd.cmd == REP.REPCMD_INSERT) {
+	                        h_pricmd.lineno++;
+	                    } else if(l_pricmd.cmd == REP.REPCMD_REPLACE){
+	                        /*
+	                         * h_pricmd ���ł͂��ł�delete����Ă���̂ŁA
+	                         * l_pricmd ���� REP_REPLACE_CMD -> REP_INSERT_CMD �֕ύX�B
+	                         */
+	                        l_pricmd.cmd = REP.REPCMD_INSERT;
+	                        h_pricmd.stat= REP_IGNORE;
+	                    } else {  /* l_pricmd->cmd == REP_DELETE_LINE_CMD */
+	                        /*
+	                         * ����ƍ폜����s���d�Ȃ�̂ŁA
+	                         * ����̃R�}���h�𖳎��ɂ���B
+	                         * �����ł͂��łɂ��̍s�͍폜����Ă���B
+	                         */
+	                        h_pricmd.stat = REP_IGNORE;
+	                        l_pricmd.stat = REP_IGNORE;
+	                        break;
+	                    }
+					}
+				}
+			}
+		}
+//		Iterator userListIterator = userList.iterator();
+//		while(userListIterator.hasNext()){
+//			//Iterator tokenListIterator = tokenList.iterator();
+//			REPCommand userCmd = (REPCommand)userListIterator.next();
+//			if(userCmd.stat == REP_IGNORE){
+//				userListIterator.remove();
+//			}
+//		}
+//
+//		Iterator tokenListIterator = tokenList.iterator();
+//		while(tokenListIterator.hasNext()){
+//			REPCommand tokenCmd = (REPCommand)tokenListIterator.next();
+//			if(tokenCmd.stat == REP_IGNORE){
+//				tokenListIterator.remove();
+//			}
+//		}
+	}
+
+	public void setMyEID(int myeid2) {
+		// TODO Auto-generated method stub
+		myeid = myeid2;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/translator/Translator.java	Sat Oct 11 16:31:03 2008 +0900
@@ -0,0 +1,35 @@
+package rep.translator;
+
+import rep.Editor;
+import rep.Forwarder;
+import rep.REPCommand;
+
+public interface Translator {
+
+	/**
+	 * 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.
+	 */
+	abstract public REPCommand transSendCmd(REPCommand 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.
+	 */
+	abstract public boolean catchOwnCommand(Editor editor);
+	
+	/**
+	 * Translate Command cmd that was received from SeMa.
+	 * @param cmd the command to be translated.
+	 * @return translated command.
+	 */
+	abstract public void transReceiveCmd(Forwarder nextEditor,REPCommand cmd);
+
+	/**
+	 * 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/rep/translator/TranslatorImpl.java	Sat Oct 11 16:31:03 2008 +0900
@@ -0,0 +1,231 @@
+package rep.translator;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.Stack;
+import java.util.TreeSet;
+
+import rep.Editor;
+import rep.Forwarder;
+import rep.REPCommand;
+import rep.REP;
+
+public class TranslatorImpl implements Translator{
+	public int eid;
+	/*
+	 * queue が5つもいるって、あまりに馬鹿げてる。
+	 */
+	private LinkedList<REPCommand> sentCmds;
+	private Stack<REPCommand> unMergedCmds;
+	private LinkedList<REPCommand> undoReplaceList;
+	public LinkedList<REPCommand> sentMergedList;
+	private LinkedList<REPCommand> mergeAgainList;
+	boolean merge_mode = false;
+
+	public TranslatorImpl(int _eid){
+		eid = _eid;
+		sentCmds = new LinkedList<REPCommand>();
+		unMergedCmds = new Stack<REPCommand>();
+		undoReplaceList = new LinkedList<REPCommand>();
+		mergeAgainList = new LinkedList<REPCommand>();
+		sentMergedList = new LinkedList<REPCommand>();
+	}
+
+	/**
+	 * New command from an editor
+	 * The command is sent to the next editor
+	 * @param cmd
+	 * @return translated command.
+	 */
+	public REPCommand transSendCmd(REPCommand cmd){
+		sentCmds.add(cmd);
+		unMergedCmds.push(cmd);
+		
+		//マージ中にユーザから割り込みがあった場合
+		if(isMerging()){
+			mergeAgainList.add(cmd);
+		}
+		
+		return cmd;
+	}
+	/**
+	 * My command is returned from the session ring. At this
+	 * stage writeQueue is empty, our editor is waiting for me.
+	 * Start merge process.
+	 * @param cmd
+	 */
+	public boolean catchOwnCommand(Editor editor){
+		LinkedList<REPCommand> output = new LinkedList<REPCommand>();
+		LinkedList<REPCommand> cmds = new LinkedList<REPCommand>();
+				//スタック上にあるコマンドを全部undoコマンドにする
+		while ( !unMergedCmds.isEmpty() ){
+			REPCommand cmd0 = unMergedCmds.pop();
+			output.add( createUndo(cmd0) );
+			cmds.add(cmd0);
+		}
+
+		/* 必要な分だけソートして返却用のリストに追加  */
+		output.addAll( sortCmds(cmds) );
+
+		/* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる  */
+		output.addAll(cmds);
+		for(REPCommand c: cmds) {
+			output.add(c);
+			unMergedCmds.push(c);
+		}
+		return editor.optimizedSend(output);
+	}
+
+	public REPCommand prev() {
+		return sentCmds.poll();
+	}
+
+	private REPCommand createUndo(REPCommand cmd){
+		REPCommand retCmd = new REPCommand(cmd);
+		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;
+	}
+
+	class REPCommandComparator implements Comparator<REPCommand>{
+
+		public int compare(REPCommand o1, REPCommand o2) {
+			
+			if ( o2.lineno > o1.lineno ) return 1;
+			else if ( o2.lineno < o1.lineno 
+					|| o2.eid > o1.eid )
+				return -1;
+
+			return 1;
+		}
+		
+	}
+	
+	private Collection<REPCommand> sortCmds(LinkedList<REPCommand> cmds) {
+		TreeSet<REPCommand> sortedCmds1 = new TreeSet<REPCommand>(new REPCommandComparator());
+		int top;
+		int prevEid=-1;
+		while ( -1 != (top=getPrecedence(cmds, prevEid+1)) ){
+			REPCommand tmp = cmds.remove(top); 
+			sortedCmds1.add(tmp);
+			prevEid = tmp.eid;
+		}
+		
+		return sortedCmds1;
+	}
+
+	/* search cmd. ordering by  min EID that is lower lowEid and min SEQ.  */
+	private int getPrecedence(LinkedList<REPCommand> cmds, int lowEid) {
+		int cEid, cSeq;
+		cEid=cSeq=Integer.MAX_VALUE;
+		int ret=-1;
+		for (int i=0; i<cmds.size(); i++){
+			REPCommand c = cmds.get(i);
+			if ( c.eid<lowEid ) continue;
+			else if ( c.eid>cEid ) continue;
+			else if ( c.eid==cEid ) {
+				if ( c.seq>cSeq ) continue;
+				cSeq=c.seq;
+				ret = i;
+			} else { /* tmp.eid<cEid */
+				cEid = c.eid;
+				cSeq = c.seq;
+				ret = i;
+			}
+		}
+		return ret;
+	}
+
+	/**
+	 * Translate Command cmd that was received from SeMa.
+	 * @param cmd the command to be translated.
+	 * @return translated commannd.
+	 */
+	public void transReceiveCmd(Forwarder nextEditor,REPCommand cmd){
+		assert (cmd.eid != eid);
+		// nop command の挿入は Editor 側で行って、こちら側ではやらない
+		unMergedCmds.push(cmd);
+		nextEditor.send(cmd);
+	}
+
+	public void setEid(int _eid){
+		eid = _eid;
+	}
+
+	public Stack<REPCommand> getList() {
+		// TODO Auto-generated method stub
+		return unMergedCmds;
+	}
+
+	public LinkedList<REPCommand> getSentCmds() {
+		// TODO Auto-generated method stub
+		return sentCmds;
+	}
+
+	public void setUndoCommand(REPCommand command) {
+		// TODO Auto-generated method stub
+		undoReplaceList.add(command);
+	}
+
+	public boolean checkMergeConflict(REPCommand command) {
+		// sentMergedList.remove();
+		
+		if(mergeAgainList.size() > 0){
+			mergeAgainList.add(command);
+			if(sentMergedList.size() == 0){
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	public LinkedList<REPCommand> getMergeAgain() {
+		LinkedList<REPCommand> returnCommand = new LinkedList<REPCommand>();
+		for(int i = 0; i < mergeAgainList.size(); i++){
+			//eid = REP.MEGE_EID
+			returnCommand.add(createUndo(mergeAgainList.get(mergeAgainList.size() - i -1)));
+		}
+		for(REPCommand command : mergeAgainList){
+			if(command.eid == REP.MERGE_EID.id){
+				returnCommand.add(command);
+			}
+		}
+		for(REPCommand command : mergeAgainList){
+			if(command.eid == eid){
+				command.eid = REP.MERGE_EID.id;
+				returnCommand.add(command);
+			}
+		}
+		mergeAgainList.clear();
+		sentMergedList = returnCommand;
+		return returnCommand;
+	}
+
+	public boolean isFinished() {
+		if(unMergedCmds.size() > 0) return false;
+		if(sentMergedList.size() > 0) return false;
+		if(sentCmds.size() > 0) return false;
+		return true;
+	}
+
+	public boolean isMerging() {
+		return merge_mode;
+	}
+
+	public void startMerge(REPCommand cmd) {
+		merge_mode = true;
+	}
+
+	public void mergeAck() {
+
+	}
+	
+	public void endMerge() {
+		merge_mode = false;
+	}
+
+
+
+}