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.Predicate;
023import org.apache.commons.collections4.Transformer;
024
025/**
026 * Transformer implementation that will call one of two closures based on whether a predicate evaluates
027 * as true or false.
028 *
029 * @param <T> the type of the input to the function.
030 * @param <R> the type of the result of the function.
031 * @since 4.1
032 */
033public class IfTransformer<T, R> implements Transformer<T, R>, Serializable {
034
035    /** Serial version UID */
036    private static final long serialVersionUID = 8069309411242014252L;
037
038    /**
039     * Factory method that performs validation.
040     *
041     * @param <I>  input type for the transformer
042     * @param <O>  output type for the transformer
043     * @param predicate  predicate to switch on
044     * @param trueTransformer  transformer used if true
045     * @param falseTransformer  transformer used if false
046     * @return the {@code if} transformer
047     * @throws NullPointerException if either argument is null
048     */
049    public static <I, O> Transformer<I, O> ifTransformer(final Predicate<? super I> predicate,
050                                                         final Transformer<? super I, ? extends O> trueTransformer,
051                                                         final Transformer<? super I, ? extends O> falseTransformer) {
052        return new IfTransformer<>(Objects.requireNonNull(predicate, "predicate"),
053                Objects.requireNonNull(trueTransformer, "trueTransformer"),
054                Objects.requireNonNull(falseTransformer, "falseTransformer"));
055    }
056    /**
057     * Factory method that performs validation.
058     * <p>
059     * This factory creates a transformer that just returns the input object when
060     * the predicate is false.
061     *
062     * @param <T>  input and output type for the transformer
063     * @param predicate  predicate to switch on
064     * @param trueTransformer  transformer used if true
065     * @return the {@code if} transformer
066     * @throws NullPointerException if either argument is null
067     */
068    public static <T> Transformer<T, T> ifTransformer(
069            final Predicate<? super T> predicate,
070            final Transformer<? super T, ? extends T> trueTransformer) {
071        return new IfTransformer<>(Objects.requireNonNull(predicate, "predicate"),
072                Objects.requireNonNull(trueTransformer, "trueTransformer"), NOPTransformer.<T>nopTransformer());
073    }
074    /** The test */
075    private final Predicate<? super T> iPredicate;
076
077    /** The transformer to use if true */
078    private final Transformer<? super T, ? extends R> iTrueTransformer;
079
080    /** The transformer to use if false */
081    private final Transformer<? super T, ? extends R> iFalseTransformer;
082
083    /**
084     * Constructor that performs no validation.
085     * Use the static factory method {@code ifTransformer} if you want that.
086     *
087     * @param predicate  predicate to switch on, not null
088     * @param trueTransformer  transformer used if true, not null
089     * @param falseTransformer  transformer used if false, not null
090     */
091    public IfTransformer(final Predicate<? super T> predicate,
092        final Transformer<? super T, ? extends R> trueTransformer,
093        final Transformer<? super T, ? extends R> falseTransformer) {
094
095        iPredicate = predicate;
096        iTrueTransformer = trueTransformer;
097        iFalseTransformer = falseTransformer;
098    }
099
100    /**
101     * Gets the transformer used when false.
102     *
103     * @return the transformer
104     */
105    public Transformer<? super T, ? extends R> getFalseTransformer() {
106        return iFalseTransformer;
107    }
108
109    /**
110     * Gets the predicate.
111     *
112     * @return the predicate
113     */
114    public Predicate<? super T> getPredicate() {
115        return iPredicate;
116    }
117
118    /**
119     * Gets the transformer used when true.
120     *
121     * @return the transformer
122     */
123    public Transformer<? super T, ? extends R> getTrueTransformer() {
124        return iTrueTransformer;
125    }
126
127    /**
128     * Transforms the input using the true or false transformer based to the result of the predicate.
129     *
130     * @param input  the input object to transform
131     * @return the transformed result
132     */
133    @Override
134    public R transform(final T input) {
135        if (iPredicate.test(input)) {
136            return iTrueTransformer.apply(input);
137        }
138        return iFalseTransformer.apply(input);
139    }
140}