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 }