All Downloads are FREE. Search and download functionalities are using the official Maven repository.

junit.extensions.jfcunit.finder.Finder Maven / Gradle / Ivy

The newest version!
package junit.extensions.jfcunit.finder;

import java.awt.AWTException;
import java.awt.Component;
import java.awt.Container;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.swing.JOptionPane;

import junit.extensions.jfcunit.PatternHelper;
import junit.extensions.jfcunit.RobotTestHelper;
import junit.extensions.jfcunit.WindowMonitor;
import junit.extensions.jfcunit.eventdata.MouseEventDataEx;

/**
 * Abstract class for defining call back classes to test whether a
 * {@link java.awt.Component} that is being searched for has been found.
 * 
 * @author Vijay Aravamudhan :
 *         ThoughtWorks Inc.
 */
public abstract class Finder
{
	/**
	 * Robot for debug mode of finders.
	 */
	private static RobotTestHelper s_robot = null;

	/**
	 * Robot Exception received.
	 */
	private static boolean s_robotException = false;

	/**
	 * String so for the OP codes.
	 */
	private static final String[] OP_CODE_STRINGS = new String[]
	{ "match", "startswith", "endswith", "equals", "contains" };

	/**
	 * Match the item using a Regular expression.
	 */
	public static final int OP_MATCH = 0;

	/**
	 * Check that the value starts with the given value.
	 */
	public static final int OP_STARTSWITH = 1;

	/**
	 * Check that the value ends with the given value.
	 */
	public static final int OP_ENDSWITH = 2;

	/**
	 * Check that the values are equal.
	 */
	public static final int OP_EQUALS = 3;

	/**
	 * Check that the value is contained.
	 */
	public static final int OP_CONTAINS = 4;

	/**
	 * This member is used to evaluate regular expressions.
	 */
	private Pattern m_patternMatcher;

	/**
	 * Ignore case.
	 */
	private boolean m_caseIndependent = false;

	/**
	 * The debug state of the finder.
	 */
	private boolean m_debug = false;

	/**
	 * visibility property defaults to false.
	 */
	private boolean m_ignoreVisiblity = false;

	/**
	 * Show Debug.
	 */
	private boolean m_showDebug = false;

	/**
	 * Operation to be performed when selecting items.
	 */
	private int m_operation = OP_MATCH;

	/**
	 * Default wait time.
	 */
	private static int s_defaultWait = 30;
	/**
	 * The max wait time for a window to appear in milliseconds.
	 */
	private int m_wait = s_defaultWait;

	/**
	 * Convert the String to a Operation code.
	 * 
	 * @param code
	 *            String version of the Operation.
	 * @return int version of the operation.
	 */
	public static final int getOperation(final String code)
	{
		for (int i = 0; i < OP_CODE_STRINGS.length; i++)
		{
			if (OP_CODE_STRINGS[i].equalsIgnoreCase(code))
			{
				return i;
			}
		}

		throw new java.lang.IllegalArgumentException("Operation not found:" + code);
	}

	/**
	 * Get the string version of the operation.
	 * 
	 * @param code
	 *            int Finder.OP_code
	 * @return String version of the operation.
	 */
	public static final String getOperationString(final int code)
	{
		if (code < 0 || code >= OP_CODE_STRINGS.length)
		{
			throw new IllegalArgumentException("Invalid Operation code:" + code);
		}

		return OP_CODE_STRINGS[code];
	}

	/**
	 * Get the debug state of the finder.
	 * 
	 * @return true if debugging should be enabled.
	 */
	public final boolean getDebug()
	{
		return this.m_debug;
	}

	/**
	 * Set the operation to be performed by this finder.
	 * 
	 * @param operation
	 *            Operation to be performed.
	 * @see OP_EQUALS Exact match
	 * @see OP_MATCH Matches a Regular Expression
	 * @see OP_STARTSWITH Starts with
	 * @see OP_ENDSWITH Ends with
	 * @see OP_CONTAINS Contains
	 */
	public final void setOperation(final int operation)
	{
		this.m_operation = operation;
	}

	/**
	 * Get the operation.
	 * 
	 * @return the operation to be performed by the finder.
	 */
	public final int getOperation()
	{
		return this.m_operation;
	}

