changeset 382:4b87f89b3afd

REP Session Manager (Java version) new structure
author one@firefly.cr.ie.u-ryukyu.ac.jp
date Mon, 10 Nov 2008 22:07:45 +0900
parents 65fdb3dc1885
children 6d48db302b07
files export/pin.jar export/sessionmanager.jar export/sessionmanager2.jar export/sm.sh java.policy.applet rep/CloseButtonEvent.java rep/ConnectButtonEvent.java rep/ConnectionListener.java rep/DoGUIUpdate.java rep/Editor.java rep/EditorList.java rep/EditorPlus.java rep/FirstConnector.java rep/Forwarder.java rep/NullForwarder.java rep/PacketSet.java rep/REPCommand.java rep/REPCommandPacker.java rep/RoutingTable.java rep/SelectButtonEvent.java rep/Session.java rep/SessionManager.java rep/SessionManagerEvent.java rep/SessionManagerEventListener.java rep/SessionManagerGUI.java rep/SessionManagerGUIimpl.java rep/SessionManagerList.java rep/SessionManagerNode.java rep/SessionViewer.java rep/Translator.java rep/TranslatorImpl.java rep/channel/ChannelSimulator.java rep/channel/NetworkSimulator.java rep/channel/SelectionKeySimulator.java rep/channel/SelectorSimulator.java rep/channel/ServerChannelSimulator.java rep/gui/CloseButtonEvent.java rep/gui/ConnectButtonEvent.java rep/gui/DoGUIUpdate.java rep/gui/RPanel.java rep/gui/SelectButtonEvent.java rep/gui/SessionManagerEvent.java rep/gui/SessionManagerEventListener.java rep/gui/SessionManagerGUI.java rep/gui/SessionManagerGUIimpl.java rep/handler/Dispatcher.java rep/handler/Editor.java rep/handler/FirstConnector.java rep/handler/Forwarder.java rep/handler/NullForwarder.java rep/handler/PacketSet.java rep/handler/REPHandler.java rep/handler/REPNode.java rep/translator/Translator.java rep/translator/TranslatorImpl.java rep/xml/SessionXMLDecoder.java rep/xml/SessionXMLEncoder.java test/ConnectionPanel.java test/DefaultTableModelTest.java test/JTableTest.java test/RepCommandOptimizeTest.java test/SessionXMLDecoder2.java test/SessionXMLParser.java test/TestGUI.java test/TestSelector.java test/TestUTF8.java test/XMLTest.java test/channeltest/testEditor.java test/channeltest/testNetworkSimulator.java test/channeltest/testSeMa.java test/channeltest/testSeMaSlave.java test/sematest/TestEditor.java test/sematest/TestGUI.java test/sematest/TestInterManagerSession.java test/sematest/TestSessionManager.java
diffstat 64 files changed, 1319 insertions(+), 1573 deletions(-) [+]
line wrap: on
line diff
Binary file export/pin.jar has changed
Binary file export/sessionmanager.jar has changed
Binary file export/sessionmanager2.jar has changed
--- a/export/sm.sh	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-java -classpath sessionmanager.jar rep.SessionManager
--- a/java.policy.applet	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-/* AUTOMATICALLY GENERATED ON Tue Apr 16 17:20:59 EDT 2002*/
-/* DO NOT EDIT */
-
-grant {
-  permission java.security.AllPermission;
-};
-
--- a/rep/CloseButtonEvent.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-package rep;
-
-public class CloseButtonEvent implements SessionManagerEvent {
-
-	private Session session;
-	private SessionManagerEventListener listener;
-
-	public CloseButtonEvent(Session session, SessionManagerEventListener listener) {
-		this.session = session;
-		this.listener = listener;
-	}
-	
-	public Session getSession(){
-		return session;
-	}
-
-	public void exec(SessionManager manager) {
-		listener.closeSession(this);
-	}
-
-}
--- a/rep/ConnectButtonEvent.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package rep;
-
-public class ConnectButtonEvent implements SessionManagerEvent{
-
-	private String host;
-
-	public ConnectButtonEvent(String host) {
-		this.host = host;
-	}
-
-	public String getHost() {
-		return host;
-	}
-
-	public void exec(SessionManager manager) {
-		manager.connectSessionManager(host);
-	}
-
-}
--- a/rep/ConnectionListener.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-package rep;
-
-public interface ConnectionListener {
-	public void connectionOccured(ConnectButtonEvent event);
-}
--- a/rep/DoGUIUpdate.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-package rep;
-
-import java.util.LinkedList;
-
-public class DoGUIUpdate implements Runnable{
-	
-	private LinkedList<Session> slist;
-	private LinkedList<Editor> elist;
-	private SessionManagerGUI gui;
-
-	public DoGUIUpdate(LinkedList<Session> _slist, LinkedList<Editor> _elist, SessionManagerGUI _gui) {
-		gui = _gui; 
-		slist = _slist; elist = _elist;
-	}
-	
-	public void run() {
-		gui.update(slist, elist);
-	}
-
-}
--- a/rep/Editor.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-package rep;
-
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-
-import rep.channel.REPSelectionKey;
-import rep.channel.REPSocketChannel;
-import rep.handler.PacketSet;
-import rep.optimizers.*;
-import rep.translator.Translator;
-import rep.translator.TranslatorImpl;
-
-public class Editor extends Forwarder {
-
-	private Translator translator;
-	private List<REPCommand> sentList = new LinkedList<REPCommand>();
-	// REPCommands we are going to send to the next editor
-	//private REPCommand quit2 = null;
-	private SessionManager manager;
-	private REPCommand quit2=null;
-
-	public Editor(SessionManager manager,boolean doOptimize,int editorNo){
-		super(manager);
-		this.manager = manager;
-		eid = editorNo;
-		REPCommandOptimizer optimizer;
-		if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ
-		else            optimizer = new NullOptimizer();         //なにもしないけどOptimizer.
-		translator = new TranslatorImpl(eid,optimizer);
-		
-	}
-
-	public Editor(SessionManager manager,int editorNo, REPSocketChannel<REPCommand> channel){
-		this(manager,false,editorNo);
-		this.channel = channel;
-	}
-
-	public void translate(REPCommand command){
-
-		if(command.eid == eid){
-			//エディタからの新たな編集コマンド
-			if (next==this) return; // singleton case
-			translator.transSendCmd(command);
-			sentList.add(new REPCommand(command));
-			assert(sentList.size()<limit);
-			next.send(command);
-			return;
-		} else if(command.eid == REP.MERGE_EID.id){
-			//マージコマンドが返ってきた
-			if(translator.checkMergeConflict(command)){
-				//マージ中にエディタからの割り込みがあった場合
-				translator.getMergeAgain(this);
-			}
-			checkEndMerge();
-		} else if(command.eid == next.getEID()){
-			// 次のEditorで一周するコマンドが来た
-			if(next==this) return; // singleton case
-			// これは、distributed case では、うまくいかないので、送り先のforwarder で処理する。
-			if (next.isDirect())
-				((Editor) next).checkReturnedCommand(command);
-			else
-				next.send(command);
-		} else {
-			//他のエディタからの編集コマンド
-			assert (command.eid!=REP.MERGE_EID.id && command.eid!=eid );
-			if (manager.hasWaitingCommand(channel)) {
-				// We cannot do this operation before watingCommandQueue.
-				manager.addWaitingCommand(new PacketSet(channel, this, command));
-				return;
-			}		
-			if(!isMerging()) {
-				translator.transReceiveCmd(next,command);
-				return;
-			}
-			manager.addWaitingCommand(new PacketSet(getChannel(), this, new REPCommand(command)));
-		}
-		return;
-	}
-
-	boolean merge(REPCommand command) {
-		//マージして送信
-		return translator.catchOwnCommand(this);
-	}
-
-	void checkReturnedCommand(REPCommand command) {
-		REPCommand prev = sentList.remove(0);
-		if (prev==null || prev.seq != command.seq || prev.eid!=command.eid) {
-			String err = "Editor.checkReturnedCommand() : command = " + command + " prev=";
-			err += prev==null?"null":prev.toString();
-			SessionManager.logger.writeLog(err);
-			assert(false);
-		}
-
-		// START_MERGE を送る
-		//    送らないで良い場合もある?
-		REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,"");
-		send(cmd);
-		// Session Manager 側で、このeditorへの他のeditorからの
-		// 入力を止めて、merge にそなえる。merge は、eidtor 側から
-		// ACKが来てから始まる。
-		translator.startMerge(cmd);
-		return;
-	}
-
-	@Override
-	public void setQuit2(REPCommand cmd) {
-		quit2 = cmd;
-		checkQuit();
-		// do not send quit2 until we received all pending
-		// command
-	}
-
-	@Override
-	public void setEID(int eid) {
-		this.eid = eid;
-		translator.setEid(eid);
-	}
-	
-	public String toString(){
-		return ("Editor eid="+eid+" sid="+sid+" " + host  + ":" + file);
-	}
-
-	public boolean isMerging() {
-		return translator.isMerging();
-	}
-
-	
-
-	void checkEndMerge() {
-		if(translator.isMerging()) return;
-		REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,eid,sid,seq(),0,"");
-		send(mergeEnd);				
-		if (quit2!=null) checkQuit();
-	}
-
-	private boolean checkQuit() {
-		if (sentList.size()==0&&!isMerging()) {
-			send(quit2);
-			quit2 = null;
-			return true;
-		}
-		return false;
-	}
-
-	@Override
-	public boolean manage(REPCommand receivedCommand) {
-		
-		
-		switch(receivedCommand.cmd){
-		// Editor Command
-		
-		case REPCMD_DELETE:
-		case REPCMD_INSERT:
-		case REPCMD_NOP:
-		{
-			translate(receivedCommand);
-			break;
-		}
-
-		case SMCMD_START_MERGE_ACK:
-		{
-			// マージの処理と次のエディタへコマンドを送信する処理
-			translator.mergeAck();
-			if (!merge(receivedCommand)) {
-				// nothing to do, send END_MERGE
-				checkEndMerge();
-			}
-			break;
-		}
-		case SMCMD_QUIT:
-		{
-			next.send(receivedCommand);
-			break;
-		}
-		case SMCMD_QUIT_2:
-		{
-			// QUIT_2 is returned.
-			if (receivedCommand.eid!=eid) {
-				// stop this editor unless this is the start, starter will stopped
-				// by QUIT_2_ACK
-				manager.remove(this);
-			}
-			// don't send quit_2 directly to the editor until all pending
-			// merge is processed.
-			//   this does not work in distributed case.
-			if (next.isDirect())
-				next.setQuit2(receivedCommand);
-			else
-				next.send(receivedCommand);
-			break;
-		}
-		case SMCMD_QUIT_2_ACK:
-		{
-			manager.remove(this);
-			break;
-		}
-		default:
-			return false;
-		}
-		return true;
-	}
-	
-
-	@Override
-	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
-		REPSocketChannel<REPCommand> channel = key.channel1();
-		REPCommand command = channel.read();
-		SessionManager.logger.writeLog("REPHandlerImpl.handle() read : command = " + command +" from "+channel);
-		if (manager.sessionManage(this, command)) return;
-		manage(command);
-	}
-
-	@Override
-	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
-		manager.remove(socketChannel);
-	}
-
-	public boolean isMaster() {
-		return mode==REP.SMCMD_PUT;
-	}
-	
-	/* Handle special case first, usually these cases
-	 * are handled in the next Editor in a session manager, but 
-	 * it is forwarded here.
-	 */
-	public void forwardedCommandManage(REPCommand command, Forwarder forwarder) {
-		if (command.cmd==REP.SMCMD_QUIT_2) {
-			// we have to wait next editor's finishing before sending this.
-			// this is odd, but the editor itself does not know it's merging
-			// state. Only this session manager knows it.
-			setQuit2(command);
-		} else if (command.eid==eid) {
-			// if we handle in editor.manage(), this editor cannot distinguish this
-			// and user input command from the editor.
-			switch(command.cmd) {
-			case REPCMD_DELETE:
-			case REPCMD_INSERT:
-			case REPCMD_NOP:
-				checkReturnedCommand(command);
-				return;
-			}
-		} 
-		send(command);
-	}
-}
--- a/rep/EditorList.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/EditorList.java	Mon Nov 10 22:07:45 2008 +0900
@@ -2,7 +2,9 @@
 
 import java.util.HashMap;
 
