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 */
017package org.apache.commons.collections4.functors;
018
019import java.io.Serializable;
020import java.util.Objects;
021
022import org.apache.commons.collections4.Closure;
023import org.apache.commons.collections4.Predicate;
024
025/**
026 * Closure implementation acts as an if statement calling one or other closure
027 * based on a predicate.
028 *
029 * @param <T> the type of the input to the operation.
030 * @since 3.0
031 */
032public class IfClosure<T> implements Closure<T>, Serializable {
033
034    /** Serial version UID */
035    private static final long serialVersionUID = 3518477308466486130L;
036
037    /**
038     * Factory method that performs validation.
039     * <p>
040     * This factory creates a closure that performs no action when
041     * the predicate is false.
042     *
043     * @param <E> the type that the closure acts on
044     * @param predicate  predicate to switch on
045     * @param trueClosure  closure used if true
046     * @return the {@code if} closure
047     * @throws NullPointerException if either argument is null
048     * @since 3.2
049     */
050    public static <E> Closure<E> ifClosure(final Predicate<? super E> predicate, final Closure<? super E> trueClosure) {
051        return IfClosure.<E>ifClosure(predicate, trueClosure, NOPClosure.<E>nopClosure());
052    }
053    /**
054     * Factory method that performs validation.
055     *
056     * @param <E> the type that the closure acts on
057     * @param predicate  predicate to switch on
058     * @param trueClosure  closure used if true
059     * @param falseClosure  closure used if false
060     * @return the {@code if} closure
061     * @throws NullPointerException if any argument is null
062     */
063    public static <E> Closure<E> ifClosure(final Predicate<? super E> predicate,
064                                           final Closure<? super E> trueClosure,
065                                           final Closure<? super E> falseClosure) {
066        return new IfClosure<>(Objects.requireNonNull(predicate, "predicate"),
067                Objects.requireNonNull(trueClosure, "trueClosure"),
068                Objects.requireNonNull(falseClosure, "falseClosure"));
069    }
070    /** The test */
071    private final Predicate<? super T> iPredicate;
072
073    /** The closure to use if true */
074    private final Closure<? super T> iTrueClosure;
075
076    /** The closure to use if false */
077    private final Closure<? super T> iFalseClosure;
078
079    /**
080     * Constructor that performs no validation.
081     * Use {@code ifClosure} if you want that.
082     * <p>
083     * This constructor creates a closure that performs no action when
084     * the predicate is false.
085     *
086     * @param predicate  predicate to switch on, not null
087     * @param trueClosure  closure used if true, not null
088     * @since 3.2
089     */
090    public IfClosure(final Predicate<? super T> predicate, final Closure<? super T> trueClosure) {
091        this(predicate, trueClosure, NOPClosure.nopClosure());
092    }
093
094    /**
095     * Constructor that performs no validation.
096     * Use {@code ifClosure} if you want that.
097     *
098     * @param predicate  predicate to switch on, not null
099     * @param trueClosure  closure used if true, not null
100     * @param falseClosure  closure used if false, not null
101     */
102    public IfClosure(final Predicate<? super T> predicate, final Closure<? super T> trueClosure,
103                     final Closure<? super T> falseClosure) {
104        iPredicate = predicate;
105        iTrueClosure = trueClosure;
106        iFalseClosure = falseClosure;
107    }
108
109    /**
110     * Executes the true or false closure according to the result of the predicate.
111     *
112     * @param input  the input object
113     */
114    @Override
115    public void execute(final T input) {
116        if (iPredicate.test(input)) {
117            iTrueClosure.accept(input);
118        } else {
119            iFalseClosure.accept(input);
120        }
121    }
122
123    /**
124     * Gets the closure called when false.
125     *
126     * @return the closure
127     * @since 3.1
128     */
129    public Closure<? super T> getFalseClosure() {
130        return iFalseClosure;
131    }
132
133    /**
134     * Gets the predicate.
135     *
136     * @return the predicate
137     * @since 3.1
138     */
139    public Predicate<? super T> getPredicate() {
140        return iPredicate;
141    }
142
143    /**
144     * Gets the closure called when true.
145     *
146     * @return the closure
147     * @since 3.1
148     */
149    public Closure<? super T> getTrueClosure() {
150        return iTrueClosure;
151    }
152
153}