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