package org.jboss.seam.core;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.util.List;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.async.AbstractDispatcher;
import org.jboss.seam.async.CronSchedule;
import org.jboss.seam.async.Dispatcher;
import org.jboss.seam.async.Schedule;
import org.jboss.seam.async.TimerSchedule;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.core.Expressions.MethodExpression;
import org.jboss.seam.core.Init.ObserverMethod;
import org.jboss.seam.core.Init.ObserverMethodExpression;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* Support for Seam component-driven events
*
* @author Gavin King
*
*/
@Scope(ScopeType.EVENT)
@BypassInterceptors
@Name("org.jboss.seam.core.events")
@Install(precedence=BUILT_IN)
public class Events
{
private static final LogProvider log = Logging.getLogProvider(Events.class);
/**
* Add a new listener for a given event type
*
* @param type the event type
* @param methodBindingExpression a method binding, expressed in EL
* @param argTypes the argument types of the method binding
*/
public void addListener(String type, String methodBindingExpression, Class... argTypes)
{
MethodExpression methodBinding = Expressions.instance().createMethodExpression(methodBindingExpression, Object.class, argTypes);
Init.instance().addObserverMethodExpression(type, methodBinding);
}
/**
* Raise an event that is to be processed synchronously
*
* @param type the event type
* @param parameters parameters to be passes to the listener method
*/
public void raiseEvent(String type, Object... parameters)
{
//TODO: find a way to map event parameters to params in an EL-defined listener
log.trace("Processing event:" + type);
List<Init.ObserverMethodExpression> list = Init.instance().getObserverMethodExpressions(type);
if (list!=null)
{
for (ObserverMethodExpression listener: list )
{
listener.getMethodBinding().invoke(parameters);
}
}
List<Init.ObserverMethod> observers = Init.instance().getObserverMethods(type);
if (observers!=null)
{
for (ObserverMethod observer: observers)
{
String name = observer.getComponent().getName();
Object listener = Component.getInstance( name, observer.isCreate(), false );
if ( observer.getComponent().hasUnwrapMethod() )
{
listener = observer.getComponent().getScope().getContext().get(name);
}
if (listener!=null)
{
observer.getComponent().callComponentMethod(listener, observer.getMethod(), parameters);
}
}
}
}
/**
* Raise an event that is to be processed asynchronously
*
* @param type the event type
* @param parameters parameters to be passes to the listener method
*/
public void raiseAsynchronousEvent(String type, Object... parameters)
{
getDispatcher().scheduleAsynchronousEvent(type, parameters);
}
/**
* Raise an event that is to be processed according to a "schedule"
*
* @see TimerSchedule (EJB, quartz or JDK timer service)
* @see CronSchedule (quartz timer service only)
*
* @param type the event type
* @param schedule the schedule object, specific to the dispatcher strategy
* @param parameters parameters to be passes to the listener method
*/
public void raiseTimedEvent(String type, Schedule schedule, Object... parameters)
{
getDispatcher().scheduleTimedEvent(type, schedule, parameters);
}
/**
* Raise an event that is to be processed after successful completion of
* the current transaction
*
* @param type the event type
* @param parameters parameters to be passes to the listener method
*/
public void raiseTransactionSuccessEvent(String type, Object... parameters)
{
getDispatcher().scheduleTransactionSuccessEvent(type, parameters);
}
/**
* Raise an event that is to be processed after the current transaction
* ends
*
* @param type the event type
* @param parameters parameters to be passes to the listener method
*/
public void raiseTransactionCompletionEvent(String type, Object... parameters)
{
getDispatcher().scheduleTransactionCompletionEvent(type, parameters);
}
/**
* @return the Dispatcher object to use for dispatching asynchronous
* and timed events
*/
protected Dispatcher getDispatcher()
{
return AbstractDispatcher.instance();
}
public static boolean exists()
{
return Contexts.isEventContextActive() && instance()!=null;
}
public static Events instance()
{
return (Events) Component.getInstance(Events.class, ScopeType.EVENT);
}
}