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 *      https://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    /**
058     * Factory method that performs validation.
059     * <p>
060     * This factory creates a transformer that just returns the input object when
061     * the predicate is false.
062     * </p>
063     *
064     * @param <T>  input and output type for the transformer
065     * @param predicate  predicate to switch on
066     * @param trueTransformer  transformer used if true
067     * @return The {@code if} transformer
068     * @throws NullPointerException if either argument is null
069     */
070    public static <T> Transformer<T, T> ifTransformer(
071            final Predicate<? super T> predicate,
072            final Transformer<? super T, ? extends T> trueTransformer) {
073        return new IfTransformer<>(Objects.requireNonNull(predicate, "predicate"),
074                Objects.requireNonNull(trueTransformer, "trueTransformer"), NOPTransformer.<T>nopTransformer());
075    }
076
077    /** The test */
078    private final Predicate<? super T> iPredicate;
079
080    /** The transformer to use if true */
081    private final Transformer<? super T, ? extends R> iTrueTransformer;
082
083    /** The transformer to use if false */
084    private final Transformer<? super T, ? extends R> iFalseTransformer;
085
086    /**
087     * Constructor that performs no validation.
088     * Use the static factory method {@code ifTransformer} if you want that.
089     *
090     * @param predicate  predicate to switch on, not null
091     * @param trueTransformer  transformer used if true, not null
092     * @param falseTransformer  transformer used if false, not null
093     */
094    public IfTransformer(final Predicate<? super T> predicate,
095        final Transformer<? super T, ? extends R> trueTransformer,
096        final Transformer<? super T, ? extends R> falseTransformer) {
097
098        iPredicate = predicate;
099        iTrueTransformer = trueTransformer;
100        iFalseTransformer = falseTransformer;
101    }
102
103    /**
104     * Gets the transformer used when false.
105     *
106     * @return The transformer
107     */
108    public Transformer<? super T, ? extends R> getFalseTransformer() {
109        return iFalseTransformer;
110    }
111
112    /**
113     * Gets the predicate.
114     *
115     * @return The predicate
116     */
117    public Predicate<? super T> getPredicate() {
118        return iPredicate;
119    }
120
121    /**
122     * Gets the transformer used when true.
123     *
124     * @return The transformer
125     */
126    public Transformer<? super T, ? extends R> getTrueTransformer() {
127        return iTrueTransformer;
128    }
129
130    /**
131     * Transforms the input using the true or false transformer based to the result of the predicate.
132     *
133     * @param input  The input object to transform
134     * @return The transformed result
135     */
136    @Override
137    public R transform(final T input) {
138        if (iPredicate.test(input)) {
139            return iTrueTransformer.apply(input);
140        }
141        return iFalseTransformer.apply(input);
142    }
143}