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.functor.core.composite;
018
019import java.io.Serializable;
020
021import org.apache.commons.functor.Function;
022import org.apache.commons.functor.Procedure;
023import org.apache.commons.functor.UnaryProcedure;
024import org.apache.commons.lang3.Validate;
025
026/**
027 * A Procedure composed of a Function whose result is then run through a UnaryProcedure.
028 * @version $Revision: 1365329 $ $Date: 2012-07-24 18:34:23 -0400 (Tue, 24 Jul 2012) $
029 */
030public class TransformedProcedure implements Procedure, Serializable {
031    /**
032     * serialVersionUID declaration.
033     */
034    private static final long serialVersionUID = -4111958123789033410L;
035
036    /** Base hash integer used to shift hash. */
037    private static final int HASH_SHIFT = 2;
038
039    /**
040     * Type-remembering helper.
041     * @param <X> the adapted function argument type.
042     */
043    private static final class Helper<X> implements Procedure, Serializable {
044        /**
045         * serialVersionUID declaration.
046         */
047        private static final long serialVersionUID = -4093503167446891318L;
048        /**
049         * The adapted function.
050         */
051        private Function<? extends X> function;
052        /**
053         * The adapted procedure.
054         */
055        private UnaryProcedure<? super X> procedure;
056
057        /**
058         * Create a new Helper.
059         * @param function Function
060         * @param procedure UnaryFunction
061         */
062        private Helper(Function<? extends X> function, UnaryProcedure<? super X> procedure) {
063            this.function = Validate.notNull(function, "Function argument must not be null");
064            this.procedure = Validate.notNull(procedure, "UnaryProcedure argument must not be null");
065        }
066
067        /**
068         * {@inheritDoc}
069         */
070        public void run() {
071            procedure.run(function.evaluate());
072        }
073    }
074
075    /**
076     * The adapted helper.
077     */
078    private final Helper<?> helper;
079
080    /**
081     * Create a new TransformedProcedure.
082     * @param <X> the adapted function argument type.
083     * @param function Function
084     * @param procedure UnaryProcedure
085     */
086    public <X> TransformedProcedure(Function<? extends X> function, UnaryProcedure<? super X> procedure) {
087        this.helper = new Helper<X>(function, procedure);
088    }
089
090    /**
091     * {@inheritDoc}
092     */
093    public final void run() {
094        helper.run();
095    }
096
097    /**
098     * {@inheritDoc}
099     */
100    @Override
101    public final boolean equals(Object obj) {
102        return obj == this || obj instanceof TransformedProcedure
103                && equals((TransformedProcedure) obj);
104    }
105
106    /**
107     * Learn whether another TransformedProcedure is equal to <code>this</code>.
108     * @param that instance to test
109     * @return whether equal
110     */
111    public final boolean equals(TransformedProcedure that) {
112        return that != null && that.helper.function.equals(this.helper.function)
113                && that.helper.procedure.equals(this.helper.procedure);
114    }
115
116    /**
117     * {@inheritDoc}
118     */
119    @Override
120    public int hashCode() {
121        int result = "TransformedProcedure".hashCode();
122        result <<= HASH_SHIFT;
123        result |= helper.procedure.hashCode();
124        result <<= HASH_SHIFT;
125        result |= helper.function.hashCode();
126        return result;
127    }
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public String toString() {
134        return "TransformedProcedure<" + helper.function + "; " + helper.procedure + ">";
135    }
136}