	/**
	 * Set the debug state of the finder.
	 * 
	 * @param value
	 *            true if debugging should be enabled.
	 */
	public final void setShowDebug(final boolean value)
	{
		if (value && s_robot == null && !s_robotException)
		{
			try
			{
				s_robot = new RobotTestHelper();
			} catch (final AWTException ex)
			{
				System.err.println("Could not create robot:");
				ex.printStackTrace();
				s_robotException = true;
			}
		}

		this.m_showDebug = value;
	}

	/**
	 * Get the debug state of the finder.
	 * 
	 * @return true if debugging should be enabled.
	 */
	public final boolean getShowDebug()
	{
		return this.m_showDebug;
	}

	/**
	 * Set the max wait time for a window to appear.
	 * 
	 * @param wait
	 *            time in seconds.
	 */
	public final Finder setWait(final int wait)
	{
		this.m_wait = wait;
		return this;
	}

	/**
	 * Get the wait time.
	 * 
	 * @return Wait time in seconds. Default wait time is 10 seconds.
	 */
	public final int getWait()
	{
		return this.m_wait;
	}

	/**
	 * Set the default wait time for the finders. This effects all new Finders
	 * which are created.
	 * 
	 * @param wait
	 *            int duration to wait by default.
	 */
	public static final void setDefaultWait(final int wait)
	{
		s_defaultWait = wait;
	}

	/**
	 * Get the default wait duration in seconds. The default effects all new
	 * finders created.
	 * 
	 * @return int default duration to wait.
	 */
	public static final int getDefaultWait()
	{
		return s_defaultWait;
	}

	/**
	 * Evaluate the current operation.
	 * 
	 * @param leftside
	 *            String to be compared.
	 * @param rightside
	 *            String or Regular expression.
	 * @return result of operation
	 */
	public final boolean evaluate(final String leftside, final String rightside)
	{
		if (leftside == null)
		{
			// If left and right are null then return true.
			// otherwise return false.
			return rightside == null;
		}
		if (rightside == null)
		{
			return false;
		}

		if (this.m_operation == OP_CONTAINS)
		{
			return leftside.indexOf(rightside) >= 0;
		} else if (this.m_operation == OP_ENDSWITH)
		{
			return leftside.endsWith(rightside);
		} else if (this.m_operation == OP_STARTSWITH)
		{
			return leftside.startsWith(rightside);
		} else if (this.m_operation == OP_EQUALS)
		{
			return leftside.equals(rightside);
		} else if (this.m_operation == OP_MATCH)
		{
			return matchPattern(leftside, rightside);
		}

		throw new java.lang.IllegalStateException("Invalid operation for finder:" + this.m_operation);
	}

	/**
	 * Set the finder into a case independent mode.
	 * 
	 * @param ignoreCase
	 *            true if case should be ignored.
	 */
	public void setCaseIndependent(final boolean ignoreCase)
	{
		this.m_caseIndependent = ignoreCase;
	}

	/**
	 * Get the state of ignore case.
	 * 
	 * @return boolean true if the case is ignored.
	 */
	public boolean isCaseIndependent()
	{
		return this.m_caseIndependent;
	}

	/**
	 * Set the debug state of the finder.
	 * 
	 * @param value
	 *            true if debugging should be enabled.
	 */
	public final void setDebug(final boolean value)
	{
		if (value && s_robot == null && !s_robotException)
		{
			try
			{
				s_robot = new RobotTestHelper();
			} catch (final AWTException ex)
			{
				System.err.println("Could not create robot:");
				ex.printStackTrace();
				s_robotException = true;
			}
		}

		this.m_debug = value;
	}

	/**
	 * Set the ignore visiblity property, to generate the proper index when a
	 * dialog is closed.
	 * 
	 * @param value
	 *            true if the visibility should be ignored.
	 */
	public final void setIgnoreVisibility(final boolean value)
	{
		this.m_ignoreVisiblity = value;
	}

	/**
	 * Method that returns true if the given component matches the search
	 * criteria.
	 * 
	 * @param comp
	 *            The {@link Component} to test
	 * @return true if this {@link Component} is a match
	 */
	public abstract boolean testComponent(final Component comp);

