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    }