001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.commons.collections.functors;
018    
019    import java.io.Serializable;
020    
021    import org.apache.commons.collections.Closure;
022    import org.apache.commons.collections.Predicate;
023    
024    /**
025     * Closure implementation that executes a closure repeatedly until a condition is met,
026     * like a do-while or while loop.
027     * 
028     * @since Commons Collections 3.0
029     * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
030     *
031     * @author Stephen Colebourne
032     */
033    public class WhileClosure implements Closure, Serializable {
034    
035        /** Serial version UID */
036        private static final long serialVersionUID = -3110538116913760108L;
037    
038        /** The test condition */
039        private final Predicate iPredicate;
040        /** The closure to call */
041        private final Closure iClosure;
042        /** The flag, true is a do loop, false is a while */
043        private final boolean iDoLoop;
044    
045        /**
046         * Factory method that performs validation.
047         * 
048         * @param predicate  the predicate used to evaluate when the loop terminates, not null
049         * @param closure  the closure the execute, not null
050         * @param doLoop  true to act as a do-while loop, always executing the closure once
051         * @return the <code>while</code> closure
052         * @throws IllegalArgumentException if the predicate or closure is null
053         */
054        public static Closure getInstance(Predicate predicate, Closure closure, boolean doLoop) {
055            if (predicate == null) {
056                throw new IllegalArgumentException("Predicate must not be null");
057            }
058            if (closure == null) {
059                throw new IllegalArgumentException("Closure must not be null");
060            }
061            return new WhileClosure(predicate, closure, doLoop);
062        }
063    
064        /**
065         * Constructor that performs no validation.
066         * Use <code>getInstance</code> if you want that.
067         * 
068         * @param predicate  the predicate used to evaluate when the loop terminates, not null
069         * @param closure  the closure the execute, not null
070         * @param doLoop  true to act as a do-while loop, always executing the closure once
071         */
072        public WhileClosure(Predicate predicate, Closure closure, boolean doLoop) {
073            super();
074            iPredicate = predicate;
075            iClosure = closure;
076            iDoLoop = doLoop;
077        }
078    
079        /**
080         * Executes the closure until the predicate is false.
081         * 
082         * @param input  the input object
083         */
084        public void execute(Object input) {
085            if (iDoLoop) {
086                iClosure.execute(input);
087            }
088            while (iPredicate.evaluate(input)) {
089                iClosure.execute(input);
090            }
091        }
092    
093        /**
094         * Gets the predicate in use.
095         * 
096         * @return the predicate
097         * @since Commons Collections 3.1
098         */
099        public Predicate getPredicate() {
100            return iPredicate;
101        }
102    
103        /**
104         * Gets the closure.
105         * 
106         * @return the closure
107         * @since Commons Collections 3.1
108         */
109        public Closure getClosure() {
110            return iClosure;
111        }
112    
113        /**
114         * Is the loop a do-while loop.
115         * 
116         * @return true is do-while, false if while
117         * @since Commons Collections 3.1
118         */
119        public boolean isDoLoop() {
120            return iDoLoop;
121        }
122    
123    }