1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.functor.core.composite;
18  
19  import java.io.Serializable;
20  import java.util.ArrayList;
21  import java.util.Iterator;
22  import java.util.List;
23  
24  import org.apache.commons.functor.BinaryProcedure;
25  
26  /**
27   * A {@link BinaryProcedure BinaryProcedure}
28   * that {@link BinaryProcedure#run runs} an ordered
29   * sequence of {@link BinaryProcedure BinaryProcedures}.
30   * When the sequence is empty, this procedure is does
31   * nothing.
32   * <p>
33   * Note that although this class implements
34   * {@link Serializable}, a given instance will
35   * only be truly <code>Serializable</code> if all the
36   * underlying functors are.  Attempts to serialize
37   * an instance whose delegates are not all
38   * <code>Serializable</code> will result in an exception.
39   * </p>
40   *
41   * @param <L> the procedure left argument type.
42   * @param <R> the procedure right argument type.
43   * @version $Revision: 1345136 $ $Date: 2012-06-01 09:47:06 -0300 (Fri, 01 Jun 2012) $
44   */
45  public class BinarySequence<L, R> implements BinaryProcedure<L, R>, Serializable {
46      /**
47       * serialVersionUID declaration.
48       */
49      private static final long serialVersionUID = 1371075584406178258L;
50      // attributes
51      // ------------------------------------------------------------------------
52      /**
53       * A list where storing all the procedures references.
54       */
55      private final List<BinaryProcedure<? super L, ? super R>> list =
56          new ArrayList<BinaryProcedure<? super L, ? super R>>();
57  
58      // constructor
59      // ------------------------------------------------------------------------
60      /**
61       * Create a new BinarySequence.
62       */
63      public BinarySequence() {
64          super();
65      }
66  
67      /**
68       * Create a new BinarySequence instance.
69       *
70       * @param procedures to run sequentially
71       */
72      public BinarySequence(BinaryProcedure<? super L, ? super R>... procedures) {
73          this();
74          if (procedures != null) {
75              for (BinaryProcedure<? super L, ? super R> p : procedures) {
76                  then(p);
77              }
78          }
79      }
80  
81      /**
82       * Create a new BinarySequence instance.
83       *
84       * @param procedures to run sequentially
85       */
86      public BinarySequence(Iterable<BinaryProcedure<? super L, ? super R>> procedures) {
87          this();
88          if (procedures != null) {
89              for (BinaryProcedure<? super L, ? super R> p : procedures) {
90                  then(p);
91              }
92          }
93      }
94  
95      /**
96       * Fluently add a BinaryProcedure.
97       * @param p BinaryProcedure to add
98       * @return this
99       */
100     public final BinarySequence<L, R> then(BinaryProcedure<? super L, ? super R> p) {
101         list.add(p);
102         return this;
103     }
104 
105     // predicate interface
106     // ------------------------------------------------------------------------
107     /**
108      * {@inheritDoc}
109      */
110     public final void run(L left, R right) {
111         for (Iterator<BinaryProcedure<? super L, ? super R>> iter = list.iterator(); iter.hasNext();) {
112             iter.next().run(left, right);
113         }
114     }
115 
116     /**
117      * {@inheritDoc}
118      */
119     @Override
120     public final boolean equals(Object that) {
121         return that == this || (that instanceof BinarySequence<?, ?> && equals((BinarySequence<?, ?>) that));
122     }
123 
124     /**
125      * Learn whether another BinarySequence is equal to this.
126      * @param that BinarySequence to test
127      * @return boolean
128      */
129     public final boolean equals(BinarySequence<?, ?> that) {
130         // by construction, list is never null
131         return null != that && list.equals(that.list);
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     public int hashCode() {
139         // by construction, list is never null
140         return "BinarySequence".hashCode() ^ list.hashCode();
141     }
142 
143     /**
144      * {@inheritDoc}
145      */
146     @Override
147     public String toString() {
148         return "BinarySequence<" + list + ">";
149     }
150 
151 }