/*******************************************************************************
* Copyright (c) 2012-2013 CWI
* 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:
*
* * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI
*******************************************************************************/
package org.rascalmpl.debug;
import java.util.Collection;
import java.util.EventObject;
/**
* Interpreter event trigger template that does not
* specify yet how an event is fired.
*/
public abstract class AbstractInterpreterEventTrigger implements IRascalEventTrigger {
private Object source;
/**
* Creates a new event trigger with a given source.
*
* @param source
* origin of events, see {@link EventObject#getSource()}
*/
public AbstractInterpreterEventTrigger(Object source) {
this.source = source;
}
/**
* Fires a interpreter event.
*
* @param event
* interpreter event to fire
*/
protected abstract void fireEvent(RascalEvent event);
/**
* Fires a creation event for this interpreter.
*/
public void fireCreationEvent() {
fireEvent(new RascalEvent(source, RascalEvent.Kind.CREATE));
}
/**
* Fires a terminate event for this interpreter.
*/
public void fireTerminateEvent() {
fireEvent(new RascalEvent(source, RascalEvent.Kind.TERMINATE));
}
/**
* Fires a resume for this debug element with the specified detail code.
*
* @param detail
* detail code for the resume event, such as
* <code>RascalEvent.Detail.STEP_OVER</code>
*/
public void fireResumeEvent(RascalEvent.Detail detail) {
fireEvent(new RascalEvent(source, RascalEvent.Kind.RESUME,
detail));
}
/**
* Fires a resume event for this debug element with detail
* <code>RascalEvent.Detail.STEP_INTO</code>.
*/
public void fireResumeByStepIntoEvent() {
fireResumeEvent(RascalEvent.Detail.STEP_INTO);
}
/**
* Fires a resume event for this debug element with detail
* <code>RascalEvent.Detail.STEP_OVER</code>.
*/
public void fireResumeByStepOverEvent() {
fireResumeEvent(RascalEvent.Detail.STEP_OVER);
}
/**
* Fires a resume event for this debug element with detail
* <code>RascalEvent.Detail.CLIENT_REQUEST</code>.
*/
public void fireResumeByClientRequestEvent() {
fireResumeEvent(RascalEvent.Detail.CLIENT_REQUEST);
}
/**
* Fires a suspend event for this debug element with the specified detail
* code.
*
* @param detail
* detail code for the suspend event, such as
* <code>RascalEvent.Detail.BREAKPOINT</code>
*/
public void fireSuspendEvent(RascalEvent.Detail detail) {
fireEvent(new RascalEvent(source, RascalEvent.Kind.SUSPEND,
detail));
}
/**
* Fires a suspend event for this debug element with detail
* <code>RascalEvent.Detail.CLIENT_REQUEST</code>.
*/
public void fireSuspendByClientRequestEvent() {
fireSuspendEvent(RascalEvent.Detail.CLIENT_REQUEST);
}
/**
* Fires a suspend event for this debug element with detail
* <code>RascalEvent.Detail.STEP_END</code>.
*/
public void fireSuspendByStepEndEvent() {
fireSuspendEvent(RascalEvent.Detail.STEP_END);
}
/**
* Fires a suspend event for this debug element with detail
* <code>RascalEvent.Detail.STEP_END</code>.
*
* @param data
* information about the breakpoint's location
*/
public void fireSuspendByBreakpointEvent(Object data) {
RascalEvent event = new RascalEvent(source,
RascalEvent.Kind.SUSPEND,
RascalEvent.Detail.BREAKPOINT);
event.setData(data);
fireEvent(event);
}
/**
* Fires a idle event for this interpreter. E.g. this happens when the REPL
* is waiting for another command input.
*/
public void fireIdleEvent() {
fireEvent(new RascalEvent(source, RascalEvent.Kind.IDLE));
}
/**
* Creates an "null" event trigger that does not react upon "fire" actions.
*
* @return new trigger instance
*/
public static AbstractInterpreterEventTrigger newNullEventTrigger() {
return new NullEventTrigger();
}
/**
* Creates an "null" event trigger that does not react upon "fire" actions.
*
* @param source
* a fixed event source of the trigger, i.e. event sender
* @param eventListeners
* collection of listeners to be notified upon "fire" actions
* @return new trigger instance
*/
public static AbstractInterpreterEventTrigger newInterpreterEventTrigger(
Object source, Collection<IRascalEventListener> eventListeners) {
return new InterpreterEventTrigger(source, eventListeners);
}
protected static class NullEventTrigger extends
AbstractInterpreterEventTrigger {
public NullEventTrigger() {
super(new Object()); // with anonymous new source object
}
@Override
protected void fireEvent(RascalEvent event) {
/* empty */
}
@Override
public void addRascalEventListener(
IRascalEventListener listener) {
/* empty */
}
@Override
public void removeRascalEventListener(
IRascalEventListener listener) {
/* empty */
}
}
protected static class InterpreterEventTrigger extends
AbstractInterpreterEventTrigger {
private final Collection<IRascalEventListener> eventListeners;
public InterpreterEventTrigger(Object source,
Collection<IRascalEventListener> eventListeners) {
super(source);
this.eventListeners = eventListeners;
}
@Override
protected void fireEvent(RascalEvent event) {
for (IRascalEventListener listener : eventListeners) {
listener.handleRascalEvent(event);
}
}
@Override
public void addRascalEventListener(
IRascalEventListener listener) {
if (!eventListeners.contains(listener)) {
eventListeners.add(listener);
}
}
@Override
public void removeRascalEventListener(
IRascalEventListener listener) {
eventListeners.remove(listener);
}
}
}