	/**
	 * Find the Component matching this finder at the given index within the
	 * container specified.
	 * 
	 * @param conts
	 *            Container to be searched.
	 * @param index
	 *            Index of the item.
	 * @return Component found.
	 */
	protected T find(final Container[] conts, final int index)
	{
		final long abortAfter = System.currentTimeMillis() + getWait() * 1000;

		Container[] search = null;
		do
		{
			int idx = 0;
			if (conts == null)
			{
				search = WindowMonitor.getWindows();
			} else
			{
				search = conts;
			}

			if (this instanceof AbstractWindowFinder)
			{
				final Object[] all = ((AbstractWindowFinder) this).findAll().toArray();
				if (all.length <= index)
				{
					continue;
				}
				return (T) all[index];
			}

			for (int window = 0; window < search.length; window++)
			{
				final List comps = findComponentList(this, search[window], new ArrayList(), index - idx);
				final int size = comps.size();

				if (size > 0 && size > index - idx)
				{
					final T comp = comps.get(index - idx);
					return comp;
				}

				idx += comps.size();
			}

			pause(abortAfter);
		} while (System.currentTimeMillis() < abortAfter);

		return null;
	}

	/**
	 * Find the component at the index. Scope to search is all frames/dialogs.
	 * 
	 * @param index
	 *            Index of the item to be found.
	 * @return Item at the given index.
	 */
	public final T find(final int index)
	{
		return find((Container[]) null, index);
	}

	/**
	 * Find the Component matching this finder at the given index within the
	 * container specified.
	 * 
	 * @param cont
	 *            Container to be searched.
	 * @param index
	 *            Index of the item.
	 * @return Component found.
	 */
	public Component find(final Container cont, final int index)
	{
		return find(new Container[]
		{ cont }, index);
	}

	/**
	 * Find the first component. Scope to search is all frames/dialogs.
	 * 
	 * @return First Item.
	 */
	public final T find()
	{
		return find(0);
	}

	/**
	 * Find all of the resulting items in the entire GUI application.
	 * 
	 * @return List resulting items matching finder.
	 */
	public List findAll()
	{
		return findAll((Container[]) null);
	}

	/**
	 * Find all of the items matching this finder in the container give.
	 * 
	 * @param cont
	 *            Container to be searched.
	 * @return List resulting items matching finder.
	 */
	public List findAll(final Container cont)
	{
		return findAll(new Container[]
		{ cont });
	}

	/**
	 * Find all of the components for this finder in the set of containers
	 * given.
	 * 
	 * @param cont
	 *            Container[] Set of containers to search.
	 * @return List resulting items matching finder.
	 */
	public List findAll(final Container[] cont)
	{
		return findAll(cont, new ArrayList());
	}

	/**
	 * This find all uses a recursive pattern for internal processing.
	 * 
	 * @param cont
	 *            Container[] Container list.
	 * @param results
	 *            List to which resulting items should be added.
	 * @return List resulting list.
	 */
	protected List findAll(final Container[] cont, final List results)
	{
		Container[] containers = cont;
		if (containers == null)
		{
			containers = WindowMonitor.getWindows();
		}
		for (int i = 0; i < containers.length; i++)
		{
			findComponentList(this, containers[i], results, Integer.MAX_VALUE);
		}
		return results;
	}

