/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
******************************************************************************/
package org.eclipse.emf.emfstore.server.eventmanager;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.emfstore.server.model.ProjectId;
import org.eclipse.emf.emfstore.server.model.versioning.events.server.ServerEvent;
import org.eclipse.emf.emfstore.server.model.versioning.events.server.ServerProjectEvent;
/**
* EventManager accepts events and distributes them to the listeners.
* EventManger runs in it's own thread. -TODO: Enable listener to listen to
* specified events only. - TODO: Don't allow listeners to block eventmanager
* (e.g. connection timeout)
*
* @author wesendon
*/
public final class EventManager extends Thread {
private static EventManager instance;
private LinkedBlockingQueue<ServerEvent> queue;
private ArrayList<ListenerContainer> listeners;
private EventManager() {
super("EventManager");
queue = new LinkedBlockingQueue<ServerEvent>();
listeners = new ArrayList<ListenerContainer>();
start();
}
/**
* Returns the instance of {@link EventManager}.
*
* @return instance
*/
public static EventManager getInstance() {
if (instance == null) {
instance = new EventManager();
}
return instance;
}
/**
* @see java.lang.Thread#run()
*/
@Override
public void run() {
ArrayList<ListenerContainer> tmp = new ArrayList<ListenerContainer>();
while (!isInterrupted()) {
try {
ServerEvent event = queue.take();
if (event != null) {
synchronized (this) {
for (ListenerContainer e : listeners) {
boolean successful = e.handleEvent(EcoreUtil
.copy(event));
if (!successful) {
tmp.add(e);
}
}
listeners.removeAll(tmp);
tmp.clear();
}
}
} catch (InterruptedException e) {
}
}
}
/**
* Register a listener. Listen to specific type of event isn't implemented
* yet.
*
* @param listener
* the listener
* @param projectId
* project id, can be null
* @param clazz
* not implemented yet
*/
public void registerListener(EMFStoreEventListener listener,
ProjectId projectId, EClass clazz) {
if (listener == null) {
return;
}
synchronized (this) {
listeners.add(new ListenerContainer(listener, projectId, clazz));
}
}
/**
* Removes a listener.
*
* @param listener
* a listener
*/
public void unregisterListener(EMFStoreEventListener listener) {
if (listener == null) {
return;
}
synchronized (this) {
listeners.remove(listener);
}
}
/**
* Use this method to distribute your event.
*
* @param event
* the event
*/
public void sendEvent(ServerEvent event) {
if (event != null) {
try {
// queue is thread safe
queue.put(event);
} catch (InterruptedException e) {
// fail silently
}
}
}
/**
* Container for listener.
*
* @author wesendon
*/
private class ListenerContainer {
private final EMFStoreEventListener listener;
private final ProjectId projectId;
@SuppressWarnings("unused")
private final EClass clazz;
public ListenerContainer(EMFStoreEventListener listener,
ProjectId projectId, EClass clazz) {
this.listener = listener;
this.projectId = projectId;
this.clazz = clazz;
}
public boolean handleEvent(ServerEvent event) {
if (projectId != null && event instanceof ServerProjectEvent) {
if (!projectId.equals(((ServerProjectEvent) event)
.getProjectId())) {
return true;
}
}
return listener.handleEvent(event);
}
}
}