/*
* Copyright (c) 2005, Rob Gordon.
*/
package org.oddjob.beanbus.mega;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.ImageIcon;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaClass;
import org.apache.log4j.Logger;
import org.oddjob.Describeable;
import org.oddjob.Iconic;
import org.oddjob.arooa.ArooaSession;
import org.oddjob.arooa.life.ArooaLifeAware;
import org.oddjob.arooa.life.ArooaSessionAware;
import org.oddjob.beanbus.BusConductor;
import org.oddjob.beanbus.BusCrashException;
import org.oddjob.beanbus.BusEvent;
import org.oddjob.beanbus.BusListener;
import org.oddjob.beanbus.TrackingBusListener;
import org.oddjob.describe.UniversalDescriber;
import org.oddjob.framework.ComponentBoundry;
import org.oddjob.framework.ComponentWrapper;
import org.oddjob.framework.WrapDynaBean;
import org.oddjob.images.IconHelper;
import org.oddjob.images.IconListener;
import org.oddjob.images.ImageIconStable;
import org.oddjob.logging.LogEnabled;
import org.oddjob.logging.LogHelper;
/**
* Wraps a Collection object so that it can be added to an
* {@link MegaBeanBus}.
* <p>
*
* @author Rob Gordon.
*/
public class CollectionWrapper<E>
implements ComponentWrapper, ArooaSessionAware, DynaBean, BusPart,
LogEnabled, Describeable, Iconic, ArooaLifeAware, Collection<E> {
public static final String INACTIVE = "inactive";
public static final String ACTIVE = "active";
public static final ImageIcon inactiveIcon
= new ImageIconStable(
IconHelper.class.getResource("diamond.gif"),
"Inactive");
public static final ImageIcon activeIcon
= new ImageIconStable(
IconHelper.class.getResource("dot_green.gif"),
"Actvie");
private static Map<String, ImageIcon> busPartIconMap =
new HashMap<String, ImageIcon>();
static {
busPartIconMap.put(INACTIVE, inactiveIcon);
busPartIconMap.put(ACTIVE, activeIcon);
}
private volatile Logger theLogger;
private final Collection<E> wrapped;
private final transient DynaBean dynaBean;
private final Object proxy;
private volatile ArooaSession session;
private final IconHelper iconHelper = new IconHelper(
this, INACTIVE, busPartIconMap);
private final TrackingBusListener busListener =
new TrackingBusListener() {
@Override
public void busCrashed(BusEvent event) {
busCrashException = event.getBusCrashException();
};
@Override
public void busTerminated(BusEvent event) {
iconHelper.changeIcon(INACTIVE);
}
@Override
public void busStarting(BusEvent event) throws BusCrashException {
busCrashException = null;
iconHelper.changeIcon(ACTIVE);
}
};
/** A job that isn't a bus service won't know the bus has crashed. */
private volatile Exception busCrashException;
/**
* Constructor.
*
* @param collection
* @param proxy
*/
public CollectionWrapper(Collection<E> collection, Object proxy) {
this.proxy = proxy;
this.wrapped = collection;
this.dynaBean = new WrapDynaBean(wrapped);
}
@Override
public void setArooaSession(ArooaSession session) {
this.session = session;
}
protected Object getWrapped() {
return wrapped;
}
protected DynaBean getDynaBean() {
return dynaBean;
}
protected Object getProxy() {
return proxy;
}
/*
* (non-Javadoc)
* @see org.oddjob.framework.BaseComponent#logger()
*/
protected Logger logger() {
if (theLogger == null) {
String logger = LogHelper.getLogger(getWrapped());
if (logger == null) {
logger = LogHelper.uniqueLoggerName(getWrapped());
}
theLogger = Logger.getLogger(logger);
}
return theLogger;
}
//
// Lifecycle Methods
@Override
public void initialised() {
}
@Override
public void configured() {
}
@Override
public void destroy() {
busListener.setBusConductor(null);
}
/*
* (non-Javadoc)
* @see org.oddjob.logging.LogEnabled#loggerName()
*/
@Override
public String loggerName() {
return logger().getName();
}
@Override
public void prepare(BusConductor busConductor) {
ComponentBoundry.push(loggerName(), wrapped);
try {
busListener.setBusConductor(busConductor);
this.session.getComponentPool().configure(getProxy());
logger().info("Prepared with Bus Conductor [" + busConductor + "]");
} finally {
ComponentBoundry.pop();
}
}
@Override
public BusConductor conductorForService(BusConductor busConductor) {
return new LoggingBusConductorFilter(busConductor);
}
/**
* Return an icon tip for a given id. Part
* of the Iconic interface.
*/
@Override
public ImageIcon iconForId(String iconId) {
return iconHelper.iconForId(iconId);
}
/**
* Add an icon listener. Part of the Iconic
* interface.
*
* @param listener The listener.
*/
@Override
public void addIconListener(IconListener listener) {
iconHelper.addIconListener(listener);
}
/**
* Remove an icon listener. Part of the Iconic
* interface.
*
* @param listener The listener.
*/
@Override
public void removeIconListener(IconListener listener) {
iconHelper.removeIconListener(listener);
}
// Object Methods
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object other) {
return other == getProxy();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getWrapped().toString();
}
@Override
public boolean contains(String name, String key) {
return getDynaBean().contains(name, key);
}
@Override
public Object get(String name) {
return getDynaBean().get(name);
}
@Override
public Object get(String name, int index) {
return getDynaBean().get(name, index);
}
@Override
public Object get(String name, String key) {
return getDynaBean().get(name, key);
}
@Override
public DynaClass getDynaClass() {
return getDynaBean().getDynaClass();
}
@Override
public void remove(String name, String key) {
getDynaBean().remove(name, key);
}
@Override
public void set(String name, int index, Object value) {
getDynaBean().set(name, index, value);
}
@Override
public void set(String name, Object value) {
getDynaBean().set(name, value);
}
@Override
public void set(String name, String key, Object value) {
getDynaBean().set(name, key, value);
}
/*
* (non-Javadoc)
* @see org.oddjob.Describeable#describe()
*/
@Override
public Map<String, String> describe() {
return new UniversalDescriber(session).describe(
getWrapped());
}
// Collection Methods
//
@Override
public boolean add(E e) {
if (busCrashException != null) {
throw new RuntimeException(busCrashException);
}
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.add(e);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean addAll(Collection<? extends E> c) {
if (busCrashException != null) {
throw new RuntimeException(busCrashException);
}
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.addAll(c);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public void clear() {
ComponentBoundry.push(loggerName(), wrapped);
try {
wrapped.clear();
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean contains(Object o) {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.contains(o);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean containsAll(Collection<?> c) {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.containsAll(c);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean isEmpty() {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.isEmpty();
}
finally {
ComponentBoundry.pop();
}
}
@Override
public Iterator<E> iterator() {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.iterator();
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean remove(Object o) {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.remove(o);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean removeAll(Collection<?> c) {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.removeAll(c);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public boolean retainAll(Collection<?> c) {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.retainAll(c);
}
finally {
ComponentBoundry.pop();
}
}
@Override
public int size() {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.size();
}
finally {
ComponentBoundry.pop();
}
}
@Override
public Object[] toArray() {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.toArray();
}
finally {
ComponentBoundry.pop();
}
}
@Override
public <T> T[] toArray(T[] a) {
ComponentBoundry.push(loggerName(), wrapped);
try {
return wrapped.toArray(a);
}
finally {
ComponentBoundry.pop();
}
}
class LoggingBusConductorFilter extends BusConductorFilter {
public LoggingBusConductorFilter(BusConductor conductor) {
super(conductor);
}
@Override
protected void busStarting(BusEvent event,
BusListener listener) throws BusCrashException {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.busStarting(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
@Override
protected void tripBeginning(BusEvent event,
BusListener listener) throws BusCrashException {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.tripBeginning(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
@Override
protected void tripEnding(BusEvent event,
BusListener listener) throws BusCrashException {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.tripEnding(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
@Override
protected void busStopRequested(BusEvent event,
BusListener listener) {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.busStopRequested(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
@Override
protected void busStopping(BusEvent event,
BusListener listener) throws BusCrashException {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.busStopping(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
@Override
protected void busCrashed(BusEvent event,
BusListener listener) {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.busCrashed(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
@Override
protected void busTerminated(BusEvent event,
BusListener listener) {
ComponentBoundry.push(loggerName(), wrapped);
try {
super.busTerminated(event, listener);
}
finally {
ComponentBoundry.pop();
}
}
}
}