001    /*
002     * Created on Jul 17, 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.matcher;
017    
018    import static java.lang.String.valueOf;
019    import static org.fest.util.Strings.concat;
020    
021    import java.util.regex.Pattern;
022    
023    import javax.swing.text.JTextComponent;
024    
025    import org.fest.swing.annotation.RunsInCurrentThread;
026    
027    /**
028     * Understands matching a <code>{@link JTextComponent}</code> by type, name or text.
029     *
030     * @author Alex Ruiz
031     */
032    public final class JTextComponentMatcher extends NamedComponentMatcherTemplate<JTextComponent> {
033    
034      private Object text;
035    
036      /**
037       * Creates a new <code>{@link JTextComponentMatcher}</code> that matches a <code>{@link JTextComponent}</code> that:
038       * <ol>
039       * <li>has a matching name</li>
040       * <li>(optionally) has matching text</li>
041       * <li>(optionally) is showing on the screen</li>
042       * <p>
043       * The following code listing shows how to match a <code>{@link JTextComponent}</code> by name and text:
044       * <pre>
045       * JTextComponentMatcher m = {@link #withName(String) withName}("lastName").{@link #andText(String) andText}("Wang");
046       * </pre>
047       * </p>
048       * <p>
049       * The following code listing shows how to match a <code>{@link JTextComponent}</code>, that should be showing on the screen,
050       * by name and text:
051       * <pre>
052       * JTextComponentMatcher m = {@link #withName(String) withName}("lastName").{@link #andText(String) andText}("Wang").{@link #andShowing() andShowing}();
053       * </pre>
054       * </p>
055       * @param name the id to match.
056       * @return the created matcher.
057       */
058      public static JTextComponentMatcher withName(String name) {
059        return new JTextComponentMatcher(name, ANY);
060      }
061    
062      /**
063       * Creates a new <code>{@link JTextComponentMatcher}</code> that matches a <code>{@link JTextComponent}</code> by its
064       * text.
065       * <p>
066       * The following code listing shows how to match a <code>{@link JTextComponent}</code> by text:
067       * <pre>
068       * JTextComponentMatcher m = {@link #withText(String) withText}("Wang");
069       * </pre>
070       * </p>
071       * <p>
072       * The following code listing shows how to match a <code>{@link JTextComponent}</code>, that should be showing on the
073       * screen, by text:
074       * <pre>
075       * JTextComponentMatcher m = {@link #withText(String) withText}("Wang").{@link #andShowing() andShowing}();
076       * </pre>
077       * </p>
078       * @param text the text to match. It can be a regular expression.
079       * @return the created matcher.
080       */
081      public static JTextComponentMatcher withText(String text) {
082        return new JTextComponentMatcher(ANY, text);
083      }
084    
085      /**
086       * Creates a new <code>{@link JTextComponentMatcher}</code> that matches a <code>{@link JTextComponent}</code> by its
087       * text.
088       * <p>
089       * The following code listing shows how to match a <code>{@link JTextComponent}</code> by text, using a regular
090       * expression pattern:
091       * <pre>
092       * JTextComponentMatcher m = {@link #withText(Pattern) withText}(Pattern.compile("W.*"));
093       * </pre>
094       * </p>
095       * <p>
096       * The following code listing shows how to match a <code>{@link JTextComponent}</code>, that should be showing on the
097       * screen, by text, using a regular expression pattern:
098       * <pre>
099       * JTextComponentMatcher m = {@link #withText(Pattern) withText}(Pattern.compile("W.*")).{@link #andShowing() andShowing}();
100       * </pre>
101       * </p>
102       * @param textPattern the text to match. It can be a regular expression.
103       * @return the created matcher.
104       */
105      public static JTextComponentMatcher withText(Pattern textPattern) {
106        return new JTextComponentMatcher(ANY, textPattern);
107      }
108    
109      /**
110       * Creates a new <code>{@link JTextComponentMatcher}</code> that matches any <code>{@link JTextComponent}</code>.
111       * @return the created matcher.
112       */
113      public static JTextComponentMatcher any() {
114        return new JTextComponentMatcher(ANY, ANY);
115      }
116    
117      private JTextComponentMatcher(Object name, Object text) {
118        super(JTextComponent.class, name);
119        this.text = text;
120      }
121    
122      /**
123       * Specifies the text to match. If this matcher was created using <code>{@link #withText(String)}</code> or
124       * <code>{@link #withText(Pattern)}</code>, this method will simply update the text to match.
125       * @param newText the new text to match. It can be a regular expression.
126       * @return this matcher.
127       */
128      public JTextComponentMatcher andText(String newText) {
129        text = newText;
130        return this;
131      }
132    
133      /**
134       * Specifies the text to match. If this matcher was created using <code>{@link #withText(String)}</code> or
135       * <code>{@link #withText(Pattern)}</code>, this method will simply update the text to match.
136       * @param textPattern the regular expression pattern to match.
137       * @return this matcher.
138       * @since 1.2
139       */
140      public JTextComponentMatcher andText(Pattern textPattern) {
141        text = textPattern;
142        return this;
143      }
144    
145      /**
146       * Indicates that the <code>{@link JTextComponent}</code> to match should be showing on the screen.
147       * @return this matcher.
148       */
149      public JTextComponentMatcher andShowing() {
150        requireShowing(true);
151        return this;
152      }
153    
154      /**
155       * Indicates whether the text of the given <code>{@link JTextComponent}</code> is equal to the text in this matcher.
156       * <p>
157       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
158       * responsible for calling this method from the EDT.
159       * </p>
160       * @param button the <code>JTextComponent</code> to match.
161       * @return <code>true</code> if the text in the <code>JTextComponent</code> is equal to the text in this matcher,
162       * <code>false</code> otherwise.
163       */
164      @RunsInCurrentThread
165      protected boolean isMatching(JTextComponent button) {
166        if (!isNameMatching(button.getName())) return false;
167        return arePropertyValuesMatching(text, button.getText());
168      }
169    
170      @Override public String toString() {
171        return concat(
172            getClass().getName(), "[",
173            "name=", quotedName(), ", ",
174            "text=", quoted(text), ", ",
175            "requireShowing=", valueOf(requireShowing()),
176            "]"
177        );
178      }
179    }