001 /*
002 * Created on Aug 6, 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.core;
017
018 import java.awt.Component;
019
020 import org.fest.swing.annotation.RunsInCurrentThread;
021
022 /**
023 * Understands a <code>{@link ComponentMatcher}</code> that matches a <code>{@link Component}</code> by type and some
024 * custom search criteria.
025 * @param <T> the type of <code>Component</code> supported by this matcher.
026 *
027 * @author Yvonne Wang
028 * @author Alex Ruiz
029 */
030 public abstract class GenericTypeMatcher<T extends Component> extends AbstractComponentMatcher {
031
032 private final Class<T> supportedType;
033
034 /**
035 * Creates a new </code>{@link GenericTypeMatcher}</code>. The component to match does not have to be showing.
036 * @param supportedType the type supported by this matcher.
037 * @throws NullPointerException if the given type is <code>null</code>.
038 */
039 public GenericTypeMatcher(Class<T> supportedType) {
040 this(supportedType, false);
041 }
042
043 /**
044 * Creates a new </code>{@link GenericTypeMatcher}</code>.
045 * @param supportedType the type supported by this matcher.
046 * @param requireShowing indicates if the component to match should be showing or not.
047 * @throws NullPointerException if the given type is <code>null</code>.
048 */
049 public GenericTypeMatcher(Class<T> supportedType, boolean requireShowing) {
050 super(requireShowing);
051 if (supportedType == null) throw new NullPointerException("The supported type should not be null");
052 this.supportedType = supportedType;
053 }
054
055 /**
056 * Verifies that the given <code>{@link Component}</code>:
057 * <ol>
058 * <li>Is an instance of the generic type specified in this <code>{@link ComponentMatcher}</code></li>
059 * <li>Matches some search criteria</li>
060 * </ol>
061 * <p>
062 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
063 * responsible for calling this method from the EDT.
064 * </p>
065 * @param c the <code>Component</code> to verify.
066 * @return <code>true</code> if the given <code>Component</code> is an instance of the generic type of this matcher
067 * and matches some search criteria. Otherwise, <code>false</code>.
068 */
069 @RunsInCurrentThread
070 public final boolean matches(Component c) {
071 if (c == null) return false;
072 if (!supportedType.isInstance(c)) return false;
073 try {
074 return (requireShowingMatches(c)) && isMatching(supportedType.cast(c));
075 } catch(ClassCastException ignored) {
076 return false;
077 }
078 }
079
080 /**
081 * Returns the supported type of this matcher.
082 * @return the supported type of this matcher.
083 */
084 public final Class<T> supportedType() {
085 return supportedType;
086 }
087
088 /**
089 * Verifies that the given component matches some search criteria.
090 * <p>
091 * <b>Note:</b> Implementations of this method <b>may not</b> be guaranteed to be executed in the event dispatch
092 * thread (EDT.) Clients are responsible for invoking this method in the EDT.
093 * </p>
094 * @param component the <code>Component</code> to verify.
095 * @return <code>true</code> if the given component matches the defined search criteria; otherwise, <code>false</code>
096 * .
097 */
098 @RunsInCurrentThread
099 protected abstract boolean isMatching(T component);
100 }