104
|
1 package sample.merge;
|
|
2
|
|
3 import java.util.ArrayList;
|
|
4 import java.util.Collection;
|
|
5 import java.util.LinkedList;
|
|
6 import java.util.Stack;
|
|
7
|
|
8 import remoteeditor.command.REPCommand;
|
|
9 import remoteeditor.network.REP;
|
|
10
|
|
11 public class TranslaterImp1 implements Translater{
|
|
12 //List <REPCommand> userList;
|
|
13 //List <REPCommand> tokenList;
|
|
14 private LinkedList<REPCommand> sentCmds;
|
|
15 //private LinkedList<REPCommand> unMergedCmds;
|
|
16 private Stack<REPCommand> unMergedCmds;
|
|
17 public int eid;
|
|
18
|
|
19 public TranslaterImp1(int _eid){
|
|
20 eid = _eid;
|
|
21 sentCmds = new LinkedList<REPCommand>();
|
|
22 unMergedCmds = new Stack<REPCommand>();
|
|
23 }
|
|
24
|
|
25 /**
|
|
26 * Translate cmd When the editor send REPCommand.
|
|
27 * but now, Only adding cmd to the queue is available.
|
|
28 * @param cmd
|
|
29 * @return translated command.
|
|
30 */
|
|
31 public REPCommand transSendCmd(REPCommand cmd){
|
|
32 sentCmds.add(cmd);
|
|
33 unMergedCmds.push(cmd);
|
|
34 return cmd;
|
|
35 }
|
|
36 /**
|
|
37 * Dequeue command cmd that was returned.
|
|
38 * @param cmd
|
|
39 */
|
|
40 public REPCommand[] catchOwnCommand(REPCommand cmd){
|
|
41 ArrayList<REPCommand> returnCmds = new ArrayList<REPCommand>();
|
|
42 ArrayList<REPCommand> cmds = new ArrayList<REPCommand>();
|
|
43 // ringである以上、戻ってきたコマンドは確実にキューsentCmdsの先頭にある事を期待している
|
|
44 //REPCommand cmd0 = sentCmds.poll();
|
|
45 //assert cmd0.seq!=cmd.seq;
|
|
46 assert cmd.eid==eid;
|
|
47
|
|
48 /* スタックから全部取り出してマージする まだマージできないやつはまたスタックへ戻す */
|
|
49 while ( !unMergedCmds.isEmpty() ){
|
|
50 REPCommand cmd0 = unMergedCmds.pop();
|
|
51 returnCmds.add( createUndo(cmd0) );
|
|
52 cmds.add(cmd0);
|
|
53 }
|
|
54 //if (cmds.size()==0) return null;
|
|
55 returnCmds.addAll( sortCmds(cmds) );
|
|
56 return returnCmds.toArray(new REPCommand[0]);
|
|
57 }
|
|
58
|
|
59 private REPCommand createUndo(REPCommand cmd){
|
|
60 //REPCommand retCmd = cmd.clone();
|
|
61 REPCommand retCmd = new REPCommand(cmd.cmd, cmd.sid, cmd.eid, cmd.seq, cmd.lineno, cmd.string.length(), cmd.string);
|
|
62
|
|
63 if (cmd.cmd==REP.REPCMD_INSERT) retCmd.cmd=REP.REPCMD_DELETE;
|
|
64 else if (cmd.cmd==REP.REPCMD_DELETE) retCmd.cmd=REP.REPCMD_INSERT;
|
|
65 return retCmd;
|
|
66 }
|
|
67
|
|
68 private ArrayList<REPCommand> sortCmds(ArrayList<REPCommand> cmds) {
|
|
69 ArrayList<REPCommand> sortedCmds = new ArrayList<REPCommand>();
|
|
70 REPCommand cmd0;
|
|
71 int prevEid=0;
|
|
72 int i,j;
|
|
73
|
|
74 /* EID,SEQの低い順に、各EID毎に1個だけ選択しcmdsに格納 */
|
|
75 while ( null != (cmd0=getPrecedence(cmds, prevEid+1)) ){
|
|
76 sortedCmds.add(cmd0);
|
|
77 cmds.remove(cmd0);
|
|
78 prevEid = cmd0.eid;
|
|
79 }
|
|
80
|
|
81 /* lineno の大きい順にソート */
|
|
82 for (i=0; i<sortedCmds.size(); i++){
|
|
83 int k=i;
|
|
84 for (j=i+1; j<sortedCmds.size(); j++){
|
|
85 if ( sortedCmds.get(k).lineno > sortedCmds.get(j).lineno ) continue;
|
|
86 else if ( sortedCmds.get(k).lineno < sortedCmds.get(j).lineno
|
|
87 || sortedCmds.get(k).eid > sortedCmds.get(j).eid )
|
|
88 /* deleteとinsertの場合などはeidによらず、順序を強制する必要があるかも */
|
|
89 k=j;
|
|
90 }
|
|
91 cmd0 = sortedCmds.get(i);
|
|
92 sortedCmds.set(i, sortedCmds.get(k));
|
|
93 sortedCmds.set(k, cmd0);
|
|
94 }
|
|
95 return sortedCmds;
|
|
96 }
|
|
97
|
|
98 /* search cmd. ordering by min EID that is lower lowEid and min SEQ. */
|
|
99 private REPCommand getPrecedence(ArrayList<REPCommand> cmds, int lowEid) {
|
|
100 int cEid, cSeq;
|
|
101 cEid=cSeq=Integer.MAX_VALUE;
|
|
102 REPCommand ret=null;
|
|
103 for (int i=0; i<cmds.size(); i++){
|
|
104 REPCommand tmp = cmds.get(i);
|
|
105 if ( tmp.eid<lowEid ) continue;
|
|
106 else if ( tmp.eid>cEid ) continue;
|
|
107 else if ( tmp.eid==cEid ) {
|
|
108 if ( tmp.seq>cSeq ) continue;
|
|
109 cSeq=tmp.seq;
|
|
110 ret = tmp;
|
|
111 } else { /* tmp.eid<cEid */
|
|
112 cEid = tmp.eid;
|
|
113 cSeq = tmp.seq;
|
|
114 ret = tmp;
|
|
115 }
|
|
116 //if ( cEid>cmds.get(i) && cmds.get(i)>lowEid )
|
|
117 }
|
|
118 return ret;
|
|
119 }
|
|
120
|
|
121 /**
|
|
122 * Translate Command cmd that was received from SeMa.
|
|
123 * @param cmd the command to be translated.
|
|
124 * @return translated commannd.
|
|
125 */
|
|
126 public REPCommand[] transReceiveCmd(REPCommand cmd){
|
|
127 int i=0;
|
|
128 REPCommand cmds[];
|
|
129 if (cmd.eid==eid){
|
|
130 return catchOwnCommand(cmd);
|
|
131 }
|
|
132
|
|
133 for (REPCommand cmd0 : unMergedCmds){
|
|
134 if (cmd0.eid==cmd.eid) i++;
|
|
135 }
|
|
136
|
|
137 if ( sentCmds.size()<i ){
|
|
138 cmds = new REPCommand[2];
|
|
139 String str = "NO OPERATION";
|
|
140 cmds[0] = new REPCommand(REP.REPCMD_NOP, 0, eid, 0, 0, str.length(), str);
|
|
141 cmds[1] = cmd;
|
|
142 //unMergedCmds.push(cmds[0]);
|
|
143 unMergedCmds.push(cmd);
|
|
144 sentCmds.add(cmds[0]);
|
|
145 return cmds;
|
|
146 }
|
|
147
|
|
148 unMergedCmds.push(cmd); /* but.. */
|
|
149 cmds = new REPCommand[1];
|
|
150 cmds[0] = cmd;
|
|
151 return cmds;
|
|
152 }
|
|
153
|
|
154 public void setEid(int _eid){
|
|
155 eid = _eid;
|
|
156 }
|
|
157 }
|