package acm.program;
import java.awt.Component;
import java.awt.Container;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import abbot.finder.BasicFinder;
import abbot.finder.ComponentNotFoundException;
import abbot.finder.Matcher;
import abbot.finder.MultipleComponentsFoundException;
import acm.graphics.GLabel;
import acm.graphics.GObject;
import acm.gui.DoubleField;
import acm.gui.IntField;
import acm.program.TestableGraphicsProgram.GraphicFilter;
import junit.framework.Assert;
public class TestableProgram extends Program
{
public Component getGUIObject(GUIFilter filter)
{
Component c = null;
BasicFinder finder = new BasicFinder();
try
{
return finder.find(filter2matcher(filter));
}
catch ( ComponentNotFoundException e )
{
return null;
}
catch ( MultipleComponentsFoundException e )
{
return e.getComponents()[0];
}
}
public <T extends Component> T getGUIObject(Class<T> type, GUIFilter filter)
{
return (T)getGUIObject(filter.and(GUIFilter.type(type)));
}
public Component getExactlyOneGUIObject(GUIFilter filter)
{
IllegalStateException ise;
Component[] comps = getAllGUIObjects(filter);
if(comps.length == 0)
{
ise = new IllegalStateException("No Components matching filter found.");
StackTraceElement[] stack = ise.getStackTrace();
for(StackTraceElement ste : stack)
{
if(ste.getClassName().startsWith("org.junit.") || ste.getClassName().startsWith("junit."))
{
Assert.fail(ise.getMessage());
}
}
throw ise;
}
else if(comps.length > 1)
{
ise = new IllegalStateException("Multiple Components matching filter found.");
StackTraceElement[] stack = ise.getStackTrace();
for(StackTraceElement ste : stack)
{
if(ste.getClassName().startsWith("org.junit.") || ste.getClassName().startsWith("junit."))
{
Assert.fail(ise.getMessage());
}
}
throw ise;
}
return comps[0];
}
public <T extends Component> T getExactlyOneGUIObject(Class<T> type, GUIFilter filter)
{
return (T)getExactlyOneGUIObject(filter.and(GUIFilter.type(type)));
}
public Component[] getAllGUIObjects(GUIFilter filter)
{
Component c = null;
BasicFinder finder = new BasicFinder();
try
{
c = finder.find(filter2matcher(filter));
Component[] comps = {c};
return comps;
}
catch ( ComponentNotFoundException e )
{
return null;
}
catch ( MultipleComponentsFoundException e )
{
Component[] comps = e.getComponents();
return comps;
}
}
public <T extends Component> T[] getAllGUIObjects(Class<T> type, GUIFilter filter)
{
Component[] comps = getAllGUIObjects(filter.and(GUIFilter.type(type)));
T[] tobjs = (T[]) Array.newInstance(type, comps.length);
for (int i = 0; i < comps.length; i++)
{
tobjs[i] = (T) comps[i];
}
return tobjs;
}
public boolean hasGUIObject(GUIFilter filter)
{
return getGUIObject(filter) != null;
}
public void assertHasGUIObject(String hint, GUIFilter filter)
{
if(!hasGUIObject(filter))
Assert.fail(hint);
}
public void assertNoGUIObject(String hint, GUIFilter filter)
{
if(hasGUIObject(filter))
Assert.fail(hint);
}
private Matcher filter2matcher(final GUIFilter filter)
{
return new Matcher()
{
public boolean matches( Component comp )
{
return filter.test(comp);
}
};
}
public static abstract class GUIFilter extends Filter
{
public final GUIFilter and(final GUIFilter otherFilter)
{
final GUIFilter self = this;
GUIFilter gf = new GUIFilter(){
public boolean test(Component comp)
{
return self.test(comp) && otherFilter.test(comp);
}
};
gf.description = "(" + this.description + " AND " + otherFilter.description + ")";
return gf;
}
public final GUIFilter or(final GUIFilter otherFilter)
{
final GUIFilter self = this;
GUIFilter gf = new GUIFilter(){
public boolean test(Component comp)
{
return self.test(comp) || otherFilter.test(comp);
}
};
gf.description = "(" + this.description + " OR " + otherFilter.description + ")";
return gf;
}
public static final GUIFilter not(final GUIFilter otherFilter)
{
GUIFilter gf = new GUIFilter(){
public boolean test(Component comp)
{
return !otherFilter.test(comp);
}
};
gf.description = " NOT " + otherFilter.description;
return gf;
}
public static final GUIFilter withText(final String text)
{
GUIFilter gf = new GUIFilter()
{
public boolean test( Component c )
{
Method m = null;
try
{
m = c.getClass().getMethod("getText");
return ((String)m.invoke(c)).equals(text);
}
catch ( SecurityException e )
{
return false;
}
catch ( NoSuchMethodException e )
{
return false;
}
catch ( IllegalArgumentException e )
{
return false;
}
catch ( IllegalAccessException e )
{
return false;
}
catch ( InvocationTargetException e )
{
return false;
}
}
};
gf.description = "with text: \"" + text + "\"";
return gf;
}
public static final GUIFilter type(final Class c)
{
GUIFilter gf = new GUIFilter()
{
public boolean test(Component comp)
{
return c.isAssignableFrom(comp.getClass());
}
};
gf.description = "class: " + c.getSimpleName();
return gf;
}
public static final GUIFilter withName(final String name)
{
GUIFilter gf = new GUIFilter()
{
public boolean test( Component c )
{
if(c.getName() == null)
return false;
else
return c.getName().equals(name);
}
};
gf.description = "named " + name;
return gf;
}
public static final GUIFilter withValue(final String value)
{
GUIFilter gf = new GUIFilter()
{
public boolean test( Component c )
{
if(JTextField.class.isAssignableFrom(c.getClass()))
return ((JTextField)c).getText().equals(value);
return false;
}
};
gf.description = "with value: " + value;
return gf;
}
public static final GUIFilter hasFocus = new GUIFilter() {
{ this.setDescription("has focus"); }
public boolean test( Component c )
{
return c.isFocusOwner();
}
};
public static final GUIFilter doesNotHaveFocus = new GUIFilter() {
{ this.setDescription("does not have focus"); }
public boolean test( Component c )
{
return !c.isFocusOwner();
}
};
public static final GUIFilter enabled = new GUIFilter() {
{this.setDescription("enabled"); }
public boolean test(Component c)
{
return c.isEnabled();
}
};
public static final GUIFilter not_enabled = new GUIFilter() {
{ this.setDescription("not enabled"); }
public boolean test(Component c)
{
return !c.isEnabled();
}
};
public abstract boolean test(Component c);
}
}