package org.jactr.eclipse.runtime.session.impl;
/*
* default logging
*/
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.eclipse.execution.internal.GeneralEventManager;
import org.jactr.eclipse.execution.internal.GeneralEventManager.INotifier;
import org.jactr.eclipse.runtime.RuntimePlugin;
import org.jactr.eclipse.runtime.session.ISession;
import org.jactr.eclipse.runtime.session.ISessionListener;
import org.jactr.eclipse.runtime.session.control.ISessionController;
import org.jactr.eclipse.runtime.session.data.ISessionData;
import org.jactr.eclipse.runtime.session.manager.internal.SessionManager;
import org.jactr.eclipse.runtime.session.stream.ISessionDataStream;
public abstract class AbstractSession implements ISession
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(AbstractSession.class);
static private enum EventType {
CLOSED, DESTROYED, NEW_DATA, NEW_TIME, NEW_STREAM
};
private boolean _closed = false;
private boolean _destroyed = false;
private final UUID _sessionId;
private final Map<String, ISessionData> _sessionData;
private final GeneralEventManager<ISessionListener, Object[]> _eventManager;
private final Map<String, Object> _metaData;
public AbstractSession()
{
this(UUID.randomUUID());
}
public AbstractSession(UUID uuid)
{
_sessionData = new ConcurrentHashMap<String, ISessionData>();
_sessionId = uuid;
_eventManager = new GeneralEventManager<ISessionListener, Object[]>(
new INotifier<ISessionListener, Object[]>() {
public void notify(ISessionListener listener, Object[] event)
{
try
{
notifyListeners(listener, event);
}
catch (Exception e)
{
LOGGER.error("Failed to propogate event to listeners ", e);
}
}
});
_metaData = new TreeMap<String, Object>();
}
protected void notifyListeners(ISessionListener listener, Object[] event)
{
EventType type = (EventType) event[0];
switch (type)
{
case CLOSED:
listener.sessionClosed(AbstractSession.this);
break;
case DESTROYED:
listener.sessionDestroyed(AbstractSession.this);
break;
case NEW_DATA:
listener.newSessionData((ISessionData) event[1]);
break;
case NEW_STREAM:
listener.newSessionDataStream(
((ISessionDataStream) event[1]).getSessionData(),
(ISessionDataStream) event[1]);
break;
}
}
public UUID getSessionId()
{
return _sessionId;
}
/**
* we dont support control through here, just yet. ideally, we'll return a
* controller that directs the ArchivalIndex directly.
*/
public ISessionController getController()
{
return null;
}
public Set<String> getMetaDataKeys(Set<String> container)
{
if (container == null) container = new HashSet<String>();
container.addAll(_metaData.keySet());
return container;
}
public Object getMetaData(String key)
{
return _metaData.get(key);
}
public Object setMetaData(String key, Object value)
{
return _metaData.put(key, value);
}
public Set<String> getKeys(Set<String> container)
{
if (container == null) container = new HashSet<String>();
container.addAll(_sessionData.keySet());
return container;
}
public ISessionData getData(String key)
{
return _sessionData.get(key);
}
public void addData(String key, ISessionData sessionData)
{
if (sessionData != _sessionData.put(key, sessionData))
fireNewData(sessionData);
}
public void close()
{
if (!isOpen()) return;
try
{
for (ISessionData data : _sessionData.values())
try
{
data.close();
}
catch (Exception e)
{
LOGGER.error("Could not close data ", e);
}
_closed = true;
closeSession();
}
finally
{
fireClosed();
}
}
public boolean isOpen()
{
return !_closed;
}
abstract protected void closeSession();
public void destroy()
{
if (hasBeenDestroyed()) return;
try
{
if (isOpen()) close();
for (ISessionData data : _sessionData.values())
try
{
data.delete();
}
catch (Exception e)
{
LOGGER.error("Could not delete data ", e);
}
/*
* we keep the containers as they are likely keys in the viewers
*/
// _sessionData.clear();
destroySession();
}
finally
{
_destroyed = true;
fireDestroyed();
((SessionManager) RuntimePlugin.getDefault().getSessionManager())
.removeSession(this);
}
}
public boolean hasBeenDestroyed()
{
return _destroyed;
}
/**
* destroy the session
*/
abstract protected void destroySession();
public void addListener(ISessionListener listener, Executor executor)
{
_eventManager.addListener(listener, executor);
}
public void removeListener(ISessionListener listener)
{
_eventManager.removeListener(listener);
}
protected void fireClosed()
{
_eventManager.notify(new Object[] { EventType.CLOSED });
}
protected void fireDestroyed()
{
_eventManager.notify(new Object[] { EventType.DESTROYED });
}
protected void fireNewData(ISessionData sessionData)
{
_eventManager.notify(new Object[] { EventType.NEW_DATA, sessionData });
}
protected void fireNewDataStream(ISessionDataStream stream)
{
_eventManager.notify(new Object[] { EventType.NEW_STREAM, stream });
}
public void newDataStreamAdded(ISessionDataStream stream)
{
fireNewDataStream(stream);
}
}