-public class EditorList extends HashMap<Integer,Editor> {
+import rep.handler.REPNode;
+
+public class EditorList extends HashMap<Integer,REPNode> {
 
 	/**
 	 * 
@@ -10,7 +12,7 @@
 	private static final long serialVersionUID = 1L;
 	private int eid_root=0;
 	
-	public void add(Editor fw) {
+	public void add(REPNode fw) {
 		put(fw.getEID(),fw);
 	}
 
--- a/rep/EditorPlus.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-package rep;
-
-import rep.channel.REPSocketChannel;
-
-public class EditorPlus {
-
-	public int eid; // globally unique
-	public int sid=-1; // globally unique
-	public String host;
-	public String file;
-	public REPSocketChannel<REPCommand> channel;
-	
-	public EditorPlus() {
-		
-	}
-	
-	public EditorPlus(int eid, REPSocketChannel<REPCommand> channel) {
-		this.eid = eid;
-		this.channel = channel;
-	}
-
-	public String getName() {
-		return file;
-	}
-
-	public void setName(String string) {
-		file = string;
-	}
-
-
-	public void setSID(int sid) {
-		this.sid = sid;
-	}
-	
-	public int getSID() {
-		return sid;
-	}
-
-	public boolean hasSession() {
-		return sid != -1;
-	}
-	
-	public String toString(){
-		return ("Editor:" + eid);
-	}
-
-	public void setEID(int eid) {
-		this.eid = eid;
-	}
-	
-	public int getEID(){
-		return eid;
-	}
-
-	public void setHost(String host){
-		if (channel!=null)
-			this.host = host;
-	}
-
-	
-	public String getHost(){
-		return host;
-	}
-	public REPSocketChannel<REPCommand> getChannel(){
-		return channel;
-		
-	}
-	public void setChannel(REPSocketChannel<REPCommand> channel) {
-		this.channel = channel;		
-	}
-
-	public void merge(EditorPlus editor) {
-		if (sid==-1) sid = editor.sid;
-		if (file==null) file = editor.file;
-		if (host==null) host = editor.host;
-	}
-}
--- a/rep/FirstConnector.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-package rep;
-
-import java.io.IOException;
-
-import rep.channel.REPSelectionKey;
-import rep.channel.REPSocketChannel;
-
-public class FirstConnector extends Forwarder {
-
-	public FirstConnector(SessionManager manager) {
-		super(manager);
-	}
-	
-	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
-		manager.remove(socketChannel);
-	}
-
-	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
-		/*
-		 * 接続要求は、EditorかSlave Editorで、
-		 *    join, put, sm_join
-		 * が来る。それ以外はエラー。master もありか?
-		 *      sm_join_ack
-		 */
-		Forwarder fw;
-		REPSocketChannel<REPCommand> channel = key.channel1();
-		REPCommand command = channel.read();
-		SessionManager.logger.writeLog("FirstConnector: command = " + command);
-		switch(command.cmd) {
-		case SMCMD_JOIN: 
-		{
-			//どのSessionにも属さないエディタをリストに追加
-			//エディタとchannelは1対1 (ではないかも)
-			//エディタが新しくputする場合は新しくソケットを作る
-			//   1対1でない場合は、multiplexerを挿めば良い
-			Editor editor = manager.newEditor(channel);
-			editor.setHost(manager.myHost);
-			command.eid = editor.eid;
-			command.sid = -1;
-			editor.setSID(-1);
-			fw = editor;
-			break;
-		}
-		case SMCMD_PUT:
-		{
-			//  新しいeditorとsessionをここで作る。eid,sidは、
-			//  session manager IDが付いているので、global unique
-			Editor editor = manager.newEditor(channel);
-			Session session = manager.newSession(editor);
-			session.setName(command.string);
-			editor.setName(command.string);
-			editor.setSID(session.getSID());
-			command.eid = editor.eid;
-			command.sid = editor.sid;
-			fw = editor;
-			break;
-		}
-		case SMCMD_SM_JOIN:
-		{
-			fw = new Forwarder(manager);
-			manager.smList.addWaitingSessionManager(fw, command);
-			break;
-		}
-		case SMCMD_SM_JOIN_ACK:
-			manager.setSessionManagerID(command.sid);
-			manager.afterConnect();
-			fw = new Forwarder(manager);
-			manager.setParent(fw);
-			break;
-		default: throw new IOException();
-		}
-		//myHost を設定。
-		//立ち上げ時にやるとlocalhostしか取れない
-		if(manager.myHost == null) manager.setMyHostName(getLocalHostName());
-		fw.setMode(command.cmd);
-		fw.setHost(manager.myHost);
-		manager.registerChannel(channel, fw);
-		manager.sessionManage(fw, command);
-	
-	}
-
-}
--- a/rep/Forwarder.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-package rep;
-
-import java.io.IOException;
-import rep.channel.REPLogger;
-import rep.channel.REPSelectionKey;
-import rep.channel.REPSocketChannel;
-import rep.handler.PacketSet;
-import rep.handler.REPHandler;
-
-public class Forwarder extends EditorPlus implements REPHandler {
-	int seq = 0;
-	Forwarder next;
-	// REPCommands we sent to the next editor
-	final int limit=100;
-	REPLogger ns = REPLogger.singleton();
-	SessionManager manager;
-	public REP mode = null;
-	
-	public Forwarder(SessionManager manager) {
-		this.manager = manager;
-	}
-
-	public int seq() {
-		return seq++;
-	}
-	
-	public void send(REPCommand command) {
-		assert(command!=null);
-		assert(channel!=null);
-		REPCommand c = new REPCommand(command);
-		manager.addWriteQueue(new PacketSet(channel,null,  c));
-	}
-	
-	public REPSocketChannel<REPCommand> getChannel() {
-		return channel;
-	}
-	
-	public void setChannel(REPSocketChannel<REPCommand> channel) {
-		this.channel = channel;
-	}
-
-	public void setQuit2(REPCommand cmd) {
-		send(cmd);
-	}
-
-	public void setNext(Forwarder next) {
-		this.next = next;
-	}
-	
-	public Forwarder getNextForwarder() {
-		return next;
-	}
-
-	public boolean manage(REPCommand command) {
-		next.send(command);
-		return true;
-	}
-
-	public String toString(){
-		return ("Forwarder:" + channel);
-	}
-	
-	public String getLocalHostName() {
-		return channel.getLocalHostName();
-	}
-
-	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
-		manager.remove(socketChannel);
-	}
-
-	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
-		/*
-		 * SessionManagerから来たコマンドは、Editor関係のコマンドは、
-		 * sessionとeidを判定して、そのeditorにforwardしてやれば良い。
-		 * 残りは、manager.manage() で処理する。
-		 */
-		REPSocketChannel<REPCommand> channel = key.channel1();
-		REPCommand command = channel.read();
-		SessionManager.logger.writeLog("REPHandlerImpl.handle() : command = " + command);
-		if (manager.sessionManage(this, command)) return;
-		
-		distpatchToEditor(channel, command);
-	}
-
-	private void distpatchToEditor(REPSocketChannel<REPCommand> channel,
-			REPCommand command) throws IOException {
-		Session s = manager.getSession(command.sid);
-		if (s==null) throw new IOException();
-		Forwarder f = s.getForwarder(channel);
-		if (f==null) throw new IOException();
-		if (!f.isDirect()) {
-			// another forwarder, pass it to the next session manager
-			f.send(command); 
-			return;
-		}
-		/*
-		 * local editor case. 
-		 */
-		Editor editor = (Editor)f;
-		editor.forwardedCommandManage(command, this);
-	}
-
-	public void setMode(REP cmd) {
-		mode = cmd;
-	}
-
-	public boolean isEditor() {
-		return mode==REP.SMCMD_JOIN||mode==REP.SMCMD_PUT;
-	}
-	
-	public boolean isForwarder() {
-		return mode==REP.SMCMD_SM_JOIN||mode==REP.SMCMD_SM_JOIN_ACK;
-	}
-
-	public boolean isDirect() {
-		return isEditor();
-	}
-
-
-}
\ No newline at end of file
--- a/rep/NullForwarder.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-package rep;
-
-import java.io.IOException;
-
-import rep.channel.REPSelectionKey;
-import rep.channel.REPSocketChannel;
-
-public class NullForwarder extends Forwarder {
-
-	public NullForwarder(SessionManager manager) {
-		super(manager);
-	}
-
-	public void send(REPCommand command) {
-		
-	}
-	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
-
-	}
-
-	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
-
-	}
-
-	public boolean manage(REPCommand command) {
-		return true;
-	}
-
-	public boolean isEditor() {
-		return false;
-	}
-	
-	public boolean isForwarder() {
-		return false;
-	}
-
-	public boolean isDirect() {
-		return false;
-	}
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/PacketSet.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,23 @@
+package rep;
+
+import rep.channel.REPSocketChannel;
+import rep.handler.REPNode;
+
+public class PacketSet {
+
+	public REPSocketChannel<REPCommand> channel;
+	public REPNode editor;
+	public REPCommand command;
+
+	public PacketSet(REPSocketChannel<REPCommand> channel, REPNode editor, REPCommand command) {
+		this.channel = channel;
+		this.editor = editor;
+		this.command = command;
+	}
+
+	public REPNode getEditor() {
+		return editor;
+	}
+	
+
+}
--- a/rep/REPCommand.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/REPCommand.java	Mon Nov 10 22:07:45 2008 +0900
@@ -9,12 +9,8 @@
 	public int seq;
 	public int len;
 	public int lineno;
-	public boolean stat;
-	public boolean throughMaster;
 
 	public  String string;
-	String host;
-	String port;
 	
 	public REPCommand(REP cmd,int sid,int eid, int seq, int lineno, String string) {
 		this.cmd = cmd;
@@ -23,8 +19,8 @@
 		this.seq = seq;
 		this.lineno = lineno;
 		this.string = string;
-		this.throughMaster = false;
 	}
+	
 	public REPCommand(REPCommand cmd){
 		this(cmd.cmd, cmd.sid, cmd.eid, cmd.seq, cmd.lineno, cmd.string);
 	}
@@ -40,7 +36,6 @@
 		this.seq = seq;
 		this.lineno = lineno;
 		this.string = string;
-		this.throughMaster = false;
 	}
 	
 	public String toString(){
@@ -66,17 +61,6 @@
 		string = string2;
 	}
 
-	public void setHost(String host) {
-		this.host = host;
-	}
-
-	public void setPort(String port) {
-		this.port = port;
-	}
-	
-	public void setThroughMaster(boolean f){
-		this.throughMaster=f;
-	}
 	public void setSEQID(int i) {
 		seq = i;
 	}
--- a/rep/REPCommandPacker.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/REPCommandPacker.java	Mon Nov 10 22:07:45 2008 +0900
@@ -41,9 +41,7 @@
 	 * @see rep.REPPack#packUConv(rep.REPCommand)
 	 */
 	public ByteBuffer packUConv(REPCommand command){
-		int size = 0;
-		if (command.string!=null) size = command.string.length()*CHARSIZE;
-    	ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE+size);
+    	ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE+(command.string.length()*CHARSIZE));
     	buffer.clear();  // position = 0 
     	buffer.putInt(command.cmd.id);
     	buffer.putInt(command.sid);
--- a/rep/RoutingTable.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/RoutingTable.java	Mon Nov 10 22:07:45 2008 +0900
@@ -3,9 +3,11 @@
 import java.util.HashMap;
 import java.util.Map.Entry;
 
+import rep.handler.REPNode;
+
 public class RoutingTable {
 
-	HashMap<Integer,Forwarder> sessionManagers =new HashMap<Integer,Forwarder>();
+	HashMap<Integer,REPNode> sessionManagers =new HashMap<Integer,REPNode>();
 	SessionManager manager;
 	// we don't need this, but we keep it because it is easy.
 	// editor can be reached using this routing table.
@@ -14,12 +16,12 @@
 		manager = sessionManager;
 	}
 
