Mercurial > hg > RemoteEditor > Eclipse
view src/sample/merge/TranslaterImp1.java @ 114:c59b0886061c
translater
author | kent |
---|---|
date | Sun, 23 Dec 2007 16:15:15 +0900 |
parents | 2e649cd44078 |
children | a9fdbcbe351f |
line wrap: on
line source
package sample.merge; import java.util.ArrayList; 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; private int seq; 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. */ synchronized public REPCommand[] transSendCmd(REPCommand cmd){ REPCommand[] cmds = new REPCommand[1]; setCmdState(cmd); cmds[0] = cmd; sentCmds.add(cmd); unMergedCmds.push(cmd); return cmds; } /** * Dequeue command cmd that was returned. * @param cmd */ synchronized public REPCommand[] catchOwnCommand(REPCommand cmd){ ArrayList<REPCommand> returnCmds = new ArrayList<REPCommand>(); ArrayList<REPCommand> cmds = new ArrayList<REPCommand>(); // ringである以上、戻ってきたコマンドは確実にキューsentCmdsの先頭にある事を期待している REPCommand tmp = sentCmds.poll(); assert tmp.seq==cmd.seq; assert cmd.eid==eid; /* スタックから全部取り出してマージする まだマージできないやつはまたスタックへ戻す */ /* スタックから全部取り出す */ while ( !unMergedCmds.isEmpty() ){ REPCommand cmd0 = unMergedCmds.pop(); returnCmds.add( createUndo(cmd0) ); cmds.add(cmd0); } /* 必要な分だけソートして返却用のリストに追加 */ //if (cmds.size()==0) return null; returnCmds.addAll( sortCmds(cmds) ); /* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる */ for(int i=0; i<cmds.size(); i++){ returnCmds.add( cmds.get(i)); unMergedCmds.push( cmds.get(i)); } //returnCmds.addAll( cmds); //unMergedCmds.addAll( cmds); return returnCmds.toArray(new REPCommand[0]); } private REPCommand createUndo(REPCommand cmd){ //REPCommand retCmd = cmd.clone(); String str = new String(cmd.string); REPCommand retCmd = new REPCommand(cmd.cmd, cmd.sid, cmd.eid, cmd.seq, cmd.lineno, str.length(), str); 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>(); int top; int prevEid=0; int i,j; /* * EID,SEQの低い順に、各EID毎に1個だけ選択しsortedCmdsに格納 * cmdsにはまだデータが残る */ while ( -1 != (top=getPrecedence(cmds, prevEid+1)) ){ REPCommand tmp = cmds.remove(top); sortedCmds.add(tmp); prevEid = tmp.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によらず、順序を強制する必要があるかも */ k=j; } REPCommand tmp = sortedCmds.get(i); sortedCmds.set(i, sortedCmds.get(k)); sortedCmds.set(k, tmp); } return sortedCmds; } /* search cmd. ordering by min EID that is lower lowEid and min SEQ. */ private int getPrecedence(ArrayList<REPCommand> cmds, int lowEid) { int cEid, cSeq; cEid=cSeq=Integer.MAX_VALUE; int ret=-1; 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 = i; } else { /* tmp.eid<cEid */ cEid = tmp.eid; cSeq = tmp.seq; ret = i; } //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. */ synchronized 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] = setCmdState( 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; } private REPCommand setCmdState(REPCommand cmd){ cmd.seq = seq++; cmd.eid = eid; return cmd; } public void setEid(int _eid){ eid = _eid; } }