001    /*
002     * Created on Dec 19, 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.timing;
017    
018    import static org.fest.swing.util.TimeoutWatch.startWatchWithTimeoutOf;
019    import static org.fest.util.Arrays.format;
020    import static org.fest.util.Arrays.isEmpty;
021    import static org.fest.util.Strings.concat;
022    
023    import java.util.concurrent.TimeUnit;
024    
025    import org.fest.swing.exception.WaitTimedOutError;
026    import org.fest.swing.util.TimeoutWatch;
027    
028    /**
029     * Understands waiting for period of time or for a particular condition to be satisfied.
030     *
031     * @author Alex Ruiz
032     * @author Yvonne Wang
033     */
034    public final class Pause {
035    
036      private static final int DEFAULT_DELAY = 30000;
037      private static final int SLEEP_INTERVAL = 10;
038    
039      /**
040       * Waits until the given condition is satisfied.
041       * @param condition the condition to verify.
042       * @throws NullPointerException if the given condition is <code>null</code>.
043       * @throws WaitTimedOutError if the wait times out (more than 30 seconds).
044       */
045      public static void pause(Condition condition) {
046        pause(condition, DEFAULT_DELAY);
047      }
048    
049      /**
050       * Waits until the given condition is satisfied.
051       * @param condition the condition to verify.
052       * @param timeout the timeout.
053       * @throws NullPointerException if the given timeout is <code>null</code>.
054       * @throws NullPointerException if the given condition is <code>null</code>.
055       * @throws WaitTimedOutError if the wait times out.
056       */
057      public static void pause(Condition condition, Timeout timeout) {
058        if (timeout == null) throw new NullPointerException("The given timeout should not be null");
059        pause(condition, timeout.duration());
060      }
061    
062      /**
063       * Waits until the given condition is satisfied.
064       * @param condition the condition to verify.
065       * @param timeout the timeout (in milliseconds.)
066       * @throws NullPointerException if the given condition is <code>null</code>.
067       * @throws WaitTimedOutError if the wait times out.
068       */
069      public static void pause(Condition condition, long timeout) {
070        if (condition == null) throw new NullPointerException("The condition to verify should not be null");
071        TimeoutWatch watch = startWatchWithTimeoutOf(timeout);
072        while (!condition.test()) {
073          if (watch.isTimeOut() && !condition.test()) {
074            condition.done();
075            throw timeoutExpired(condition);
076          }
077          pause(SLEEP_INTERVAL);
078        }
079        condition.done();
080      }
081    
082      private static WaitTimedOutError timeoutExpired(Condition condition) {
083        return new WaitTimedOutError((concat("Timed out waiting for ", condition)));
084      }
085    
086      /**
087       * Waits until the given conditions are satisfied.
088       * @param conditions the conditions to verify.
089       * @throws NullPointerException if the array of conditions is <code>null</code>.
090       * @throws IllegalArgumentException if the array of conditions is empty.
091       * @throws NullPointerException if the array of conditions has one or more <code>null</code> values.
092       * @throws WaitTimedOutError if the wait times out (more than 30 seconds).
093       */
094      public static void pause(Condition[] conditions) {
095        pause(conditions, DEFAULT_DELAY);
096      }
097    
098      /**
099       * Waits until the given conditions are satisfied.
100       * @param conditions the conditions to verify.
101       * @param timeout the timeout.
102       * @throws NullPointerException if the given timeout is <code>null</code>.
103       * @throws NullPointerException if the array of conditions is <code>null</code>.
104       * @throws IllegalArgumentException if the array of conditions is empty.
105       * @throws NullPointerException if the array of conditions has one or more <code>null</code> values.
106       * @throws WaitTimedOutError if the wait times out.
107       */
108      public static void pause(Condition[] conditions, Timeout timeout) {
109        pause(conditions, timeout.duration());
110      }
111    
112      /**
113       * Waits until the given conditions are satisfied.
114       * @param conditions the conditions to verify.
115       * @param timeout the timeout (in milliseconds.)
116       * @throws NullPointerException if the array of conditions is <code>null</code>.
117       * @throws IllegalArgumentException if the array of conditions is empty.
118       * @throws NullPointerException if the array of conditions has one or more <code>null</code> values.
119       * @throws WaitTimedOutError if the wait times out.
120       */
121      public static void pause(Condition[] conditions, long timeout) {
122        validate(conditions);
123        TimeoutWatch watch = startWatchWithTimeoutOf(timeout);
124        while (!areSatisfied(conditions)) {
125          if (watch.isTimeOut()) {
126            done(conditions);
127            throw timeoutExpired(conditions);
128          }
129          pause(SLEEP_INTERVAL);
130        }
131        done(conditions);
132      }
133    
134      private static void validate(Condition[] conditions) {
135        if (conditions == null) throw new NullPointerException("The array of conditions to verify should not be null");
136        if (isEmpty(conditions))
137          throw new IllegalArgumentException("The array of conditions to verify should not be empty");
138        for (Condition condition : conditions) {
139          if (condition != null) continue;
140          throw new NullPointerException(concat(
141              "The array of conditions <", format(conditions), "> contains one or more null values"));
142        }
143      }
144    
145      private static boolean areSatisfied(Condition[] conditions) {
146        for (Condition condition : conditions) if (!condition.test()) return false;
147        return true;
148      }
149    
150      private static void done(Condition[] conditions) {
151        for (Condition condition : conditions) condition.done();
152      }
153    
154      private static WaitTimedOutError timeoutExpired(Condition[] conditions) {
155        return new WaitTimedOutError((concat("Timed out waiting for ", format(conditions))));
156      }
157    
158      /**
159       * Sleeps for the specified time.
160       * @param timeout the quantity of time units to sleep.
161       * @param unit the time units.
162       * @see #pause(long)
163       * @throws NullPointerException if <code>unit</code> is <code>null</code>.
164       */
165      public static void pause(long timeout, TimeUnit unit) {
166        if (unit == null) throw new NullPointerException("Time unit cannot be null");
167        pause(unit.toMillis(timeout));
168      }
169    
170      /**
171       * Sleeps for the specified time.
172       * <p>
173       * To catch any <code>InterruptedException</code>s that occur, <code>{@link Thread#sleep(long)}()</code> may be used
174       * instead.
175       * </p>
176       * @param ms the time to sleep in milliseconds.
177       */
178      public static void pause(long ms) {
179        try {
180          Thread.sleep(ms);
181        } catch (InterruptedException e) {
182          Thread.currentThread().interrupt();
183        }
184      }
185    
186      /**
187       * Sleeps for 10 milliseconds.
188       */
189      public static void pause() { pause(SLEEP_INTERVAL); }
190    
191      private Pause() {}
192    }