001    /*
002     * Created on Dec 22, 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 static java.lang.String.valueOf;
019    import static org.fest.util.Objects.areEqual;
020    import static org.fest.util.Strings.*;
021    
022    import java.awt.Component;
023    
024    import org.fest.swing.annotation.RunsInCurrentThread;
025    
026    /**
027     * Understands <code>{@link java.awt.Component}</code> matching by name and (optionally) by type.
028     *
029     * @author Alex Ruiz
030     */
031    public final class NameMatcher extends AbstractComponentMatcher {
032    
033      private final String name;
034      private final Class<? extends Component> type;
035    
036      /**
037       * Creates a new <code>{@link NameMatcher}</code>. The component to match does not have to be showing.
038       * @param name the name of the component we are looking for.
039       * @throws NullPointerException if the given name is <code>null</code>.
040       * @throws IllegalArgumentException if the given name is empty.
041       */
042      public NameMatcher(String name) {
043        this(name, false);
044      }
045    
046      /**
047       * Creates a new <code>{@link NameMatcher}</code>.
048       * @param name the name of the component we are looking for.
049       * @param requireShowing indicates if the component to match should be showing or not.
050       * @throws NullPointerException if the given name is <code>null</code>.
051       * @throws IllegalArgumentException if the given name is empty.
052       */
053      public NameMatcher(String name, boolean requireShowing) {
054        this(name, Component.class, requireShowing);
055      }
056    
057      /**
058       * Creates a new <code>{@link NameMatcher}</code>. The component to match does not have to be showing.
059       * @param name the name of the component we are looking for.
060       * @param type the type of the component we are looking for.
061       * @throws NullPointerException if the given name is empty.
062       * @throws IllegalArgumentException if the given name is empty.
063       * @throws NullPointerException if the given type is <code>null</code>.
064       */
065      public NameMatcher(String name, Class<? extends Component> type) {
066        this(name, type, false);
067      }
068    
069      /**
070       * Creates a new <code>{@link NameMatcher}</code>.
071       * @param name the name of the component we are looking for.
072       * @param type the type of the component we are looking for.
073       * @param requireShowing indicates if the component to match should be showing or not.
074       * @throws NullPointerException if the given name is empty.
075       * @throws IllegalArgumentException if the given name is empty.
076       * @throws NullPointerException if the given type is <code>null</code>.
077       */
078      public NameMatcher(String name, Class<? extends Component> type, boolean requireShowing) {
079        super(requireShowing);
080        if (name == null) throw new NullPointerException("The name of the component to find should not be null");
081        if (isEmpty(name)) throw new IllegalArgumentException("The name of the component to find should not be empty");
082        if (type == null) throw new NullPointerException("The type of component to find should not be null");
083        this.name = name;
084        this.type = type;
085      }
086    
087      /**
088       * Indicates whether the name and visibility of the given <code>{@link java.awt.Component}</code> matches the value
089       * specified in this matcher.
090       * <p>
091       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
092       * responsible for calling this method from the EDT.
093       * </p>
094       * @return <code>true</code> if the name and visibility of the given <code>Component</code> matches the values
095       * specified in this matcher, <code>false</code> otherwise.
096       */
097      @RunsInCurrentThread
098      public boolean matches(Component c) {
099        return areEqual(name, c.getName()) && type.isInstance(c) && requireShowingMatches(c);
100      }
101    
102      @Override public String toString() {
103        return concat(
104            getClass().getName(), "[",
105            "name=", quote(name), ", ",
106            "type=", type.getName(), ", ",
107            "requireShowing=", valueOf(requireShowing()),
108            "]"
109        );
110      }
111    }