	/**
	 * Method that calls itself repetitively to build up a list of all
	 * components in the container instance that is passed in.
	 * 
	 * @param finder
	 *            An instance of the finder which implements the testComponent()
	 *            method.
	 * @param cont
	 *            The Container inside which the component is to be found.
	 * @param pList
	 *            The return list.
	 * @param index
	 *            The index of the component. The first component matching the
	 *            criteria will have index 0, the second 1, etc.
	 * @return The component that has been found (or null if none found).
	 */
	public static final  List findComponentList(final Finder finder, final Container cont,
			final List pList, final int index)
	{
		List outList = pList;

		if (outList == null)
		{
			outList = new ArrayList();
		}

		if (cont == null || finder == null)
		{
			return outList;
		}

		final Component[] children = cont.getComponents();

		for (int i = 0; i < children.length; i++)
		{
			if (finder.testComponent(children[i]))
			{
				if (finder.getDebug())
				{
					System.err.println("Finder Candidate(" + outList.size() + ") " + children[i].getClass().getName());
				}

				if (finder.getShowDebug() && s_robot != null)
				{
					try
					{
						s_robot.enterClickAndLeave(new MouseEventDataEx(children[i], 0, 0, false));
						JOptionPane.showMessageDialog(null, "Finder Candidate Index:" + outList.size()
								+ "

" + children[i].getClass().getName() + ""); } catch (final Exception ae) { ae.printStackTrace(); // Ignore } } if (!outList.contains(children[i])) { outList.add((T) children[i]); } if (outList.size() > index) { return outList; } } else if (children[i] instanceof Container) { findComponentList(finder, (Container) children[i], outList, index); if (outList.size() > index) { return outList; } } } return outList; } /** * This method is used to check that the window object is an instance of the * specified class and is also visible. * * @param comp * The {@link Component} to be checked * @param cls * The type of the component * @return true if the component is of the specified type and is visible. */ protected final boolean isValidForProcessing(final Component comp, final Class cls) { final boolean value = comp != null && cls != null && cls.isInstance(comp) && (this.m_ignoreVisiblity || comp.isShowing()); return value; } /** * Recreate the pattern. * * @param patternString * String pattern string. * @param caseIndependent * boolean true if the case should be ignored. */ protected void recreatePatternMatcher(final String patternString, final boolean caseIndependent) { this.m_patternMatcher = null; createPatternMatcher(patternString, caseIndependent); } /** * This method is used to filter components' attributes based on a pattern * specified by the user. For example, to search for all windows with title * matching 'testWindow*'. Note: If the patternString is null, we need to * avoid the PatternCompiler.compile() throwing a * NullPointerException and in this case, return true if the * componentAttribute is also null. The pattern syntax can be found at the * Jakarta RegExp API Documentation in {@link org.apache.regexp.RE}. * * @param patternString * The pattern to match with * @param caseIndependent * Whether the match should be case independent (true) or not * (false) */ protected void createPatternMatcher(final String patternString, final boolean caseIndependent) { if (this.m_patternMatcher == null) { try { this.m_patternMatcher = PatternHelper.compile(patternString, caseIndependent); } catch (final PatternSyntaxException e) { this.m_patternMatcher = null; } } } /** * This method is used to filter components' attributes based on a pattern * specified by the user. For example, to search for all windows with title * matching 'testWindow*'. Note: If the patternString is null, we need to * avoid the PatternCompiler.compile() throwing a * NullPointerException and in this case, return true if the * componentAttribute is also null. The pattern syntax can be found at the * Jakarta RegExp API Documentation in {@link org.apache.regexp.RE}. * * @param componentAttribute * The attribute text of the component to match against * @param patternString * The pattern to match with * @param caseIndependent * Whether the match should be case independent (true) or not * (false) * @return boolean whether the pattern is contained within the components' * attribute text * @see #createPatternMatcher(String, boolean) * @see #matchPattern(String, String) */ protected boolean matchPattern(final String componentAttribute, final String patternString, final boolean caseIndependent) { createPatternMatcher(patternString, caseIndependent); return matchPattern(componentAttribute, patternString); } /** * This method is used to filter components' attributes based on a pattern * specified by the user. For example, to search for all windows with title * matching 'testWindow*'. Note: If the patternString is null, we need to * avoid the PatternCompiler.compile() throwing a * NullPointerException and in this case, return true if the * componentAttribute is also null. The pattern syntax can be found at the * Jakarta RegExp API Documentation in {@link org.apache.regexp.RE}. * * @param componentAttribute * The attribute text of the component to match against * @param patternString * The pattern to match with * @return boolean whether the pattern is contained within the components' * attribute text */ protected boolean matchPattern(final String componentAttribute, final String patternString) { return matchPattern(componentAttribute, patternString, this.m_patternMatcher); } /** * This method is used to filter components' attributes based on a pattern * specified by the user. For example, to search for all windows with title * matching 'testWindow*'. Note: If the patternString is null, we need to * avoid the PatternCompiler.compile() throwing a * NullPointerException and in this case, return true if the * componentAttribute is also null. The pattern syntax can be found at the * Jakarta RegExp API Documentation in {@link org.apache.regexp.RE}. * * @param componentAttribute * The attribute text of the component to match against * @param patternString * The pattern to match with * @param re * The RE pattern matcher to be used * @return boolean whether the pattern is contained within the components' * attribute text */ protected final boolean matchPattern(final String componentAttribute, final String patternString, final Pattern re) { // if the patternString is null, we need to avoid a NullPointerException // but at the same time, return true if the componentAttribute is also // null if (patternString == null) { return componentAttribute == null; } return componentAttribute != null && re != null && re.matcher(componentAttribute).matches(); } /** * Puase the finder for a bit. * * @param date * Termination time of the finder. */ protected final void pause(final long date) { int sleep = 1000; if (System.currentTimeMillis() + 3000 < date) { sleep = 3000; } try { Thread.currentThread(); Thread.sleep(sleep); } catch (final InterruptedException ex) { ; // Ignore } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy