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.functor.core.composite;
018    
019    import org.apache.commons.functor.BinaryFunction;
020    import org.apache.commons.functor.BinaryPredicate;
021    import org.apache.commons.functor.UnaryFunction;
022    import org.apache.commons.functor.UnaryPredicate;
023    import org.apache.commons.functor.UnaryProcedure;
024    
025    /**
026     * Utility/fluent methods for creating composite functors.
027     * @version $Revision: 1166365 $ $Date: 2011-09-07 22:06:50 +0200 (Wed, 07 Sep 2011) $
028     * @author Rodney Waldhoff
029     */
030    public final class Composite {
031        // constructor - for beanish apis
032        // ------------------------------------------------------------------------
033        /**
034         * <p>{@code Composite} instances should NOT be constructed in
035         * standard programming. Instead, the methods of the class should be invoked
036         * statically.</p>
037         *
038         * <p>This constructor is public to permit tools that require a JavaBean
039         * instance to operate.</p>
040         */
041        public Composite() { }
042    
043        /**
044         * Create a composite UnaryProcedure.
045         * @param procedure UnaryProcedure to execute against output of <code>f</code>
046         * @return CompositeUnaryProcedure<A>
047         */
048        public static <A> CompositeUnaryProcedure<A> procedure(UnaryProcedure<? super A> procedure) {
049            return new CompositeUnaryProcedure<A>(procedure);
050        }
051    
052        /**
053         * Create a composite UnaryProcedure.
054         * @param procedure UnaryProcedure to execute against output of <code>f</code>
055         * @param function UnaryFunction to apply
056         * @return CompositeUnaryProcedure<A>
057         */
058        public static <A, T> CompositeUnaryProcedure<A> procedure(UnaryProcedure<? super T> procedure,
059                UnaryFunction<? super A, ? extends T> function) {
060            return new CompositeUnaryProcedure<T>(procedure).of(function);
061        }
062    
063        /**
064         * Create a composite UnaryPredicate.
065         * @param pred UnaryPredicate to test the output of <code>f</code>
066         * @return CompositeUnaryPredicate<A>
067         */
068        public static <A> CompositeUnaryPredicate<A> predicate(UnaryPredicate<? super A> pred) {
069            return new CompositeUnaryPredicate<A>(pred);
070        }
071    
072        /**
073         * Create a composite UnaryPredicate.
074         * @param predicate UnaryPredicate to test the output of <code>f</code>
075         * @param function UnaryFunction to apply
076         * @return CompositeUnaryPredicate<A>
077         */
078        public static <A, T> CompositeUnaryPredicate<A> predicate(UnaryPredicate<? super T> predicate,
079                UnaryFunction<? super A, ? extends T> function) {
080            return new CompositeUnaryPredicate<T>(predicate).of(function);
081        }
082    
083        /**
084         * Create a composite BinaryPredicate.
085         * @param p BinaryPredicate to test <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i>
086         * @param g left UnaryFunction
087         * @param h right UnaryFunction
088         * @return BinaryPredicate
089         */
090        public static <L, R, G, H> UnaryCompositeBinaryPredicate<L, R> predicate(
091                BinaryPredicate<? super G, ? super H> p, UnaryFunction<? super L, ? extends G> g,
092                UnaryFunction<? super R, ? extends H> h) {
093            return new UnaryCompositeBinaryPredicate<L, R>(p, g, h);
094        }
095    
096        /**
097         * Create a composite UnaryFunction.
098         * @param f UnaryFunction to apply to the output of <code>g</code>
099         * @return UnaryFunction
100         */
101        public static <A, T> CompositeUnaryFunction<A, T> function(UnaryFunction<? super A, ? extends T> f) {
102            return new CompositeUnaryFunction<A, T>(f);
103        }
104    
105        /**
106         * Create a composite UnaryFunction.
107         * @param f UnaryFunction to apply to the output of <code>g</code>
108         * @param g UnaryFunction to apply first
109         * @return UnaryFunction
110         */
111        public static <A, X, T> CompositeUnaryFunction<A, T> function(UnaryFunction<? super X, ? extends T> f,
112                UnaryFunction<? super A, ? extends X> g) {
113            return new CompositeUnaryFunction<X, T>(f).of(g);
114        }
115    
116    //    /**
117    //     * Chain a BinaryFunction to a UnaryFunction.
118    //     * @param <L>
119    //     * @param <R>
120    //     * @param <X>
121    //     * @param <T>
122    //     * @param f UnaryFunction to apply to the output of <code>g</code>
123    //     * @param g BinaryFunction to apply first
124    //     * @return BinaryFunction<L, R, T>
125    //     */
126    //    public static <L, R, X, T> BinaryFunction<L, R, T> function(UnaryFunction<? super X, ? extends T> f,
127    //             BinaryFunction<? super L,
128    //             ? super R, ? extends X> g) {
129    //        return new CompositeUnaryFunction<X, T>(f).of(g);
130    //    }
131    
132        /**
133         * Create a composite<UnaryFunction> BinaryFunction.
134         * @param f BinaryFunction to apply to <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i>
135         * @param g left UnaryFunction
136         * @param h right UnaryFunction
137         * @return BinaryFunction
138         */
139        public static <L, R, G, H, T> UnaryCompositeBinaryFunction<L, R, T> function(
140                BinaryFunction<? super G, ? super H, ? extends T> f, UnaryFunction<? super L, ? extends G> g,
141                UnaryFunction<? super R, ? extends H> h) {
142            return new UnaryCompositeBinaryFunction<L, R, T>(f, g, h);
143        }
144    
145        /**
146         * Create a composite<BinaryFunction> BinaryFunction.
147         * @param f BinaryFunction to apply to <i>output(</i><code>f</code><i>), output(</i><code>g</code><i>)</i>
148         * @param g left BinaryFunction
149         * @param h right BinaryFunction
150         * @return BinaryFunction
151         */
152        public static <L, R, G, H, T> BinaryCompositeBinaryFunction<L, R, T> function(
153                BinaryFunction<? super G, ? super H, ? extends T> f, BinaryFunction<? super L, ? super R, ? extends G> g,
154                BinaryFunction<? super L, ? super R, ? extends H> h) {
155            return new BinaryCompositeBinaryFunction<L, R, T>(f, g, h);
156        }
157    }