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