package org.oddjob.beanbus.destinations;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.inject.Inject;
import org.oddjob.arooa.ArooaSession;
import org.oddjob.arooa.convert.ArooaConversionException;
import org.oddjob.arooa.deploy.annotations.ArooaHidden;
import org.oddjob.arooa.life.ArooaSessionAware;
import org.oddjob.arooa.reflect.ArooaClass;
import org.oddjob.arooa.reflect.BeanOverview;
import org.oddjob.arooa.reflect.PropertyAccessor;
import org.oddjob.beanbus.AbstractFilter;
import org.oddjob.beanbus.BusConductor;
import org.oddjob.beanbus.BusCrashException;
import org.oddjob.beanbus.BusEvent;
import org.oddjob.beanbus.BusFilter;
import org.oddjob.beanbus.TrackingBusListener;
import org.oddjob.io.StdoutType;
/**
* A {@link BusFilter} that analyses beans.
*
*
* @author rob
*
* @param <T> The type of the beans to be analysed.
*/
public class BeanDiagnostics<T> extends AbstractFilter<T, T>
implements ArooaSessionAware {
private final Set<ArooaClass> types = new LinkedHashSet<ArooaClass>();
private final TrackingBusListener busListener =
new TrackingBusListener() {
@Override
public void busStarting(BusEvent event) throws BusCrashException {
types.clear();
nulls = 0;
count = 0;
if (output == null) {
try {
output = new StdoutType().toValue();
} catch (ArooaConversionException e) {
throw new BusCrashException(e);
}
}
}
@Override
public void busTerminated(BusEvent event) {
PrintStream out = new PrintStream(output);
out.println("Analysed " + count + " beans. Discovered " +
types.size() + " types.");
for (ArooaClass type : types) {
printTypeInfo(type, out);
}
out.close();
}
};
private PropertyAccessor accessor;
private int nulls;
private int count;
private OutputStream output;
public void setArooaSession(ArooaSession session) {
this.accessor = session.getTools().getPropertyAccessor();
}
@Override
protected T filter(T from) {
++count;
if (from == null) {
++nulls;
}
else {
ArooaClass type = accessor.getClassName(from);
types.add(type);
}
return from;
}
@ArooaHidden
@Inject
public void setBusConductor(BusConductor busConductor) {
busListener.setBusConductor(busConductor);
}
public void setOutput(OutputStream output) {
this.output = output;
}
public OutputStream getOutput() {
return output;
}
public Set<ArooaClass> getTypes() {
return types;
}
@Override
public boolean isEmpty() {
return types.size() == 0;
}
public int getCount() {
return count;
}
public void printTypeInfo(ArooaClass type, PrintStream out) {
out.println("Type: " + type);
out.println(" Properties:");
BeanOverview overview = type.getBeanOverview(accessor);
String[] properties = overview.getProperties();
Arrays.sort(properties);
for (String property : properties) {
out.println(" " + property + ": " +
overview.getPropertyType(property).getName() +
(overview.isIndexed(property) ? ", indexed" : "") +
(overview.isMapped(property) ? ", mapped" : "") +
(overview.hasReadableProperty(property) ? "" : " (Write Only)") +
(overview.hasWriteableProperty(property) ? "" : " (Read Only)")
);
}
}
}