package org.smartly.commons;
import org.smartly.commons.async.Async;
import org.smartly.commons.logging.Logger;
import org.smartly.commons.logging.util.LoggingUtils;
import org.smartly.commons.util.BeanUtils;
import org.smartly.commons.util.FormatUtils;
import java.lang.reflect.Method;
import java.util.*;
/**
* Common listeners repository.
*/
public class Delegates {
public static interface Handler { /** base handler **/
}
// --------------------------------------------------------------------
// F u n c t i o n D e l e g a t e s
// --------------------------------------------------------------------
public static interface CreateRunnableCallback extends Handler {
Runnable handle(final int index, final int length);
}
public static interface Function<T> extends Handler {
T handle(final Object...args );
}
// --------------------------------------------------------------------
// E v e n t s
// --------------------------------------------------------------------
public static interface ExceptionCallback extends Handler {
void handle(final String message, final Throwable exception);
}
/**
* Simple handler for Async Action
*/
public static interface Action extends Handler {
void handle(final Object... args);
}
/**
* Callback for progress indicators.
*/
public static interface ProgressCallback extends Handler {
void handle(final int index, final int length, final double progress);
}
// --------------------------------------------------------------------
// E v e n t H a n d l e r s P o o l
// --------------------------------------------------------------------
public static final class Handlers {
private final Map<Class, List<Object>> _handlers;
public Handlers() {
_handlers = Collections.synchronizedMap(new HashMap<Class, List<Object>>());
}
public void clear() {
synchronized (_handlers) {
if (!_handlers.isEmpty()) {
final Collection<List<Object>> values = _handlers.values();
for (final List<Object> list : values) {
list.clear();
}
}
_handlers.clear();
}
}
public int size() {
return _handlers.size();
}
public int size(final Class hclass) {
synchronized (_handlers) {
return _handlers.containsKey(hclass) ? _handlers.get(hclass).size() : 0;
}
}
public boolean contains(final Class hclass) {
return _handlers.containsKey(hclass);
}
public void add(final Object handler) {
if (null != handler) {
final Class hclass = this.getInterfaceClass(handler.getClass());
this.add(hclass, handler);
}
}
public void triggerAsync(final Class hclass, final Object... args) {
synchronized (_handlers) {
if (_handlers.containsKey(hclass)) {
this.trigger(true, _handlers.get(hclass), args);
} else {
this.getLogger().fine(FormatUtils.format("No handlers of type '{0}'!", hclass.getName()));
}
}
}
public void trigger(final Class hclass, final Object... args) {
synchronized (_handlers) {
if (_handlers.containsKey(hclass)) {
this.trigger(false, _handlers.get(hclass), args);
} else {
this.getLogger().fine(FormatUtils.format("No handlers of type '{0}'!", hclass.getName()));
}
}
}
//-- p r i v a t e --//
private Logger getLogger() {
return LoggingUtils.getLogger(this);
}
private void add(final Class hclass, final Object handler) {
synchronized (_handlers) {
if (!_handlers.containsKey(hclass)) {
final List<Object> list = new LinkedList<Object>();
_handlers.put(hclass, list);
}
_handlers.get(hclass).add(handler);
}
}
private void trigger(final boolean async, final List<Object> handlers,
final Object... args) {
for (final Object handler : handlers) {
final Class hclass = this.getInterfaceClass(handler);
final Method method = null != args && args.length > 0
? BeanUtils.getMethodIfAny(hclass, "handle", args)
: BeanUtils.getMethodIfAny(hclass, "handle");
if (null != method) {
if (async) {
Async.Action(new Action() {
@Override
public void handle(final Object... args2) {
try {
method.invoke(handler, args2);
} catch (Throwable t) {
// manage execution error
}
}
}, args);
} else {
try {
method.invoke(handler, args);
} catch (Throwable t) {
// manage execution error
}
}
}
}
}
private Class getInterfaceClass(final Object instance) {
return null != instance
? this.getInterfaceClass(instance.getClass())
: null;
}
private Class getInterfaceClass(final Class hclass) {
try {
return hclass.getInterfaces()[0];
} catch (Throwable ignored) {
}
return null;
}
}
// --------------------------------------------------------------------
// c o n s t r u c t o r
// --------------------------------------------------------------------
private Delegates() {
}
}