001 /* 002 * Created on Oct 29, 2007 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 * 014 * Copyright @2007-2010 the original author or authors. 015 */ 016 package org.fest.swing.finder; 017 018 import static org.fest.swing.timing.Pause.pause; 019 import static org.fest.util.Strings.concat; 020 021 import java.awt.Component; 022 import java.util.concurrent.TimeUnit; 023 024 import org.fest.swing.core.*; 025 import org.fest.swing.exception.WaitTimedOutError; 026 import org.fest.swing.fixture.ComponentFixture; 027 028 /** 029 * Understands a template for <code>{@link Component}</code> finders. 030 * @param <T> the type of component this finder can search. 031 * 032 * @author Yvonne Wang 033 * @author Alex Ruiz 034 */ 035 public abstract class ComponentFinderTemplate<T extends Component> { 036 037 static final long TIMEOUT = 5000; 038 039 private long timeout = TIMEOUT; 040 041 private final ComponentMatcher matcher; 042 private final String searchDescription; 043 044 /** 045 * Creates a new </code>{@link ComponentFinderTemplate}</code>. 046 * @param componentName the name of the {@code Component} to find. 047 * @param componentType the type of the {@code Component} to find. 048 */ 049 protected ComponentFinderTemplate(String componentName, Class<? extends T> componentType) { 050 this(new NameMatcher(componentName, componentType, true)); 051 } 052 053 /** 054 * Creates a new </code>{@link ComponentFinderTemplate}</code>. 055 * @param matcher specifies the search criteria to use when looking up a {@code Component}. 056 */ 057 protected ComponentFinderTemplate(GenericTypeMatcher<? extends T> matcher) { 058 this((ComponentMatcher)matcher); 059 } 060 061 /** 062 * Creates a new </code>{@link ComponentFinderTemplate}</code>. 063 * @param componentType the type of the {@code Component} to find. 064 */ 065 protected ComponentFinderTemplate(Class<? extends T> componentType) { 066 this(new TypeMatcher(componentType, true)); 067 } 068 069 private ComponentFinderTemplate(ComponentMatcher matcher) { 070 if (matcher == null) throw new NullPointerException("The matcher should not be null"); 071 this.matcher = matcher; 072 searchDescription = concat("component to be found using matcher ", matcher); 073 } 074 075 /** 076 * Sets the timeout for this finder. The {@code Component} to find should be found within the given time period. 077 * @param newTimeout the period of time the search should be performed. 078 * @param unit the time unit for <code>timeout</code>. 079 * @return this finder. 080 * @throws NullPointerException if the time unit is <code>null</code>. 081 * @throws IllegalArgumentException if the timeout is a negative number. 082 */ 083 protected ComponentFinderTemplate<T> withTimeout(long newTimeout, TimeUnit unit) { 084 if (unit == null) throw new NullPointerException("Time unit cannot be null"); 085 return withTimeout(unit.toMillis(newTimeout)); 086 } 087 088 /** 089 * Sets the timeout for this finder. The {@code Component} to find should be found within the given time period. 090 * @param newTimeout the number of milliseconds before stopping the search. 091 * @return this finder. 092 * @throws IllegalArgumentException if the timeout is a negative number. 093 */ 094 protected ComponentFinderTemplate<T> withTimeout(long newTimeout) { 095 if (newTimeout < 0) throw new IllegalArgumentException("Timeout cannot be a negative number"); 096 this.timeout = newTimeout; 097 return this; 098 } 099 100 /** 101 * Finds a component by name or type using the given robot. 102 * @param robot contains the underlying finding to delegate the search to. 103 * @return a fixture capable of managing the found component. 104 * @throws WaitTimedOutError if a component with the given name or of the given type could not be found. 105 */ 106 public abstract ComponentFixture<T> using(Robot robot); 107 108 /** 109 * Finds the component using either by name or type. 110 * @param robot contains the underlying finding to delegate the search to. 111 * @return the found component. 112 * @throws WaitTimedOutError if a component with the given name or of the given type could not be found. 113 */ 114 protected final T findComponentWith(Robot robot) { 115 ComponentFoundCondition condition = new ComponentFoundCondition(searchDescription, robot.finder(), matcher); 116 pause(condition, timeout); 117 return cast(condition.found()); 118 } 119 120 /** 121 * Casts the given {@code Component} to the type supported by this finder. 122 * @param c the given {@code Component}. 123 * @return the given {@code Component} casted to the type supported by this finder. 124 */ 125 protected abstract T cast(Component c); 126 }