-	public void add(Forwarder forwarder, int smid) {
+	public void add(REPNode forwarder, int smid) {
 		if (smid>0) sessionManagers.put(smid, forwarder)	;
 	}
 	
-	public void remove(Forwarder f) {
-		for(Entry<Integer, Forwarder> entry:sessionManagers.entrySet()) {
+	public void remove(REPNode f) {
+		for(Entry<Integer, REPNode> entry:sessionManagers.entrySet()) {
 			if (entry.getValue()==f) sessionManagers.remove(entry.getKey());
 		}
 	}
@@ -28,8 +30,8 @@
 		sessionManagers.remove(smid);
 	}
 
-	public Forwarder toSessionManager(int eid) {
-		Forwarder next = sessionManagers.get(eid);
+	public REPNode toSessionManager(int eid) {
+		REPNode next = sessionManagers.get(eid);
 		if (next==null) return manager.smList.parent();
 		return next;
 	}
--- a/rep/SelectButtonEvent.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-package rep;
-
-import java.io.IOException;
-
-public class SelectButtonEvent implements SessionManagerEvent{
-
-	private int sid;
-	private Forwarder editor;
-
-	public SelectButtonEvent(Forwarder editor, Session session) {
-		this.editor = editor;
-		this.sid = session.getSID();
-	}
-
-	public int getSID() {
-		return sid;
-	}
-
-	public Forwarder getEditor() {
-		return editor;
-	}
-
-	public void exec(SessionManager manager) {
-		try {
-			manager.selectSession(this);
-		} catch (IOException e) {
-		}
-	}
-
-}
--- a/rep/Session.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/Session.java	Mon Nov 10 22:07:45 2008 +0900
@@ -4,35 +4,38 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import rep.channel.REPSocketChannel;
+import rep.handler.Editor;
+import rep.handler.REPNode;
+import rep.handler.Forwarder;
 
-public class Session extends HashMap<Integer,EditorPlus> {
+public class Session extends HashMap<Integer,REPNode> {
 	/**
 	 * 
 	 */
 	private static final long serialVersionUID = 1L;
-	private Forwarder masterEditor;
+	private REPNode masterEditor;
 	private int sessionID;
 	private String sessionName;
 	// isOnwer means this session has active channels(forwarders).
 	private boolean isOwner = false;
-	private Forwarder first;
-	private Forwarder last;
+	private REPNode first;
+	private REPNode last;
 	
-	public Session(int sid, String name, Forwarder editor) {
+	public Session(int sid, String name, REPNode editor) {
 		this(sid, editor);
 		sessionName = name;
 	}
 	
 
-	public Session(int sid, Forwarder editor) {
+	public Session(int sid, REPNode master) {
 		sessionID = sid;
-		if (editor!=null) {
+		if (master!=null) {
 			// we have a master
-			masterEditor = last = editor;
-			editor.setSID(sid);
-			put(editor.eid,editor);
-			if(editor.channel!=null) {
-				first = editor;
+			masterEditor = last = master;
+			master.setSID(sid);
+			put(master.eid,master);
+			if(master.channel!=null) {
+				first = master;
 				masterEditor.setNext(masterEditor);
 				isOwner = true;
 			}
@@ -42,15 +45,15 @@
 	/*
 	 * どこにlocal editorを入れても良いのだが、まとめた方が良いか?
 	 */
-	public void addForwarder(Forwarder forwarder) {
+	public void addForwarder(REPNode editor) {
 		// add a forwarder and connect this to the session 
-		forwarder.setSID(sessionID);
-		forwarder.setNext(last.getNextForwarder());
-		last.setNext(forwarder);
-		last = forwarder;
-		put(forwarder.eid,forwarder);
+		editor.setSID(sessionID);
+		editor.setNext(last.getNextForwarder());
+		last.setNext(editor);
+		last = editor;
+		put(editor.eid,editor);
 		isOwner = true;
-		if(first==null) first = forwarder;
+		if(first==null) first = editor;
 		
 		// printSessionDetail();
 	}
@@ -62,14 +65,14 @@
 		put(editor.eid,editor);
 	}
 	
-	public Collection<EditorPlus> getEditorList() {
+	public Collection<REPNode> getEditorList() {
 		return values();
 	}
 	
 	public int getSID() {
 		return sessionID;
 	}
-	public Forwarder getOwner() {
+	public REPNode getOwner() {
 		return masterEditor;
 	}
 	public String getName() {
@@ -78,14 +81,14 @@
 	
 	
 	public boolean deleteEditor(REPSocketChannel<REPCommand> channel) {
-		LinkedList<EditorPlus> toBeRemoved = new LinkedList<EditorPlus>();
-	    for (EditorPlus e:values() ) {
+		LinkedList<REPNode> toBeRemoved = new LinkedList<REPNode>();
+	    for (REPNode e:values() ) {
 			if (e.getChannel()==channel) {
 				unconnect((Forwarder)e);
 				toBeRemoved.add(e);
 			}
 		}
-	    for(EditorPlus e:toBeRemoved) {
+	    for(REPNode e:toBeRemoved) {
 	    	remove(e);
 	    }
 		return !toBeRemoved.isEmpty();
@@ -98,7 +101,7 @@
 	
 	private void unconnect(Forwarder e) {
 		boolean hasOwner = false;
-		for(EditorPlus e1:values()) {
+		for(REPNode e1:values()) {
 			Forwarder f = (Forwarder)e1;
 			if(f.next==e) {
 				f.next=e.next;
@@ -121,7 +124,7 @@
 	
 	
 	public Editor getEditor(REPSocketChannel<REPCommand> channel) {
-		for(EditorPlus editor : values()){
+		for(REPNode editor : values()){
 			if(editor.getChannel() == channel) {
 				return (Editor)editor;
 			}
@@ -132,14 +135,14 @@
 	
 	
 	public void closeSession() {
-		Forwarder f = first;
+		REPNode f = first;
 		REPCommand command = new REPCommand(REP.REPCMD_CLOSE, sessionID, REP.SM_EID.id, 0, 0, "");
 		if (f!=null)
 			f.send(command);
 	}
 	
-	public Forwarder getForwarder(REPSocketChannel<REPCommand> channel) {
-		Forwarder f = first;
+	public REPNode getForwarder(REPSocketChannel<REPCommand> channel) {
+		REPNode f = first;
 		while(f.channel!=channel) f = f.next;
 		SessionManager.logger.writeLog("getFirstForwarder="+f.next+"=>"+f.next.channel);
 		return f.next;
@@ -147,7 +150,7 @@
 
 
 	public void remove(SessionManager manager) {
-		for(EditorPlus editor : values()){
+		for(REPNode editor : values()){
 			if(editor.getChannel() !=null) 
 				unconnect((Forwarder)editor);
 			manager.editorList.remove(editor);
@@ -156,8 +159,8 @@
 
 
 	public void merge(Session s) {
-		for(EditorPlus editor : s.values()){
-			EditorPlus mine = get(editor.eid);
+		for(REPNode editor : s.values()){
+			REPNode mine = get(editor.eid);
 			if (mine==null) {
 				put(editor.eid,editor);
 			} else {
@@ -179,7 +182,7 @@
 	}
 
 
-	public void setFirstForwarder(Forwarder f) {
+	public void setFirstForwarder(REPNode f) {
 		f.setSID(sessionID);
 		put(f.eid,f);
 		f.setNext(f);
@@ -187,7 +190,7 @@
 	}
 
 	public void printSessionDetail() {
-		Forwarder f = first;
+		REPNode f = first;
 		if (f==null) return;
 		String log = "Session Detail ";
 		while (f!=null) {
--- a/rep/SessionManager.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/SessionManager.java	Mon Nov 10 22:07:45 2008 +0900
@@ -18,8 +18,18 @@
 import rep.channel.REPLogger;
 import rep.channel.REPServerSocketChannel;
 import rep.channel.REPSocketChannel;
-import rep.handler.PacketSet;
-import rep.handler.REPHandler;
+import rep.gui.CloseButtonEvent;
+import rep.gui.DoGUIUpdate;
+import rep.gui.SelectButtonEvent;
+import rep.gui.SessionManagerEvent;
+import rep.gui.SessionManagerEventListener;
+import rep.gui.SessionManagerGUI;
+import rep.gui.SessionManagerGUIimpl;
+import rep.handler.Dispatcher;
+import rep.handler.Editor;
+import rep.handler.REPNode;
+import rep.handler.FirstConnector;
+import rep.handler.Forwarder;
 import rep.channel.REPSelector;
 import rep.xml.SessionXMLDecoder;
 import rep.xml.SessionXMLEncoder;
@@ -61,7 +71,7 @@
 	private BlockingQueue<SessionManagerEvent> waitingEventQueue 
 		= new LinkedBlockingQueue<SessionManagerEvent>();;
 	// host name of this server. One of connecting SocketChannel's hostname
-	String myHost;
+	public String myHost;
 	// Single threaded write queueu. To avoid dead lock with too many writes.
 	private LinkedList<PacketSet> writeQueue = new LinkedList<PacketSet>();
 	private int receive_port;
@@ -75,7 +85,7 @@
 	SessionXMLDecoder decoder = new SessionXMLDecoder();
 	SessionXMLEncoder encoder = new SessionXMLEncoder();
 	// SocketChannel for our parent. At most one parent is allowed.
-	private Forwarder sm_join_channel;
+	private REPNode sm_join_channel;
 	// Routing table for session and session manager.
 	private RoutingTable routingTable = new RoutingTable(this);
 	private SessionManagerEvent execAfterConnect = null;;
@@ -118,7 +128,7 @@
 		//getAllByNameで取れた全てのアドレスに対してbindする
 		ssc.socket().bind(new InetSocketAddress(port));
 		ssc.register(selector, SelectionKey.OP_ACCEPT, 
-				new Forwarder(this));
+				new Dispatcher(this));  // FirstConnector?
 
 		sessionList = new SessionList();
 		smList = new SessionManagerList();
@@ -183,7 +193,7 @@
 		List<PacketSet> w = waitingCommandInMerge;
 		waitingCommandInMerge = new LinkedList<PacketSet>();
 		for(PacketSet p: w) {
-			Editor e = p.getEditor();
+			REPNode e = p.getEditor();
 			if(e.isMerging()) { // still merging do nothing
 				waitingCommandInMerge.add(p);
 			} else {
@@ -219,7 +229,7 @@
 	 */
 	private void close(REPSocketChannel<REPCommand> channel) {
 		REPSelectionKey<REPCommand>key = channel.keyFor1(selector);
-		REPHandler handler = (REPHandler)key.attachment();
+		REPNode handler = (REPNode)key.attachment();
 		key.cancel();
 		handler.cancel(channel);
 		// we have to remove session/enditor
@@ -250,7 +260,7 @@
 				 * A hadler throw IOException() in case of a trouble to
 				 * close the channel.
 				 */
-				REPHandler handler = (REPHandler)(key.attachment());
+				REPNode handler = (REPNode)key.attachment();
 				try {
 					handler.handle(key);
 				} catch (IOException e) {
@@ -261,7 +271,7 @@
 		}
 	}
 	
-	void registerChannel(REPSocketChannel<REPCommand> channel,Forwarder handler) throws IOException {
+	public void registerChannel(REPSocketChannel<REPCommand> channel,REPNode handler) throws IOException {
 		if(channel == null) {
 			return;
 		}
@@ -280,7 +290,7 @@
 	}
 
 
-	private void removeChannel(Forwarder channel) {
+	private void removeChannel(REPNode channel) {
 		REPSelectionKey<REPCommand> key = channel.channel.keyFor1(selector);
 		key.cancel();
 		try {
@@ -293,17 +303,17 @@
 	void updateGUI() {
 		//リストのコピーをGUIに渡す
 		LinkedList<Session> sList = new LinkedList<Session>(sessionList.values());
-		LinkedList<Editor> eList;
+		LinkedList<REPNode> eList;
 		if (false) { 
 			// local editor only 
-			eList = new LinkedList<Editor>();
-			for(Editor e:editorList.values()) {
+			eList = new LinkedList<REPNode>();
+			for(REPNode e:editorList.values()) {
 				if (getSMID(e.eid)==smList.sessionManagerID()) {
 					eList.add(e);
 				}
 			}
 		} else {
-			eList = new LinkedList<Editor>(editorList.values());
+			eList = new LinkedList<REPNode>(editorList.values());
 		}
 		//GUIに反映
 		Runnable doRun = new DoGUIUpdate(sList, eList, gui);
@@ -312,13 +322,13 @@
 
 
 
-	void setMyHostName(String localHostName) {
+	public void setMyHostName(String localHostName) {
 		myHost = localHostName + receive_port;
 		setHostToEditor(myHost);
 	}
 
 	private void setHostToEditor(String myHost2) {
-		for(Editor editor : editorList.values()){
+		for(REPNode editor : editorList.values()){
 			if (editor.channel!=null)
 				editor.setHost(myHost2);
 		}
@@ -344,7 +354,7 @@
 			REPSocketChannel<REPCommand> sessionchannel = REPSocketChannel.<REPCommand>create(new REPCommandPacker());
 			sessionchannel.connect(addr);
 			while(!sessionchannel.finishConnect());
-			Forwarder sm = new FirstConnector(this);
+			REPNode sm = new FirstConnector(this);
 			registerChannel(sessionchannel, sm);
 			sm_join(sm);
 		}catch (IOException e) {
@@ -359,7 +369,7 @@
 	 * channel に SMCMD_SM_JOIN command を送る。
 	 * @param channel
 	 */
-	private void sm_join(Forwarder channel){
+	private void sm_join(REPNode channel){
 		sm_join_channel = channel;
 		//SM_JOINコマンドを生成。
 		REPCommand command = new REPCommand();
@@ -387,7 +397,7 @@
 		int sid = event.getSID();
 		Session session = sessionList.get(sid);
 		if (session==null) throw new IOException();
-		Editor editor = (Editor)event.getEditor();
+		REPNode editor = event.getEditor();
 		if (editor.hasSession()) return;
 		// assert(getSMID(editor.eid)==smList.sessionManagerID());
 		// assert(editor.channel!=null);
@@ -395,12 +405,12 @@
 		selectSession0(sid, session, editor.getEID(), editor);
 	}
 
-	private void selectSession0(int sid, Session session, int eid, Editor editor) {
+	private void selectSession0(int sid, Session session, int eid, REPNode editor) {
 		if (editor.isDirect()&&editor.getEID()==eid) {
 			selectSession(sid, session, editor.getEID(), editor);
 		} else {
 			// we don't have this editor, search the editor first.
-			Forwarder next = routingTable.toSessionManager(getSMID(eid));
+			REPNode next = routingTable.toSessionManager(getSMID(eid));
 			// pass the select command to the next path.
 			REPCommand command = new REPCommand();
 			command.setCMD(REP.SMCMD_SELECT0);
@@ -415,7 +425,7 @@
 	 * Select Session Protocol handler
 	 *    called from GUI or incoming SMCMD_SELECT command.
 	 */
-	private void selectSession(int sid, Session session, int eid, Forwarder editor) {
+	private void selectSession(int sid, Session session, int eid, REPNode editor) {
 		if(session.hasOwner()){
 			// we have selected session.
 			REPCommand sendCommand = new REPCommand();
@@ -440,12 +450,12 @@
 	}
 
 	private void forwardSelect(int sid, Session session, int eid,
-			Forwarder editor) {
-		Forwarder next;
+			REPNode editor) {
+		REPNode next;
 		// session searching continue...
 		next = routingTable.toSessionManager(getSMID(sid));
 		// make a forwarding channel here
-		Forwarder f = createSessionDispatcher(sid, next);
+		REPNode f = createSessionForwarder(sid, next);
 		session.setFirstForwarder(f);
 		session.addForwarder(editor);
 		// pass the select command to the next path.
@@ -457,8 +467,9 @@
 		next.send(command);
 	}
 
-	private Forwarder createSessionDispatcher(int sid, Forwarder editor) {
-		Forwarder f = new Editor(this, false, makeID(editorList.newEid()));
+	private REPNode createSessionForwarder(int sid, REPNode editor) {
+		REPNode f = new Forwarder(this);
+		f.setEID(makeID(editorList.newEid()));
 		f.setChannel(editor.channel); // incoming channel
 		f.setHost(myHost);
 		f.setSID(sid);
@@ -479,9 +490,9 @@
 	 * Create new editor in this sessin manager. A dummy editor
 	 * is created also.
 	 */
-	public Editor newEditor(REPSocketChannel<REPCommand> channel) {
+	public REPNode newEditor(REPSocketChannel<REPCommand> channel) {
 		int eid =  makeID(editorList.newEid());
-		Editor editor = new Editor(this, eid, channel);
+		REPNode editor = new Editor(this, eid, channel);
 		editorList.add(editor);
 		return editor;
 	}
@@ -489,7 +500,7 @@
 	/*
 	 * Create new session.
 	 */
-	public Session newSession(Forwarder master) {
+	public Session newSession(REPNode master) {
 		int sid= makeID(sessionList.newSessionID());
 		Session session = new Session(sid, master);
 		sessionList.put(sid, session);
@@ -584,7 +595,7 @@
 	}
 
 
-	boolean sessionManage(Forwarder forwarder, REPCommand command) throws ClosedChannelException,
+	public boolean sessionManage(REPNode forwarder, REPCommand command) throws ClosedChannelException,
 			IOException {
 		switch(command.cmd){
 	
@@ -652,9 +663,9 @@
 			/*
 			 * finding joining editor, do not make the path.
 			 */
-			Forwarder editor  = editorList.get(command.eid);
+			REPNode editor  = editorList.get(command.eid);
 			if (editor==null|| !editor.isDirect()) {
-				Forwarder next = routingTable.toSessionManager(getSMID(command.eid));
+				REPNode next = routingTable.toSessionManager(getSMID(command.eid));
 				next.send(command);
 				break;
 			}
@@ -671,7 +682,7 @@
 			}
 			// Do not directly addForwarder(forwarder). It may be
 			// shared among sessions.
-			Forwarder f = createSessionDispatcher(command.sid, forwarder);
+			REPNode f = createSessionForwarder(command.sid, forwarder);
 			session.addForwarder(f); // f.next is set up here.
 			selectSession(command.sid, session, command.eid, forwarder);
 		}
@@ -731,8 +742,8 @@
 		return true;
 	}
 
-	private void registSessionManager(Forwarder forwarder, REPCommand command) {
-		Forwarder sm;
+	private void registSessionManager(REPNode forwarder, REPCommand command) {
+		REPNode sm;
 		int psid = command.eid;
 		if (forwarder.sid!=-1) {
 		// すでに channelはSessionManager Idを持っていて、
@@ -770,7 +781,7 @@
 	 * 指定されたeditorがlocalにあるかどうかを調べる。なければ、他に送る。戻って何回も探すことが
 	 * あり得るので、よろしくない。
 	 */
-	private void searchSelectedEditor(REPCommand command, Forwarder editor) {
+	private void searchSelectedEditor(REPCommand command, REPNode editor) {
 		for(;editor.isDirect();editor = editor.getNextForwarder()) {
 			if (editor.getEID()==command.eid) {
 				// select したeditor を見つけた
@@ -821,10 +832,10 @@
 	 * @param forwarder     Editor to be add
 	 * @param command
 	 */
-	public void registEditor(Forwarder forwarder,REPCommand command) {
+	public void registEditor(REPNode forwarder,REPCommand command) {
 		// make ack for PUT/JOIN. Do not send this to the editor,
 		// before select. After select, ack is sent to the editor. 
-		Editor editor;
+		REPNode editor;
 		if (getSMID(command.eid)==smList.sessionManagerID()) {
 			if (forwarder.isDirect()) {
 				editor = (Editor)forwarder;
@@ -880,7 +891,7 @@
 		execAfterConnect = null;
 	}
 
-	public void setParent(Forwarder fw) {
+	public void setParent(REPNode fw) {
 		smList.setParent(fw);
 	}
 	
@@ -890,5 +901,9 @@
 		return "rep.SessionManager-"+myId+"@"+myHost+":"+receive_port; 
 	}
 
+	public void addWaitingSessionManager(REPNode fw, REPCommand command) {
+		smList.addWaitingSessionManager(fw, command) ;
+	}
+
 
 }
--- a/rep/SessionManagerEvent.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-package rep;
-
-public interface SessionManagerEvent {
-
-	void exec(SessionManager manager);
-
-}
--- a/rep/SessionManagerEventListener.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-package rep;
-
-import java.io.IOException;
-
-//implemented class is SessionManager.
-
-public interface SessionManagerEventListener {
-	
-	public void buttonPressed(SessionManagerEvent event);
-	public void selectSession(SelectButtonEvent selectButtonEvent) throws IOException;
-	public void closeSession(SessionManagerEvent event);
-}
--- a/rep/SessionManagerGUI.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-package rep;
-
-import java.util.LinkedList;
-
-public interface SessionManagerGUI {
-
-	public void update(LinkedList<Session> slist, LinkedList<Editor> elist);
-
-	void invokeLater(Runnable doRun) ;
-}
\ No newline at end of file
--- a/rep/SessionManagerGUIimpl.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-package rep;
-
-import java.awt.Container;
-import java.util.LinkedList;
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
-
-import rep.gui.RPanel;
-
-
-public class SessionManagerGUIimpl implements Runnable, SessionManagerGUI {
-	
-	public static void main(String[] args){
-		SessionManagerGUIimpl gui = new SessionManagerGUIimpl(new SessionManagerEventListener() {
-			public void buttonPressed(SessionManagerEvent event) {
-			}
-			public void closeSession(SessionManagerEvent event) {
-			}
-			public void selectSession(SelectButtonEvent selectButtonEvent) {
-			}
-		});
-		Thread th = new Thread( gui ); 
-		th.start();
-	}
-
-	public SessionManagerGUIimpl(SessionManagerEventListener manager) {
-		rp = new RPanel();
-		rp.addREPActionListener(manager);
-		Thread th = new Thread(this);
-		th.start();
-	}
-
-	private RPanel rp;
-	private JFrame frame;
-
-	public void run() {
-		frame = new JFrame("SessionManager");
-		frame.setBounds(100, 100, 600, 300);
-		Container cont = frame.getContentPane();
-		cont.add(rp);
-
-		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-		frame.setVisible(true);
-		
-	}
-
-	/* (non-Javadoc)
-	 * @see rep.SessionManagerGUIint#update(java.util.LinkedList, java.util.LinkedList)
-	 */
-	public void update(LinkedList<Session> slist, LinkedList<Editor> elist) {
-		rp.setTableSession(slist);
-		rp.setTableEditor(elist);
-	}
-
-
-	public void invokeLater(Runnable doRun) {
-		SwingUtilities.invokeLater(doRun);
-	}
-
-}
\ No newline at end of file
--- a/rep/SessionManagerList.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/SessionManagerList.java	Mon Nov 10 22:07:45 2008 +0900
@@ -2,7 +2,10 @@
 
 import java.util.LinkedList;
 
-public class SessionManagerList extends LinkedList<Forwarder>{
+import rep.handler.REPNode;
+import rep.handler.NullForwarder;
+
+public class SessionManagerList extends LinkedList<REPNode>{
 
 	/**
 	 * 
@@ -10,11 +13,11 @@
 	private static final long serialVersionUID = 1L;
 	private int mySMID=0;
 	private int smid_root=0;
-	private Forwarder parent=new NullForwarder(null);
-	private LinkedList<Forwarder> waiting= new LinkedList<Forwarder>();
+	private REPNode parent=new NullForwarder(null);
+	private LinkedList<REPNode> waiting= new LinkedList<REPNode>();
 
 
-	public void setMaster(Forwarder f) {
+	public void setMaster(REPNode f) {
 		this.parent = f;
 	}
 
@@ -23,7 +26,7 @@
 	}
 
 	public void sendToSlaves(REPCommand repCmd) {
-		for(Forwarder channel : this){
+		for(REPNode channel : this){
 			channel.send(repCmd);
 		}
 	}
@@ -32,11 +35,11 @@
 		return !parent.isForwarder();
 	}
 
-	public int addNewSessionManager(Forwarder fw,REPCommand receivedCommand) {
-		add(fw);
+	public int addNewSessionManager(REPNode sm,REPCommand receivedCommand) {
+		add(sm);
 		int sid = ++smid_root;
-		fw.setSID(sid);
-		fw.setName(receivedCommand.string);
+		sm.setSID(sid);
+		sm.setName(receivedCommand.string);
 		return sid;
 	}
 
@@ -49,7 +52,7 @@
 		return mySMID;
 	}
 
-	public void addWaitingSessionManager(Forwarder fw, REPCommand command) {
+	public void addWaitingSessionManager(REPNode fw, REPCommand command) {
 		// SID assign 待ちのSessionManager Channelを登録する
 		waiting.add(fw);
 		
@@ -58,7 +61,7 @@
 	public void assignSessionManagerIDtoWaitingSM(int sid) {
 		// 待っていたSession Manager ChannelにSession IDを登録し,Session Manager List
 		// に登録する。この次のsm_join_ackでSIDが確定する。
-		Forwarder waiter;
+		REPNode waiter;
 		if ((waiter=waiting.poll())!=null) {
 			waiter.setSID(sid);
 			add(waiter);
@@ -67,11 +70,11 @@
 		assert false;
 	}
 
-	public void setParent(Forwarder fw) {
+	public void setParent(REPNode fw) {
 		parent = fw;
 	}
 	
-	public Forwarder parent() {
+	public REPNode parent() {
 		return parent;
 	}
 
--- a/rep/SessionManagerNode.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-package rep;
-
-import java.nio.channels.SocketChannel;
-
-public class SessionManagerNode {
-
-	public SessionManagerNode(SocketChannel channel) {
-	}
-
-}
--- a/rep/SessionViewer.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-package rep;
-
-import java.awt.Component;
-
-import javax.swing.JTree;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultMutableTreeNode;
-
-public class SessionViewer implements TreeSelectionListener {
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
-	DefaultMutableTreeNode nRoot = new DefaultMutableTreeNode("top");
-	DefaultMutableTreeNode nJapan = new DefaultMutableTreeNode("Session:1");
-	DefaultMutableTreeNode nUsa = new DefaultMutableTreeNode("Session:2");
-	DefaultMutableTreeNode nKantoh = new DefaultMutableTreeNode("Editor:1");
-	DefaultMutableTreeNode nKansai = new DefaultMutableTreeNode("Editor:2");
-	DefaultMutableTreeNode nTokyo = new DefaultMutableTreeNode("Editor:3");
-	private JTree tree;
-	SessionViewer() {
-		tree = new JTree(nRoot);
-		tree.setRootVisible(true);
-		tree.addTreeSelectionListener(this);
-		//getContentPane().add(tree);
-
-		nRoot.add(nJapan);
-		nRoot.add(nUsa);
-		nJapan.add(nKantoh);
-		nJapan.add(nKansai);
-		nUsa.add(nTokyo);
-		//nJapan.remove(0);
-
-		//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-		//setTitle("JTreeTest");
-		//setSize(200, 150);
-		//setVisible(true);
-	}
-	public void valueChanged(TreeSelectionEvent e) {
-		JTree tree = (JTree)e.getSource();
-		DefaultMutableTreeNode node =
-			(DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
-		if (node != null) {
-			System.out.println((String)node.getUserObject());
-		}
-	}
-	public static void main(String[] args) {
-		new SessionViewer();
-	}
-	public Component getTree() {
-		// TODO Auto-generated method stub
-		return tree;
-	}
-	public void addSessionTree(int sid) {
-		// TODO Auto-generated method stub
-		nRoot.add(new DefaultMutableTreeNode("Session:"+sid));
-	}
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/Translator.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,47 @@
+package rep;
+
+import rep.handler.REPNode;
+
+public interface Translator {
+
+	/*
+	 * Interface で分離する意味が良くわからない。Application毎に
+	 * Transltorを換えるつもりなのか?
+	 */
+	/**
+	 * 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);
+
+	/**
+	 * 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 boolean catchOwnCommand(REPNode editor);
+	
+	/**
+	 * Translate Command cmd that was received from SeMa.
+	 * @param cmd the command to be translated.
+	 * @return translated command.
+	 */
+	public void transReceiveCmd(REPNode next,REPCommand cmd);
+
+	/**
+	 * set the editor's id.
+	 * @param editor's id.
+	 */
+	public void setEid(int _eid);
+
+	boolean checkMergeConflict(REPCommand command);
+
+	public void getMergeAgain(REPNode editor);
+
+	public void startMerge(REPCommand cmd);
+
+	public boolean isMerging();
+
+	public void mergeAck();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/TranslatorImpl.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,228 @@
+package rep;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeSet;
+
+import rep.handler.REPNode;
+import rep.optimizers.REPCommandOptimizer;
+
+public class TranslatorImpl implements Translator{
+	public int eid;
+	
+	public REPCommandOptimizer optimizer;
+	private LinkedList<REPCommand> unMergedCmds;
+	public LinkedList<REPCommand> sentMergedList;
+	private LinkedList<REPCommand> mergeAgainList;
+	boolean merge_mode = false;
+
+	public TranslatorImpl(int _eid,REPCommandOptimizer opt){
+		eid = _eid;
+		optimizer = opt;
+		unMergedCmds = 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){
+		assert(cmd.eid==eid);
+		unMergedCmds.add(cmd);
+		
+		//マージ中にユーザから割り込みがあった場合
+		if(isMerging()){
+			mergeAgainList.add(cmd);
+		}
+		
+		return cmd;
+	}
+	/**
+	 * My command is returned from the session ring, and START_MERGE_ACK
+	 * is returned. At this
+	 * stage my writeQueue is empty, our editor is waiting for me.
+	 * Start merge process.
+	 * @param cmd
+	 */
+	public boolean catchOwnCommand(REPNode editor){
+		LinkedList<REPCommand> output = new LinkedList<REPCommand>();
+		LinkedList<REPCommand> cmds = new LinkedList<REPCommand>();
+				//スタック上にあるコマンドを全部undoコマンドにする
+		while ( !unMergedCmds.isEmpty() ){
+			REPCommand cmd0 = unMergedCmds.removeLast();
+			output.add( createUndo(cmd0) );
+			cmds.add(cmd0);
+		}
+
+		/* 必要な分だけソートして返却用のリストに追加  */
+		output.addAll( sortCmds(cmds) );
+
+		/* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる  */
+		output.addAll(cmds);
+		for(REPCommand c: cmds) {
+			output.add(c);
+			unMergedCmds.add(c);
+		}
+		return optimizedSend(editor,output);
+	}
+
+	/**
+	 * Sent optimized merged command list
+	 * @param editor 
+	 * @param output
+	 * @return if any sent commands output 
+	 */
+	public boolean optimizedSend(REPNode editor, LinkedList<REPCommand> output) {
+		List<REPCommand> output1 = optimizer.optimize(output);
+		if (output1.size()==0) {
+			merge_mode = false;
+			return false;
+		}
+		for(REPCommand c:output1) {
+			REPCommand m = new REPCommand(c);
+			m.setEID(REP.MERGE_EID.id);
+			m.setSEQID(editor.seq());
+			sentMergedList.add(m);
+			editor.send(m);
+		}				
+		return true;
+	}
+	
+	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(REPNode nextEditor,REPCommand cmd){
+		assert (cmd.eid != eid);
+		// nop command の挿入は Editor 側で行って、こちら側ではやらない
+		unMergedCmds.add(cmd);
+		if(cmd.cmd==REP.REPCMD_DELETE) {
+			// delete のundo用の文字列は、外に出す意味はない
+			cmd = new REPCommand(cmd);
+			cmd.string=null;
+		}
+		nextEditor.send(cmd);
+	}
+
+	public void setEid(int _eid){
+		eid = _eid;
+	}
+
+	public boolean checkMergeConflict(REPCommand command) {
+		REPCommand prev = sentMergedList.remove();
+		assert (prev.seq==command.seq);
+		
+		if(mergeAgainList.size() > 0){
+			mergeAgainList.add(command);
+			return true;
+		}
+		if(sentMergedList.size()==0) {
+			merge_mode=false;
+		}
+		return false;
+	}
+
+	public void getMergeAgain(REPNode editor) {
+		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();
+		optimizedSend(editor, returnCommand);
+	}
+
+	public boolean isFinished() {
+		if(unMergedCmds.size() > 0) return false;
+		if(sentMergedList.size() > 0) return false;
+		return true;
+	}
+
+	public boolean isMerging() {
+		return merge_mode;
+	}
+
+	public void startMerge(REPCommand cmd) {
+		merge_mode = true;
+	}
+
+	public void mergeAck() {
+	}
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/CloseButtonEvent.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,24 @@
+package rep.gui;
+
+import rep.Session;
+import rep.SessionManager;
+
+public class CloseButtonEvent implements SessionManagerEvent {
+
+	private Session session;
+	private SessionManagerEventListener listener;
+
+	public CloseButtonEvent(Session session, SessionManagerEventListener listener) {
+		this.session = session;
+		this.listener = listener;
+	}
+	
+	public Session getSession(){
+		return session;
+	}
+
+	public void exec(SessionManager manager) {
+		listener.closeSession(this);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/ConnectButtonEvent.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,21 @@
+package rep.gui;
+
+import rep.SessionManager;
+
+public class ConnectButtonEvent implements SessionManagerEvent{
+
+	private String host;
+
+	public ConnectButtonEvent(String host) {
+		this.host = host;
+	}
+
+	public String getHost() {
+		return host;
+	}
+
+	public void exec(SessionManager manager) {
+		manager.connectSessionManager(host);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/DoGUIUpdate.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,23 @@
+package rep.gui;
+
+import java.util.LinkedList;
+
+import rep.Session;
+import rep.handler.REPNode;
+
+public class DoGUIUpdate implements Runnable{
+	
+	private LinkedList<Session> slist;
+	private LinkedList<REPNode> elist;
+	private SessionManagerGUI gui;
+
+	public DoGUIUpdate(LinkedList<Session> _slist, LinkedList<REPNode> list, SessionManagerGUI _gui) {
+		gui = _gui; 
+		slist = _slist; elist = list;
+	}
+	
+	public void run() {
+		gui.update(slist, elist);
+	}
+
+}
--- a/rep/gui/RPanel.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/gui/RPanel.java	Mon Nov 10 22:07:45 2008 +0900
@@ -15,16 +15,10 @@
 import javax.swing.JTextField;
 import javax.swing.table.DefaultTableModel;
 
-import rep.CloseButtonEvent;
-import rep.ConnectButtonEvent;
-import rep.Editor;
-import rep.EditorPlus;
-import rep.Forwarder;
 import rep.REPCommand;
-import rep.SelectButtonEvent;
 import rep.Session;
-import rep.SessionManagerEventListener;
 import rep.channel.REPSocketChannel;
+import rep.handler.REPNode;
 
 import java.util.*;
 
@@ -49,7 +43,7 @@
 	private DefaultTableModel s_tableModel = new DefaultTableModel(session_column, 0);
 	private DefaultTableModel e_tableModel = new DefaultTableModel(editor_column, 0);
 	//LinkedList<SessionPlus> s_list = new LinkedList<SessionPlus>();
-	LinkedList<EditorPlus> e_list = new LinkedList<EditorPlus>();
+	LinkedList<REPNode> e_list = new LinkedList<REPNode>();
 	private String s_host;
 	private String s_port;
 	private String s_file;
@@ -60,7 +54,7 @@
 	private JButton selectButton;
 	private JButton closeButton;
 	private SessionManagerEventListener listener;
-	private LinkedList<Editor> editorList;
+	private LinkedList<REPNode> editorList;
 	private LinkedList<Session> sessionList;
 
 	public RPanel() {
@@ -159,15 +153,15 @@
 		}
 	}
 
-	public void setTableEditor(LinkedList<Editor> list) {
+	public void setTableEditor(LinkedList<REPNode> elist) {
 		/*
 		 * Editor.eid is unique in a session, we cannot use.
 		 * number it simply based on the order in the list 
 		 */
 		e_tableModel.setRowCount(0);
-		editorList = list;
+		editorList = elist;
 		int i=0;
-		for(Forwarder editor : list){
+		for(REPNode editor : elist){
 			setTableEditor(i++, editor.getChannel());
 		}
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/SelectButtonEvent.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,34 @@
+package rep.gui;
+
+import java.io.IOException;
+
+import rep.Session;
+import rep.SessionManager;
+import rep.handler.REPNode;
+
+public class SelectButtonEvent implements SessionManagerEvent{
+
+	private int sid;
+	private REPNode editor;
+
+	public SelectButtonEvent(REPNode editorPlus, Session session) {
+		this.editor = editorPlus;
+		this.sid = session.getSID();
+	}
+
+	public int getSID() {
+		return sid;
+	}
+
+	public REPNode getEditor() {
+		return editor;
+	}
+
+	public void exec(SessionManager manager) {
+		try {
+			manager.selectSession(this);
+		} catch (IOException e) {
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/SessionManagerEvent.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,9 @@
+package rep.gui;
+
+import rep.SessionManager;
+
+public interface SessionManagerEvent {
+
+	void exec(SessionManager manager);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/SessionManagerEventListener.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,13 @@
+package rep.gui;
+
+import java.io.IOException;
+
+
+//implemented class is SessionManager.
+
+public interface SessionManagerEventListener {
+	
+	public void buttonPressed(SessionManagerEvent event);
+	public void selectSession(SelectButtonEvent selectButtonEvent) throws IOException;
+	public void closeSession(SessionManagerEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/SessionManagerGUI.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,13 @@
+package rep.gui;
+
+import java.util.LinkedList;
+
+import rep.Session;
+import rep.handler.REPNode;
+
+public interface SessionManagerGUI {
+
+	public void update(LinkedList<Session> slist, LinkedList<REPNode> elist);
+
+	void invokeLater(Runnable doRun) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/gui/SessionManagerGUIimpl.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,61 @@
+package rep.gui;
+
+import java.awt.Container;
+import java.util.LinkedList;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import rep.Session;
+import rep.handler.REPNode;
+
+
+public class SessionManagerGUIimpl implements Runnable, SessionManagerGUI {
+	
+	public static void main(String[] args){
+		SessionManagerGUIimpl gui = new SessionManagerGUIimpl(new SessionManagerEventListener() {
+			public void buttonPressed(SessionManagerEvent event) {
+			}
+			public void closeSession(SessionManagerEvent event) {
+			}
+			public void selectSession(SelectButtonEvent selectButtonEvent) {
+			}
+		});
+		Thread th = new Thread( gui ); 
+		th.start();
+	}
+
+	public SessionManagerGUIimpl(SessionManagerEventListener manager) {
+		rp = new RPanel();
+		rp.addREPActionListener(manager);
+		Thread th = new Thread(this);
+		th.start();
+	}
+
+	private RPanel rp;
+	private JFrame frame;
+
+	public void run() {
+		frame = new JFrame("SessionManager");
+		frame.setBounds(100, 100, 600, 300);
+		Container cont = frame.getContentPane();
+		cont.add(rp);
+
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.setVisible(true);
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see rep.SessionManagerGUIint#update(java.util.LinkedList, java.util.LinkedList)
+	 */
+	public void update(LinkedList<Session> slist, LinkedList<REPNode> elist) {
+		rp.setTableSession(slist);
+		rp.setTableEditor(elist);
+	}
+
+
+	public void invokeLater(Runnable doRun) {
+		SwingUtilities.invokeLater(doRun);
+	}
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/handler/Dispatcher.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,77 @@
+package rep.handler;
+
+import java.io.IOException;
+
+import rep.REPCommand;
+import rep.Session;
+import rep.SessionManager;
+import rep.channel.REPSelectionKey;
+import rep.channel.REPSocketChannel;
+
+/**
+ * @author kono
+ *    Handle SessionManager incoming Channel
+ *    SessionManager Command and Multiplexed Editor Command come here.
+ *    Dispatch Editor command according to the session and the channel.
+ */
+public class Dispatcher extends Forwarder {
+
+	public Dispatcher(SessionManager manager) {
+		super(manager);
+	}
+
+	public void setQuit2(REPCommand cmd) {
+		send(cmd);
+	}
+
+	public boolean manage(REPCommand command) {
+		next.send(command);
+		return true;
+	}
+
+	public String toString(){
+		return ("Dispatcher:" + channel);
+	}
+	
+
+	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
+		/*
+		 * SessionManagerから来たコマンドは、Editor関係のコマンドは、
+		 * sessionとeidを判定して、そのeditorにforwardしてやれば良い。
+		 * 残りは、manager.manage() で処理する。
+		 */
+		REPSocketChannel<REPCommand> channel = key.channel1();
+		REPCommand command = channel.read();
+		SessionManager.logger.writeLog("REPHandlerImpl.handle() : command = " + command);
+		if (manager.sessionManage(this, command)) return;
+		
+		distpatchToEditor(channel, command);
+	}
+
+	private void distpatchToEditor(REPSocketChannel<REPCommand> channel,
+			REPCommand command) throws IOException {
+		Session s = manager.getSession(command.sid);
+		if (s==null) throw new IOException();
+		REPNode f = s.getForwarder(channel);
+		if (f==null) throw new IOException();
+		if (!f.isDirect()) {
+			// another forwarder, pass it to the next session manager
+			f.send(command); 
+			return;
+		}
+		/*
+		 * local editor case. 
+		 */
+		Editor editor = (Editor)f;
+		editor.forwardedCommandManage(command, this);
+	}
+
+
+	public void setNext(REPNode f) {
+		next = f;
+	}
+
+	public boolean isMerging() {
+		return false;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/handler/Editor.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,249 @@
+package rep.handler;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import rep.PacketSet;
+import rep.REP;
+import rep.REPCommand;
+import rep.SessionManager;
+import rep.Translator;
+import rep.TranslatorImpl;
+import rep.channel.REPSelectionKey;
+import rep.channel.REPSocketChannel;
+import rep.optimizers.*;
+
+public class Editor extends Forwarder {
+
+	private Translator translator;
+	private List<REPCommand> sentList = new LinkedList<REPCommand>();
+	// REPCommands we are going to send to the next editor
+	//private REPCommand quit2 = null;
+	private SessionManager manager;
+	private REPCommand quit2=null;
+
+	public Editor(SessionManager manager,boolean doOptimize,int editorNo){
+		super(manager);
+		this.manager = manager;
+		eid = editorNo;
+		REPCommandOptimizer optimizer;
+		if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ
+		else            optimizer = new NullOptimizer();         //なにもしないけどOptimizer.
+		translator = new TranslatorImpl(eid,optimizer);
+		
+	}
+
+	public Editor(SessionManager manager,int editorNo, REPSocketChannel<REPCommand> channel){
+		this(manager,false,editorNo);
+		this.channel = channel;
+	}
+
+	public void translate(REPCommand command){
+
+		if(command.eid == eid){
+			//エディタからの新たな編集コマンド
+			if (next==this) return; // singleton case
+			translator.transSendCmd(command);
+			sentList.add(new REPCommand(command));
+			assert(sentList.size()<limit);
+			next.send(command);
+			return;
+		} else if(command.eid == REP.MERGE_EID.id){
+			//マージコマンドが返ってきた
+			if(translator.checkMergeConflict(command)){
+				//マージ中にエディタからの割り込みがあった場合
+				translator.getMergeAgain(this);
+			}
+			checkEndMerge();
+		} else if(command.eid == next.getEID()){
+			// 次のEditorで一周するコマンドが来た
+			if(next==this) return; // singleton case
+			// これは、distributed case では、うまくいかないので、送り先のforwarder で処理する。
+			if (next.isDirect())
+				((Editor) next).checkReturnedCommand(command);
+			else
+				next.send(command);
+		} else {
+			//他のエディタからの編集コマンド
+			assert (command.eid!=REP.MERGE_EID.id && command.eid!=eid );
+			if (manager.hasWaitingCommand(channel)) {
+				// We cannot do this operation before watingCommandQueue.
+				manager.addWaitingCommand(new PacketSet(channel, this, command));
+				return;
+			}		
+			if(!isMerging()) {
+				translator.transReceiveCmd(next,command);
+				return;
+			}
+			manager.addWaitingCommand(new PacketSet(getChannel(), this, new REPCommand(command)));
+		}
+		return;
+	}
+
+	boolean merge(REPCommand command) {
+		//マージして送信
+		return translator.catchOwnCommand(this);
+	}
+
+	void checkReturnedCommand(REPCommand command) {
+		REPCommand prev = sentList.remove(0);
+		if (prev==null || prev.seq != command.seq || prev.eid!=command.eid) {
+			String err = "Editor.checkReturnedCommand() : command = " + command + " prev=";
+			err += prev==null?"null":prev.toString();
+			SessionManager.logger.writeLog(err);
+			assert(false);
+		}
+
+		// START_MERGE を送る
+		//    送らないで良い場合もある?
+		REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,"");
+		send(cmd);
+		// Session Manager 側で、このeditorへの他のeditorからの
+		// 入力を止めて、merge にそなえる。merge は、eidtor 側から
+		// ACKが来てから始まる。
+		translator.startMerge(cmd);
+		return;
+	}
+
+	@Override
+	public void setQuit2(REPCommand cmd) {
+		quit2 = cmd;
+		checkQuit();
+		// do not send quit2 until we received all pending
+		// command
+	}
+
+	@Override
+	public void setEID(int eid) {
+		this.eid = eid;
+		translator.setEid(eid);
+	}
+	
+	public String toString(){
+		return ("Editor eid="+eid+" sid="+sid+" " + host  + ":" + file);
+	}
+
+	public boolean isMerging() {
+		return translator.isMerging();
+	}
+
+	
+
+	void checkEndMerge() {
+		if(translator.isMerging()) return;
+		REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,eid,sid,seq(),0,"");
+		send(mergeEnd);				
+		if (quit2!=null) checkQuit();
+	}
+
+	private boolean checkQuit() {
+		if (sentList.size()==0&&!isMerging()) {
+			send(quit2);
+			quit2 = null;
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public boolean manage(REPCommand receivedCommand) {
+		
+		
+		switch(receivedCommand.cmd){
+		// Editor Command
+		
+		case REPCMD_DELETE:
+		case REPCMD_INSERT:
+		case REPCMD_NOP:
+		{
+			translate(receivedCommand);
+			break;
+		}
+
+		case SMCMD_START_MERGE_ACK:
+		{
+			// マージの処理と次のエディタへコマンドを送信する処理
+			translator.mergeAck();
+			if (!merge(receivedCommand)) {
+				// nothing to do, send END_MERGE
+				checkEndMerge();
+			}
+			break;
+		}
+		case SMCMD_QUIT:
+		{
+			next.send(receivedCommand);
+			break;
+		}
+		case SMCMD_QUIT_2:
+		{
+			// QUIT_2 is returned.
+			if (receivedCommand.eid!=eid) {
+				// stop this editor unless this is the start, starter will stopped
+				// by QUIT_2_ACK
+				manager.remove(this);
+			}
+			// don't send quit_2 directly to the editor until all pending
+			// merge is processed.
+			//   this does not work in distributed case.
+			if (next.isDirect())
+				next.setQuit2(receivedCommand);
+			else
+				next.send(receivedCommand);
+			break;
+		}
+		case SMCMD_QUIT_2_ACK:
+		{
+			manager.remove(this);
+			break;
+		}
+		default:
+			return false;
+		}
+		return true;
+	}
+	
+
+	@Override
+	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
+		REPSocketChannel<REPCommand> channel = key.channel1();
+		REPCommand command = channel.read();
+		SessionManager.logger.writeLog("REPHandlerImpl.handle() read : command = " + command +" from "+channel);
+		if (manager.sessionManage(this, command)) return;
+		manage(command);
+	}
+
+	@Override
+	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
+		manager.remove(socketChannel);
+	}
+
+	public boolean isMaster() {
+		return mode==REP.SMCMD_PUT;
+	}
+	
+	/* Handle special case first, usually these cases
+	 * are handled in the next Editor in a session manager, but 
+	 * it is forwarded here.
+	 */
+	public void forwardedCommandManage(REPCommand command, REPNode forwarder) {
+		if (command.cmd==REP.SMCMD_QUIT_2) {
+			// we have to wait next editor's finishing before sending this.
+			// this is odd, but the editor itself does not know it's merging
+			// state. Only this session manager knows it.
+			setQuit2(command);
+		} else if (command.eid==eid) {
+			// if we handle in editor.manage(), this editor cannot distinguish this
+			// and user input command from the editor.
+			switch(command.cmd) {
+			case REPCMD_DELETE:
+			case REPCMD_INSERT:
+			case REPCMD_NOP:
+				checkReturnedCommand(command);
+				return;
+			}
+		} 
+		manage(command);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/handler/FirstConnector.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,85 @@
+package rep.handler;
+
+import java.io.IOException;
+
+import rep.REPCommand;
+import rep.Session;
+import rep.SessionManager;
+import rep.channel.REPSelectionKey;
+import rep.channel.REPSocketChannel;
+
+public class FirstConnector extends Forwarder {
+
+	public FirstConnector(SessionManager manager) {
+		super(manager);
+	}
+	
+	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
+		manager.remove(socketChannel);
+	}
+
+	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
+		/*
+		 * 接続要求は、EditorかSlave Editorで、
+		 *    join, put, sm_join
+		 * が来る。それ以外はエラー。master もありか?
+		 *      sm_join_ack
+		 */
+		REPNode fw;
+		REPSocketChannel<REPCommand> channel = key.channel1();
+		REPCommand command = channel.read();
+		SessionManager.logger.writeLog("FirstConnector: command = " + command);
+		switch(command.cmd) {
+		case SMCMD_JOIN: 
+		{
+			//どのSessionにも属さないエディタをリストに追加
+			//エディタとchannelは1対1 (ではないかも)
+			//エディタが新しくputする場合は新しくソケットを作る
+			//   1対1でない場合は、multiplexerを挿めば良い
+			REPNode editor = manager.newEditor(channel);
+			editor.setHost(manager.myHost);
+			command.eid = editor.eid;
+			command.sid = -1;
+			editor.setSID(-1);
+			fw = editor;
+			break;
+		}
+		case SMCMD_PUT:
+		{
+			//  新しいeditorとsessionをここで作る。eid,sidは、
+			//  session manager IDが付いているので、global unique
+			REPNode editor = manager.newEditor(channel);
+			Session session = manager.newSession(editor);
+			session.setName(command.string);
+			editor.setName(command.string);
+			editor.setSID(session.getSID());
+			command.eid = editor.eid;
+			command.sid = editor.sid;
+			fw = editor;
+			break;
+		}
+		case SMCMD_SM_JOIN:
+		{
+			fw = new Dispatcher(manager);
+			manager.addWaitingSessionManager(fw, command);
+			break;
+		}
+		case SMCMD_SM_JOIN_ACK:
+			manager.setSessionManagerID(command.sid);
+			manager.afterConnect();
+			fw = new Dispatcher(manager);
+			manager.setParent(fw);
+			break;
+		default: throw new IOException();
+		}
+		//myHost を設定。
+		//立ち上げ時にやるとlocalhostしか取れない
+		if(manager.myHost == null) manager.setMyHostName(getLocalHostName());
+		fw.setMode(command.cmd);
+		fw.setHost(manager.myHost);
+		manager.registerChannel(channel, fw);
+		manager.sessionManage(fw, command);
+	
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/handler/Forwarder.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,96 @@
+package rep.handler;
+
+import java.io.IOException;
+
+import rep.PacketSet;
+import rep.REP;
+import rep.REPCommand;
+import rep.SessionManager;
+import rep.channel.REPLogger;
+import rep.channel.REPSelectionKey;
+import rep.channel.REPSocketChannel;
+
+/**
+ * @author kono
+ *    Forward Editor Command to the other Session Manager
+ *    Basic send API is supported.
+ */
+public class Forwarder extends REPNode  {
+	int seq = 0;
+	// REPCommands we sent to the next editor
+	final int limit=100; // debugging purpose, assert check only
+	final REPLogger ns = REPLogger.singleton();
+	SessionManager manager;
+	public REP mode = null;
+	
+	public Forwarder(SessionManager manager) {
+		this.manager = manager;
+	}
+
+	public int seq() {
+		return seq++;
+	}
+
+	public void send(REPCommand command) {
+		assert(command!=null);
+		assert(channel!=null);
+		REPCommand c = new REPCommand(command);
+		manager.addWriteQueue(new PacketSet(channel,null,  c));
+	}
+	
+	public void sendWithSeq(REPCommand command) {
+		assert(command!=null);
+		assert(channel!=null);
+		REPCommand c = new REPCommand(command);
+		c.setSEQID(seq());
+		manager.addWriteQueue(new PacketSet(channel,null,  c));
+	}
+	
+	public REPSocketChannel<REPCommand> getChannel() {
+		return channel;
+	}
+	
+	public void setChannel(REPSocketChannel<REPCommand> channel) {
+		this.channel = channel;
+	}
+
+	public void setQuit2(REPCommand cmd) {
+		send(cmd);
+	}
+
+	public void setNext(Forwarder next) {
+		this.next = next;
+	}
+	
+	public REPNode getNextForwarder() {
+		return next;
+	}
+
+	public boolean manage(REPCommand command) {
+		next.send(command);
+		return true;
+	}
+
+	public String toString(){
+		return ("Forwarder:" + channel);
+	}
+	
+	public String getLocalHostName() {
+		return channel.getLocalHostName();
+	}
+
+	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
+		manager.remove(socketChannel);
+	}
+
+	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
+		assert false;
+	}
+
+
+	public boolean isMerging() {
+		return false;
+	}
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/handler/NullForwarder.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,43 @@
+package rep.handler;
+
+import java.io.IOException;
+
+import rep.REPCommand;
+import rep.SessionManager;
+import rep.channel.REPSelectionKey;
+import rep.channel.REPSocketChannel;
+
+public class NullForwarder extends Forwarder {
+
+	public NullForwarder(SessionManager manager) {
+		super(manager);
+	}
+
+	public void send(REPCommand command) {
+		
+	}
+	public void cancel(REPSocketChannel<REPCommand> socketChannel) {
+
+	}
+
+	public void handle(REPSelectionKey<REPCommand> key) throws IOException {
+
+	}
+
+	public boolean manage(REPCommand command) {
+		return true;
+	}
+
+	public boolean isEditor() {
+		return false;
+	}
+	
+	public boolean isForwarder() {
+		return false;
+	}
+
+	public boolean isDirect() {
+		return false;
+	}
+
+}
--- a/rep/handler/PacketSet.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-package rep.handler;
-
-import rep.Editor;
-import rep.REPCommand;
-import rep.channel.REPSocketChannel;
-
-public class PacketSet {
-
-	public REPSocketChannel<REPCommand> channel;
-	public Editor editor;
-	public REPCommand command;
-
-	public PacketSet(REPSocketChannel<REPCommand> channel, Editor editor, REPCommand command) {
-		this.channel = channel;
-		this.editor = editor;
-		this.command = command;
-	}
-
-	public Editor getEditor() {
-		return editor;
-	}
-	
-
-}
--- a/rep/handler/REPHandler.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-package rep.handler;
-
-import java.io.IOException;
-
-import rep.REPCommand;
-import rep.channel.REPSelectionKey;
-import rep.channel.REPSocketChannel;
-
-public interface REPHandler {
-	void handle(REPSelectionKey<REPCommand> key) throws IOException;
-
-	void cancel(REPSocketChannel<REPCommand> socketChannel);
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rep/handler/REPNode.java	Mon Nov 10 22:07:45 2008 +0900
@@ -0,0 +1,130 @@
+package rep.handler;
+
+import java.io.IOException;
+
+import rep.REP;
+import rep.REPCommand;
+import rep.channel.REPSelectionKey;
+import rep.channel.REPSocketChannel;
+
+public abstract class REPNode {
+
+	public int eid; // globally unique
+	public int sid=-1; // globally unique
+	public String host;
+	public String file;
+	public REP mode;
+	public REPSocketChannel<REPCommand> channel;
+	public REPNode next;
+	
+	public REPNode() {
+		
+	}
+	
+	public REPNode(int eid, REPSocketChannel<REPCommand> channel) {
+		this.eid = eid;
+		this.channel = channel;
+	}
+
+	public String getName() {
+		return file;
+	}
+
+	public void setName(String string) {
+		file = string;
+	}
+
+
+	public void setSID(int sid) {
+		this.sid = sid;
+	}
+	
+	public int getSID() {
+		return sid;
+	}
+
+	public boolean hasSession() {
+		return sid != -1;
+	}
+	
+	public String toString(){
+		return ("Editor:" + eid);
+	}
+
+	public void setEID(int eid) {
+		this.eid = eid;
+	}
+	
+	public int getEID(){
+		return eid;
+	}
+
+	public void setHost(String host){
+		if (channel!=null)
+			this.host = host;
+	}
+
+	
+	public String getHost(){
+		return host;
+	}
+	public REPSocketChannel<REPCommand> getChannel(){
+		return channel;
+		
+	}
+	public void setChannel(REPSocketChannel<REPCommand> channel) {
+		this.channel = channel;		
+	}
+
+	public void merge(REPNode editor) {
+		if (sid==-1) sid = editor.sid;
+		if (file==null) file = editor.file;
+		if (host==null) host = editor.host;
+	}
+
+	public abstract void handle(REPSelectionKey<REPCommand> key) throws IOException;
+
+
+	public abstract void cancel(REPSocketChannel<REPCommand> channel1) ;
+
+	public abstract String getLocalHostName();
+
+
+	public abstract void send(REPCommand command) ;
+
+
+	public abstract void setQuit2(REPCommand receivedCommand) ;
+
+	public abstract int seq() ;
+
+	public abstract boolean isMerging() ;
+
+
+	public abstract boolean manage(REPCommand command) ;
+
+
+	public void setMode(REP cmd) {
+		mode = cmd;
+	}
+
+	public boolean isEditor() {
+		return mode==REP.SMCMD_JOIN||mode==REP.SMCMD_PUT;
+	}
+	
+	public boolean isForwarder() {
+		return mode==REP.SMCMD_SM_JOIN||mode==REP.SMCMD_SM_JOIN_ACK;
+	}
+
+	public boolean isDirect() {
+		return isEditor();
+	}
+
+	public REPNode getNextForwarder() {
+		return next;
+	}
+	public void setNext(REPNode f) {
+		next = f;
+	}
+	
+
+}
--- a/rep/translator/Translator.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-package rep.translator;
-
-import rep.Editor;
-import rep.Forwarder;
-import rep.REPCommand;
-
-public interface Translator {
-
-	/*
-	 * Interface で分離する意味が良くわからない。Application毎に
-	 * Transltorを換えるつもりなのか?
-	 */
-	/**
-	 * 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);
-
-	/**
-	 * 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 boolean catchOwnCommand(Editor editor);
-	
-	/**
-	 * Translate Command cmd that was received from SeMa.
-	 * @param cmd the command to be translated.
-	 * @return translated command.
-	 */
-	public void transReceiveCmd(Forwarder nextEditor,REPCommand cmd);
-
-	/**
-	 * set the editor's id.
-	 * @param editor's id.
-	 */
-	public void setEid(int _eid);
-
-	boolean checkMergeConflict(REPCommand command);
-
-	public void getMergeAgain(Editor editor);
-
-	public void startMerge(REPCommand cmd);
-
-	public boolean isMerging();
-
-	public void mergeAck();
-}
--- a/rep/translator/TranslatorImpl.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-package rep.translator;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TreeSet;
-
-import rep.Editor;
-import rep.Forwarder;
-import rep.REPCommand;
-import rep.REP;
-import rep.optimizers.REPCommandOptimizer;
-
-public class TranslatorImpl implements Translator{
-	public int eid;
-	
-	public REPCommandOptimizer optimizer;
-	private LinkedList<REPCommand> unMergedCmds;
-	public LinkedList<REPCommand> sentMergedList;
-	private LinkedList<REPCommand> mergeAgainList;
-	boolean merge_mode = false;
-
-	public TranslatorImpl(int _eid,REPCommandOptimizer opt){
-		eid = _eid;
-		optimizer = opt;
-		unMergedCmds = 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){
-		assert(cmd.eid==eid);
-		unMergedCmds.add(cmd);
-		
-		//マージ中にユーザから割り込みがあった場合
-		if(isMerging()){
-			mergeAgainList.add(cmd);
-		}
-		
-		return cmd;
-	}
-	/**
-	 * My command is returned from the session ring, and START_MERGE_ACK
-	 * is returned. At this
-	 * stage my 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.removeLast();
-			output.add( createUndo(cmd0) );
-			cmds.add(cmd0);
-		}
-
-		/* 必要な分だけソートして返却用のリストに追加  */
-		output.addAll( sortCmds(cmds) );
-
-		/* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる  */
-		output.addAll(cmds);
-		for(REPCommand c: cmds) {
-			output.add(c);
-			unMergedCmds.add(c);
-		}
-		return optimizedSend(editor,output);
-	}
-
-	/**
-	 * Sent optimized merged command list
-	 * @param editor 
-	 * @param output
-	 * @return if any sent commands output 
-	 */
-	public boolean optimizedSend(Editor editor, LinkedList<REPCommand> output) {
-		List<REPCommand> output1 = optimizer.optimize(output);
-		if (output1.size()==0) {
-			merge_mode = false;
-			return false;
-		}
-		for(REPCommand c:output1) {
-			REPCommand m = new REPCommand(c);
-			m.setEID(REP.MERGE_EID.id);
-			m.setSEQID(editor.seq());
-			sentMergedList.add(m);
-			editor.send(m);
-		}				
-		merge_mode = true;
-		return true;
-	}
-	
-	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.add(cmd);
-		if(cmd.cmd==REP.REPCMD_DELETE) {
-			// delete のundo用の文字列は、外に出す意味はない
-			cmd = new REPCommand(cmd);
-			cmd.string=null;
-		}
-		nextEditor.send(cmd);
-	}
-
-	public void setEid(int _eid){
-		eid = _eid;
-	}
-
-	public boolean checkMergeConflict(REPCommand command) {
-		REPCommand prev = sentMergedList.remove();
-		assert (prev.seq==command.seq);
-		
-		if(mergeAgainList.size() > 0){
-			mergeAgainList.add(command);
-			return true;
-		}
-		if(sentMergedList.size()==0) {
-			merge_mode=false;
-		}
-		return false;
-	}
-
-	public void getMergeAgain(Editor editor) {
-		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();
-		optimizedSend(editor, returnCommand);
-	}
-
-	public boolean isFinished() {
-		if(unMergedCmds.size() > 0) return false;
-		if(sentMergedList.size() > 0) return false;
-		return true;
-	}
-
-	public boolean isMerging() {
-		return merge_mode;
-	}
-
-	public void startMerge(REPCommand cmd) {
-		merge_mode = true;
-	}
-
-	public void mergeAck() {
-	}
-	
-
-
-
-}
--- a/rep/xml/SessionXMLDecoder.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/xml/SessionXMLDecoder.java	Mon Nov 10 22:07:45 2008 +0900
@@ -13,9 +13,9 @@
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
-import rep.Editor;
 import rep.Session;
 import rep.SessionList;
+import rep.handler.Editor;
 
 public class SessionXMLDecoder {
 
--- a/rep/xml/SessionXMLEncoder.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/rep/xml/SessionXMLEncoder.java	Mon Nov 10 22:07:45 2008 +0900
@@ -14,9 +14,9 @@
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import rep.EditorPlus;
 import rep.Session;
 import rep.SessionList;
+import rep.handler.REPNode;
 
 public class SessionXMLEncoder {
 	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
@@ -64,7 +64,7 @@
 			root.appendChild(elementSession);
 			elementSession.setAttribute("sid", Integer.toString(session.getSID()));
 
-			for(EditorPlus editor : session.getEditorList()){
+			for(REPNode editor : session.getEditorList()){
 				Element elementEditor = doc.createElement("Editor");
 				elementEditor.setAttribute("eid", Integer.toString(editor.getEID()));
 				elementSession.appendChild(elementEditor);
--- a/test/ConnectionPanel.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-package test;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-public class ConnectionPanel extends JPanel implements ActionListener{
-	
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
-	private JButton button;
-	private JTextField textField;
-	public String host;
-
-	public ConnectionPanel() {		
-		button = new JButton("Connect");
-		textField = new JTextField("localhost");
-	
-		button.setBounds(160, 5, 100, 20);
-		textField.setBounds(5, 5, 150, 20);
-
-		this.setLayout(null);
-		this.add(textField);
-		this.add( button);
-	
-		button.addActionListener(this);
-	}
-
-
-	public void actionPerformed(ActionEvent event) {
-		if (event.getSource() == button) {
-			host = textField.getText();
-			//System.out.println("pressed!");
-		}
-	}
-
-}
--- a/test/DefaultTableModelTest.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-package test;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

class DefaultTableModelTest extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	DefaultTableModelTest() {
		getContentPane().setLayout(new FlowLayout());

		String[][] rowData = {
			{ "A1", "B1", "C1" },
			{ "A2", "B2", "C2" },
			{ "A3", "B3", "C3" },
			{ "A4", "B4", "C4" },
		};
		String[] colNames = { "A", "B", "C" };

		DefaultTableModel tm = new DefaultTableModel(rowData, colNames);
		JTable tb = new JTable(tm);
		JScrollPane sp = new JScrollPane(tb);
		sp.setPreferredSize(new Dimension(230, 80));
		getContentPane().add(sp);

		String[] data = { "A5", "B5", "C5" };
		tm.addRow(data);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("DefaultTableModelTest");
		setSize(250, 120);
		setVisible(true);
	}
	public static void main(String[] args) {
		new DefaultTableModelTest();
	}
}
\ No newline at end of file
--- a/test/JTableTest.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-package test;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

class JTableTest extends JFrame implements ActionListener, FocusListener, ListSelectionListener{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTable tb;
	JTableTest() {
		getContentPane().setLayout(new FlowLayout());

		tb = new JTable(10, 5);
		tb.setValueAt("AAA", 0, 0);
		tb.setValueAt("BBB", 1, 1);
		tb.setValueAt("CCC", 2, 2);
		
		tb.addFocusListener(this);
		

		JScrollPane sp = new JScrollPane(tb);
		sp.setPreferredSize(new Dimension(230, 80));
		getContentPane().add(sp);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("JTableTest");
		setSize(250, 120);
		setVisible(true);
	}
	public static void main(String[] args) {
		new JTableTest();
	}
	public void actionPerformed(ActionEvent event) {
		//if(event.getSource() == tb){
		//	int a = tb.getSelectedColumn();
		//	int b = tb.getSelectedRow();
		//	System.out.println("Selected item is " + a + ":" + b);
		//}
	}

	public void focusGained(FocusEvent event) {
		int column = tb.getSelectedColumn();
		int row = tb.getSelectedRow();
		System.out.println("Gained item is " + column + ":" + row);
	}
	public void focusLost(FocusEvent event) {
		
	}
	public void valueChanged(ListSelectionEvent event) {
		int column = tb.getSelectedColumn();
		int row = tb.getSelectedRow();
		Object value = tb.getValueAt(row, column);
		System.out.println("Gained item is " + column + ":" + row + "," + value);
	}
}
\ No newline at end of file
--- a/test/SessionXMLDecoder2.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-package test;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-public class SessionXMLDecoder2 {
-	void parse(String string){
-		try {
-			SAXParserFactory spfactory = SAXParserFactory.newInstance();
-			SAXParser parser = spfactory.newSAXParser();
-			InputSource source = new InputSource(new StringReader(string));
-			parser.parse(source, new SessionXMLParser());
-		} catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		} catch (ParserConfigurationException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		} catch (SAXException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	}
-}
--- a/test/SessionXMLParser.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-package test;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-public class SessionXMLParser extends DefaultHandler{
-	
-	public void startDocument() {
-		System.out.println("Start Document.");
-	}
-	
-	public void startElement(String uri, String localName, String qName, Attributes attributes){
-
-	}
-	
-
-	public static void main(String[] args) {
-		String string = null;
-		if(args.length > 0) {
-			string = args[0];
-		}
-		try {
-			SAXParserFactory spfactory = SAXParserFactory.newInstance();
-			SAXParser parser = spfactory.newSAXParser();
-			InputSource source = new InputSource(new StringReader(string));
-			parser.parse(source, new SessionXMLParser());
-		} catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		} catch (ParserConfigurationException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		} catch (SAXException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	}
-	
-}
--- a/test/TestGUI.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-package test;
-
-import java.awt.Container;
-import javax.swing.JFrame;
-
-
-public class TestGUI {
-
-	private static JFrame frame;
-	private static ConnectionPanel cp;
-	//private static ConnectionListener listener;
-
-	public TestGUI() {
-	}
-
-	public static void main(String[] args){
-		frame = new JFrame("SessionManager");
-		frame.setBounds(100, 100, 400, 100);
-		cp =  new ConnectionPanel();
-		Container cont = frame.getContentPane();
-		cont.add(cp);
-
-		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-		frame.setVisible(true);
-	}
-	
-}
--- a/test/TestSelector.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-package test;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
-import java.nio.channels.ServerSocketChannel;
-
-public class TestSelector {
-	public static void main(String[] args) throws IOException{
-		Selector selector = Selector.open();
-		ServerSocketChannel ssc = ServerSocketChannel.open();
-		ssc.configureBlocking(false);
-		ssc.socket().bind(new InetSocketAddress(8765));
-		ssc.register(selector, SelectionKey.OP_ACCEPT);
-		
-		
-	}
-}
--- a/test/TestUTF8.java	Mon Nov 10 01:12:46 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-//package rep;
-package test;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-
-import rep.REPCommand;
-
-public class TestUTF8 {
-	
-	public static ByteBuffer pack(REPCommand command){
-    	System.out.println("send command: " + command.toString());
-    	ByteBuffer buffer = ByteBuffer.allocateDirect(24+(command.string).length()*2);
-    	buffer.clear();  // position = 0 
-    	buffer.putInt(command.cmd.id); buffer.putInt(command.sid); buffer.putInt(command.eid);
-    	buffer.putInt(command.seq); buffer.putInt(command.lineno); 
-    	System.out.println("Plane: Set REPComand textlen(Byte) : " + command.string.length()*2);  
-    	buffer.putInt(command.string.length()*2); 
-    	for(int i=0;i<command.string.length();i++) {
-			buffer.putChar(command.string.charAt(i));
-		}	
-    	buffer.flip();    // limit = current position, position = 0
-		return buffer;
-	}
-	
-	public static ByteBuffer packUConv(REPCommand command){		
-    	ByteBuffer buffer = ByteBuffer.allocateDirect(24+(command.string).length()*3);
-    	buffer.clear();  // position = 0 
-    	buffer.putInt(command.cmd.id); buffer.putInt(command.sid); buffer.putInt(command.eid);
-    	buffer.putInt(command.seq); buffer.putInt(command.lineno); 
-
-    	int pos = buffer.position();
-    	buffer.putInt(0);     	
-    	
-    	//Encode to UTF8    	
-    	CharBuffer cb = CharBuffer.wrap(command.string);    	
-		Charset charset = Charset.forName("UTF-8");
-		CharsetEncoder encoder = charset.newEncoder();
-		//try {
-		encoder.encode(cb, buffer, false);
-		/*} catch (CharacterCodingException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}*/
-		System.out.println("UTF-8: Set REPComand textlen(Byte) : " + (buffer.position() - pos-4));    	
-		buffer.putInt(pos, (buffer.position()-pos-4));
-		buffer.rewind();
-		return buffer;    	
-	}
-	
-	public static void unpack_check(ByteBuffer buffer) {
-		String text = "";
-		int cmd = buffer.getInt();
-		int sid = buffer.getInt();
-		int eid = buffer.getInt();
-		int seqid = buffer.getInt();
-		int lineno = buffer.getInt();
-		int textsiz = buffer.getInt();
-		
-		//textBuffer.rewind();
-		for(int i=0;i<(textsiz/2);i++) {
-			text +=buffer.getChar();
-		}
-		String string = text;
-		System.out.println("Plane: => cmd:"+cmd+" sid:"+sid+" eid:"+eid+"seqid:"+seqid+" lineno:"+lineno+" textsiz:" +textsiz+" text: "+string);			
-	}
-
-	public static void unpackUConv_check(ByteBuffer buffer) {
-		int cmd = buffer.getInt();
-		int sid = buffer.getInt();
-		int eid = buffer.getInt();
-		int seqid = buffer.getInt();
-		int lineno = buffer.getInt();
-		int textsiz = buffer.getInt();
-
-		Charset charset1 = Charset.forName("UTF-8");
-		CharsetDecoder decoder = charset1.newDecoder();
-		CharBuffer cb = null;
-		try {
-			cb = decoder.decode(buffer);
-		} catch (CharacterCodingException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-
-		String string = cb.toString();
-		System.out.println("UTF-8: => cmd:"+cmd+" sid:"+sid+" eid:"+eid+"seqid:"+seqid+" lineno:"+lineno+" textsiz:" +textsiz+" text: "+string);			
-		//System.out.println("string size:"+string.length());
-		//System.out.println(string);
-	}
-	
-	public static void main(String[] args) throws IOException{
-		String text = "あいうえお、かきくけこ、さしすせそ";
-		REPCommand utf8buf = new REPCommand(1, 2, 3, 4, 5, 0, text);
-		REPCommand buf = new REPCommand(1, 2, 3, 4, 5, 0, text);
-	    ByteBuffer buf1,buf2;
-
-	    buf1 = pack(buf);
-	    buf2 = packUConv(utf8buf);
-	    System.out.println(" ");    
-	    System.out.println("Encode TEST");
-	    
-		System.out.println("Plane: ByteBuffer :" +buf1.toString());
-		System.out.println("UTF-8: Encoded byteBuffer :" +buf2.toString());
-		
-
-		unpack_check(buf1);
-		unpackUConv_check(buf2);
-	}
-}
--- a/test/XMLTest.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/test/XMLTest.java	Mon Nov 10 22:07:45 2008 +0900
@@ -1,8 +1,8 @@
 package test;
 
-import rep.Editor;
 import rep.Session;
 import rep.SessionList;
+import rep.handler.Editor;
 import rep.xml.SessionXMLDecoder;
 import rep.xml.SessionXMLEncoder;
 
--- a/test/sematest/TestGUI.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/test/sematest/TestGUI.java	Mon Nov 10 22:07:45 2008 +0900
@@ -2,13 +2,13 @@
 
 import java.util.LinkedList;
 
-import rep.Editor;
-import rep.SelectButtonEvent;
 import rep.Session;
-import rep.SessionManagerEvent;
-import rep.SessionManagerEventListener;
-import rep.SessionManagerGUI;
 import rep.channel.REPLogger;
+import rep.gui.SelectButtonEvent;
+import rep.gui.SessionManagerEvent;
+import rep.gui.SessionManagerEventListener;
+import rep.gui.SessionManagerGUI;
+import rep.handler.REPNode;
 
 /**
  * @author kono
@@ -19,7 +19,7 @@
 
 public class TestGUI implements SessionManagerGUI {
 	public LinkedList<Session> slist;
-	public LinkedList<Editor> elist;
+	public LinkedList<REPNode> elist;
 	SessionManagerEventListener manager;
 	int count = 0;
 	private REPLogger ns;
@@ -33,14 +33,14 @@
 		doRun.run();
 	}
 
-	public void update(LinkedList<Session> slist, LinkedList<Editor> elist) {
+	public void update(LinkedList<Session> slist, LinkedList<REPNode> elist) {
 		int i = 0;
 		this.slist = slist;
 		this.elist = elist;
 		// fair and deterministic select session for an empty editor
 		if (slist.size()==0) return;
 		Session s = slist.get(count++ % slist.size());
-		for(Editor e :elist) {
+		for(REPNode e :elist) {
 			if (e.isDirect() && !e.hasSession()) {
 				SessionManagerEvent event = new SelectButtonEvent(e, s);
 				ns.writeLog("Select session "+s.getSID()+" and editor "+i);
--- a/test/sematest/TestInterManagerSession.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/test/sematest/TestInterManagerSession.java	Mon Nov 10 22:07:45 2008 +0900
@@ -6,8 +6,8 @@
 import rep.REP;
 import rep.REPCommand;
 import rep.SessionManager;
-import rep.SessionManagerEvent;
 import rep.channel.REPServerSocketChannel;
+import rep.gui.SessionManagerEvent;
 
 public class TestInterManagerSession extends TestSessionManager {
 
--- a/test/sematest/TestSessionManager.java	Mon Nov 10 01:12:46 2008 +0000
+++ b/test/sematest/TestSessionManager.java	Mon Nov 10 22:07:45 2008 +0900
@@ -2,10 +2,10 @@
 
 import java.io.IOException;
 import rep.SessionManager;
-import rep.SessionManagerEvent;
-import rep.SessionManagerGUI;
 import rep.channel.REPLogger;
 import rep.channel.REPServerSocketChannel;
+import rep.gui.SessionManagerEvent;
+import rep.gui.SessionManagerGUI;
 
 
 public class TestSessionManager {