view rep/Session.java @ 384:bcdf5476b8e4

restructured-version
author one@firefly.cr.ie.u-ryukyu.ac.jp
date Mon, 10 Nov 2008 22:16:37 +0900
parents 4b87f89b3afd
children 1d5b608f39da
line wrap: on
line source

package rep;

import java.util.Collection;
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,REPNode> {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private REPNode masterEditor;
	private int sessionID;
	private String sessionName;
	// isOnwer means this session has active channels(forwarders).
	private boolean isOwner = false;
	private REPNode first;
	private REPNode last;
	
	public Session(int sid, String name, REPNode editor) {
		this(sid, editor);
		sessionName = name;
	}
	

	public Session(int sid, REPNode master) {
		sessionID = sid;
		if (master!=null) {
			// we have a master
			masterEditor = last = master;
			master.setSID(sid);
			put(master.eid,master);
			if(master.channel!=null) {
				first = master;
				masterEditor.setNext(masterEditor);
				isOwner = true;
			}
		}
	}
	
	/*
	 * どこにlocal editorを入れても良いのだが、まとめた方が良いか?
	 */
	public void addForwarder(REPNode editor) {
		// add a forwarder and connect this to the session 
		editor.setSID(sessionID);
		editor.setNext(last.getNextForwarder());
		last.setNext(editor);
		last = editor;
		put(editor.eid,editor);
		isOwner = true;
		if(first==null) first = editor;
		
		// printSessionDetail();
	}
	
	public void addEditor(Editor editor) {
		// add a not-connected editor in a sassion
		// the editor is outside of this manager 
		editor.setSID(sessionID);
		put(editor.eid,editor);
	}
	
	public Collection<REPNode> getEditorList() {
		return values();
	}
	
	public int getSID() {
		return sessionID;
	}
	public REPNode getOwner() {
		return masterEditor;
	}
	public String getName() {
		return sessionName;
	}
	
	
	public boolean deleteEditor(REPSocketChannel<REPCommand> channel) {
		LinkedList<REPNode> toBeRemoved = new LinkedList<REPNode>();
	    for (REPNode e:values() ) {
			if (e.getChannel()==channel) {
				unconnect((Forwarder)e);
				toBeRemoved.add(e);
			}
		}
	    for(REPNode e:toBeRemoved) {
	    	remove(e);
	    }
		return !toBeRemoved.isEmpty();
	}
	
	public boolean deleteForwarder(Forwarder editor) {
		unconnect(editor);
		return remove(editor)!=null;
	}
	
	private void unconnect(Forwarder e) {
		boolean hasOwner = false;
		for(REPNode e1:values()) {
			Forwarder f = (Forwarder)e1;
			if(f.next==e) {
				f.next=e.next;
			} else {
				if (f.channel!=null) hasOwner=true;
			}
		}
		if(first==e) first=null;
		if(masterEditor==e) masterEditor=null;
		isOwner = hasOwner;
	}
	
	public void setSID(int sid) {
		sessionID = sid;
	}
	
	public boolean hasOwner() {
		return isOwner;
	}
	
	
	public Editor getEditor(REPSocketChannel<REPCommand> channel) {
		for(REPNode editor : values()){
			if(editor.getChannel() == channel) {
				return (Editor)editor;
			}
		}
		return null;
	}

	
	
	public void closeSession() {
		REPNode f = first;
		REPCommand command = new REPCommand(REP.REPCMD_CLOSE, sessionID, REP.SM_EID.id, 0, 0, "");
		if (f!=null)
			f.send(command);
	}
	
	public REPNode getForwarder(REPSocketChannel<REPCommand> channel) {
		REPNode f = first;
		while(f.channel!=channel) f = f.next;
		ServerMainLoop.logger.writeLog("getFirstForwarder="+f.next+"=>"+f.next.channel);
		return f.next;
	}


	public void remove(SessionManager manager) {
		for(REPNode editor : values()){
			if(editor.getChannel() !=null) 
				unconnect((Forwarder)editor);
			manager.editorList.remove(editor);
		}	
	}


	public void merge(Session s) {
		for(REPNode editor : s.values()){
			REPNode mine = get(editor.eid);
			if (mine==null) {
				put(editor.eid,editor);
			} else {
				mine.merge(editor);
			}
		}	
	}
	
	@Override
	public String toString() {
		String s = super.toString();
		return s+" sid="+sessionID+" "+sessionName+" master="+
			((masterEditor==null)?"null":masterEditor.toString());
	}


	public void setName(String string) {
		sessionName = string;
	}


	public void setFirstForwarder(REPNode f) {
		f.setSID(sessionID);
		put(f.eid,f);
		f.setNext(f);
		first = last = f;
	}

	public void printSessionDetail() {
		REPNode f = first;
		if (f==null) return;
		String log = "Session Detail ";
		while (f!=null) {
			log += ","+f+"="+f.channel+"->"+f.next;
			f = f.next;
			if (f==first) {
				log += "*";
				break;
			}
		}
		ServerMainLoop.logger.writeLog(log);
	}

}