001    package org.nakedobjects.applib.spec;
002    
003    import org.nakedobjects.applib.util.ReasonBuffer;
004    
005    
006    /**
007     * Adapter to make it easy to perform boolean algebra on {@link Specification}s.
008     * 
009     * <p>
010     * Subclasses represent the intersection of multiple {@link Specification}s.  An 
011     * implementation should instantiate the {@link Specification}s to be satisfied 
012     * in its constructor.
013     * 
014     * <p>
015     * For example:
016     * <pre>
017     * public class MilkAndSugarSpec extends SpecificationAnd {
018     *     public MilkAndSugarSpec() {
019     *         super(
020     *             new MustBeMilkySpec(), 
021     *             new TwoLumpsOfSugarSpec()
022     *         );
023     *     }
024     * }
025     * </pre>
026     * 
027     * @see SpecificationOr
028     * @see SpecificationNot
029     */
030    public abstract class SpecificationAnd implements Specification {
031    
032        private final Specification[] specifications;
033    
034        public SpecificationAnd(Specification... specifications) {
035            this.specifications = specifications;
036        }
037     
038        public String satisfies(Object obj) {
039            ReasonBuffer buf = new ReasonBuffer();
040            for(Specification specification: specifications) {
041                String reasonNotSatisfiedIfAny = specification.satisfies(obj);
042                buf.append(reasonNotSatisfiedIfAny);
043            }
044            return buf.getReason(); // may be null if all were satisfied.
045        }
046    
047    
048    }