001 /* 002 * Copyright 2002-2004 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.rules.closure.support; 017 018 import java.util.Arrays; 019 import java.util.Iterator; 020 import java.util.LinkedHashSet; 021 import java.util.Set; 022 023 import org.springframework.rules.closure.Closure; 024 import org.springframework.core.style.ToStringCreator; 025 026 /** 027 * A chain of closures that evaluate their results in a ordered sequence. 028 * <p> 029 * For example, declaring 030 * <code>new ClosureChain() { f1, f2, f3 }.call(fooArg)</code> will trigger 031 * the evaluation of <code>f1</code> first, it's result will be passed to 032 * <code>f2</code> for evaluation, and f2's result will be passed to 033 * <code>f3</code> for evaluation. The final f3 result will be returned to the 034 * caller. 035 * </p> 036 * 037 * @author Keith Donald 038 */ 039 public class ClosureChain implements Closure { 040 041 /** Holds the sequence of closures. */ 042 private Set closures = new LinkedHashSet(); 043 044 /** 045 * Constructs a function chain with no initial members. It is expected the 046 * client will call "add" to add individual predicates. 047 */ 048 public ClosureChain() { 049 050 } 051 052 /** 053 * Creates a chain composed of two functions. 054 * 055 * @param function1 the first function 056 * @param function2 the second function 057 */ 058 public ClosureChain(Closure function1, Closure function2) { 059 closures.add(function1); 060 closures.add(function2); 061 } 062 063 /** 064 * Creates a chain composed of the ordered array of functions. 065 * 066 * @param functions the aggregated functions 067 */ 068 public ClosureChain(Closure[] functions) { 069 this.closures.addAll(Arrays.asList(functions)); 070 } 071 072 /** 073 * Add the specified function to the set of functions aggregated by this 074 * function chain. 075 * 076 * @param function the function to add 077 * @return A reference to this, to support easy chaining. 078 */ 079 public ClosureChain add(Closure function) { 080 this.closures.add(function); 081 return this; 082 } 083 084 /** 085 * Return an iterator over the aggregated predicates. 086 * 087 * @return An iterator 088 */ 089 public Iterator iterator() { 090 return closures.iterator(); 091 } 092 093 /** 094 * {@inheritDoc} 095 */ 096 public Object call(Object argument) { 097 Object result = argument; 098 Iterator it = iterator(); 099 while (it.hasNext()) { 100 Closure f = (Closure) it.next(); 101 result = f.call(result); 102 } 103 return result; 104 } 105 106 /** 107 * {@inheritDoc} 108 */ 109 public String toString() { 110 return new ToStringCreator(this).append("closureChain", closures).toString(); 111 } 112 }