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;
020import java.util.ArrayList;
021import java.util.Iterator;
022import java.util.List;
023
024import org.apache.commons.functor.UnaryProcedure;
025
026/**
027 * A {@link UnaryProcedure UnaryProcedure}
028 * that {@link UnaryProcedure#run runs} an ordered
029 * sequence of {@link UnaryProcedure UnaryProcedures}.
030 * When the sequence is empty, this procedure is does
031 * nothing.
032 * <p>
033 * Note that although this class implements
034 * {@link Serializable}, a given instance will
035 * only be truly <code>Serializable</code> if all the
036 * underlying functors are.  Attempts to serialize
037 * an instance whose delegates are not all
038 * <code>Serializable</code> will result in an exception.
039 * </p>
040 * @param <A> the argument type.
041 * @version $Revision: 1363382 $ $Date: 2012-07-19 11:23:19 -0400 (Thu, 19 Jul 2012) $
042 */
043public class UnarySequence<A> implements UnaryProcedure<A>, Serializable {
044
045    /**
046     * serialVersionUID declaration.
047     */
048    private static final long serialVersionUID = 9194268249717820246L;
049    // attributes
050    // ------------------------------------------------------------------------
051    /**
052     * The data structure to store the procedure sequence.
053     */
054    private final List<UnaryProcedure<? super A>> list = new ArrayList<UnaryProcedure<? super A>>();
055
056    // constructor
057    // ------------------------------------------------------------------------
058    /**
059     * Create a new UnarySequence.
060     */
061    public UnarySequence() {
062        super();
063    }
064
065    /**
066     * Create a new UnarySequence instance.
067     *
068     * @param procedures to run sequentially
069     */
070    public UnarySequence(UnaryProcedure<? super A>... procedures) {
071        this();
072        if (procedures != null) {
073            for (UnaryProcedure<? super A> p : procedures) {
074                then(p);
075            }
076        }
077    }
078
079    /**
080     * Create a new UnarySequence instance.
081     *
082     * @param procedures to run sequentially
083     */
084    public UnarySequence(Iterable<UnaryProcedure<? super A>> procedures) {
085        this();
086        if (procedures != null) {
087            for (UnaryProcedure<? super A> p : procedures) {
088                then(p);
089            }
090        }
091    }
092
093    // modifiers
094    // ------------------------------------------------------------------------
095    /**
096     * Fluently add a UnaryProcedure to the sequence.
097     * @param p UnaryProcedure to add
098     * @return this
099     */
100    public UnarySequence<A> then(UnaryProcedure<? super A> p) {
101        if (p != null) {
102            list.add(p);
103        }
104        return this;
105    }
106
107    // predicate interface
108    // ------------------------------------------------------------------------
109    /**
110     * {@inheritDoc}
111     */
112    public void run(A obj) {
113        for (Iterator<UnaryProcedure<? super A>> iter = list.iterator(); iter.hasNext();) {
114            iter.next().run(obj);
115        }
116    }
117
118    /**
119     * {@inheritDoc}
120     */
121    @Override
122    public boolean equals(Object that) {
123        return that == this || (that instanceof UnarySequence<?> && equals((UnarySequence<?>) that));
124    }
125
126    /**
127     * Learn whether another UnarySequence is equal to this.
128     * @param that UnarySequence to test
129     * @return boolean
130     */
131    public boolean equals(UnarySequence<?> that) {
132        // by construction, list is never null
133        return null != that && list.equals(that.list);
134    }
135
136    /**
137     * {@inheritDoc}
138     */
139    @Override
140    public int hashCode() {
141        // by construction, list is never null
142        return "UnarySequence".hashCode() ^ list.hashCode();
143    }
144
145    /**
146     * {@inheritDoc}
147     */
148    @Override
149    public String toString() {
150        return "UnarySequence<" + list + ">";
151    }
152
153}