Coverage Report - jaggregate.UnaryPredicate
 
Classes in this File Line Coverage Branch Coverage Complexity
UnaryPredicate
100%
8/8
N/A
0
UnaryPredicate$CompositeUnaryPredicate
100%
5/5
N/A
0
UnaryPredicate$ConjunctiveUnaryPredicate
100%
4/4
100%
1/1
0
UnaryPredicate$DisjunctiveUnaryPredicate
100%
4/4
100%
1/1
0
UnaryPredicate$ExclusivelyDisjunctiveUnaryPredicate
100%
4/4
N/A
0
UnaryPredicate$InvertedUnaryPredicate
100%
6/6
100%
1/1
0
 
 1  
 /*
 2  
  Copyright 2004-2008 Paul R. Holser, Jr.  All rights reserved.
 3  
  Licensed under the Academic Free License version 3.0
 4  
  */
 5  
 
 6  
 package jaggregate;
 7  
 
 8  
 import static java.lang.String.*;
 9  
 
 10  
 import static jaggregate.internal.ArgumentChecks.*;
 11  
 
 12  
 /**
 13  
  * A predicate that accepts one argument.
 14  
  *
 15  
  * @param <A> a constraint on the allowable types for the predicate's argument.
 16  
  * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
 17  
  * @version $Id: UnaryPredicate.java,v 1.6 2008/10/03 19:01:23 pholser Exp $
 18  
  */
 19  
 public abstract class UnaryPredicate<A> implements UnaryCondition<A> {
 20  
     /**
 21  
      * Creates a new predicate.
 22  
      */
 23  626
     protected UnaryPredicate() {
 24  
         // For subclasses.
 25  626
     }
 26  
 
 27  
     /**
 28  
      * Answers a predicate that represents the logical <dfn>inverse</dfn> of this
 29  
      * predicate; wherever this predicate's {@link #matches(Object) matches} method
 30  
      * would answer {@code true}, the inverse answers {@code false}; and vice versa.
 31  
      *
 32  
      * @return the inverse of this predicate
 33  
      */
 34  
     public final UnaryPredicate<A> not() {
 35  6
         return new InvertedUnaryPredicate<A>( this );
 36  
     }
 37  
 
 38  
     /**
 39  
      * Answers a predicate that represents the logical <dfn>inverse</dfn> of the given
 40  
      * predicate; wherever the given predicate's {@link #matches(Object) matches} method
 41  
      * would answer {@code true}, the inverse answers {@code false}; and vice versa.
 42  
      *
 43  
      * @param <T> constraint on the types accepted by the predicate
 44  
      * @param predicate the predicate to invert
 45  
      * @return the inverse of {@code predicate}
 46  
      * @throws NullPointerException if {@code predicate} is {@code null}
 47  
      */
 48  
     public static <T> UnaryPredicate<T> not( UnaryPredicate<T> predicate ) {
 49  2
         return new InvertedUnaryPredicate<T>( predicate );
 50  
     }
 51  
 
 52  
     /**
 53  
      * Answers a predicate that represents the logical <dfn>disjunction</dfn> of this
 54  
      * predicate and another predicate.  The disjunction's {@link #matches(Object)
 55  
      * matches} method answers {@code true} if either this predicate or the other
 56  
      * predicate would answer {@code true}.
 57  
      * <p/>
 58  
      * When the disjunction is evaluated, this predicate is always evaluated first.
 59  
      * The other predicate may not be evaluated; so do not depend on its evaluation for
 60  
      * side effects.
 61  
      *
 62  
      * @param other the "right-hand" operand of the disjunction
 63  
      * @return the logical disjunction of this predicate and {@code other}
 64  
      * @throws NullPointerException if {@code other} is {@code null}
 65  
      */
 66  
     public final UnaryPredicate<A> or( UnaryPredicate<? super A> other ) {
 67  4
         return new DisjunctiveUnaryPredicate<A>( this, other );
 68  
     }
 69  
 
 70  
     /**
 71  
      * Answers a predicate that represents the logical <dfn>conjunction</dfn> of this
 72  
      * predicate and another predicate.  The conjunction's {@link #matches(Object)
 73  
      * matches} method answers {@code true} if both this predicate and the other
 74  
      * predicate would answer {@code true}.
 75  
      * <p/>
 76  
      * When the conjunction is evaluated, this predicate is always evaluated first.
 77  
      * The other predicate may not be evaluated; so do not depend on its evaluation for
 78  
      * side effects.
 79  
      *
 80  
      * @param other the "right-hand" operand of the conjunction
 81  
      * @return the logical conjunction of this predicate and {@code other}
 82  
      * @throws NullPointerException if {@code other} is {@code null}
 83  
      */
 84  
     public final UnaryPredicate<A> and( UnaryPredicate<? super A> other ) {
 85  4
         return new ConjunctiveUnaryPredicate<A>( this, other );
 86  
     }
 87  
 
 88  
     /**
 89  
      * Answers a predicate that represents the logical <dfn>exclusive disjunction</dfn>
 90  
      * of this predicate and another predicate.  The disjunction's
 91  
      * {@link #matches(Object) matches} method answers {@code true} if either this
 92  
      * predicate or the other predicate, but not both, would answer {@code true}.
 93  
      * <p/>
 94  
      * When the disjunction is evaluated, both this predicate and the other predicate
 95  
      * will be evaluated.
 96  
      *
 97  
      * @param other the "right-hand" operand of the disjunction
 98  
      * @return the logical exclusive disjunction of this predicate and {@code other}
 99  
      * @throws NullPointerException if {@code other} is {@code null}
 100  
      */
 101  
     public final UnaryPredicate<A> xor( UnaryPredicate<? super A> other ) {
 102  5
         return new ExclusivelyDisjunctiveUnaryPredicate<A>( this, other );
 103  
     }
 104  
 
 105  
     /**
 106  
      * Gives a string that describes the kinds of objects which match this predicate.
 107  
      * <p/>
 108  
      * If not overridden, this method answers the same as {@link #toString()}.
 109  
      *
 110  
      * @return a description of objects that meet this predicate's criteria
 111  
      */
 112  
     public String describe() {
 113  15
         return toString();
 114  
     }
 115  
 
 116  
     private static class InvertedUnaryPredicate<A> extends UnaryPredicate<A> {
 117  
         private final UnaryPredicate<A> wrapped;
 118  
 
 119  8
         InvertedUnaryPredicate( UnaryPredicate<A> wrapped ) {
 120  8
             ensureNotNull( wrapped, DISCRIMINATOR );
 121  7
             this.wrapped = wrapped;
 122  7
         }
 123  
 
 124  
         public boolean matches( A target ) {
 125  8
             return !wrapped.matches( target );
 126  
         }
 127  
 
 128  
         @Override
 129  
         public String describe() {
 130  3
             return format( "something other than <%1$s>", wrapped.describe() );
 131  
         }
 132  
     }
 133  
 
 134  
     private abstract static class CompositeUnaryPredicate<A> extends UnaryPredicate<A> {
 135  
         protected final UnaryPredicate<A> first;
 136  
         protected final UnaryPredicate<? super A> second;
 137  
 
 138  
         protected CompositeUnaryPredicate( UnaryPredicate<A> first,
 139  13
             UnaryPredicate<? super A> second ) {
 140  
 
 141  13
             ensureNotNull( second, "'right-hand' operand" );
 142  
 
 143  10
             this.first = first;
 144  10
             this.second = second;
 145  10
         }
 146  
     }
 147  
 
 148  
     private static class DisjunctiveUnaryPredicate<A>
 149  
         extends CompositeUnaryPredicate<A> {
 150  
 
 151  
         DisjunctiveUnaryPredicate( UnaryPredicate<A> first,
 152  
             UnaryPredicate<? super A> second ) {
 153  
 
 154  4
             super( first, second );
 155  3
         }
 156  
 
 157  
         public boolean matches( A target ) {
 158  6
             return first.matches( target ) || second.matches( target );
 159  
         }
 160  
 
 161  
         @Override
 162  
         public String describe() {
 163  1
             return format( "<%1$s> or <%2$s>", first.describe(), second.describe() );
 164  
         }
 165  
     }
 166  
 
 167  
     private static class ConjunctiveUnaryPredicate<A>
 168  
         extends CompositeUnaryPredicate<A> {
 169  
 
 170  
         ConjunctiveUnaryPredicate( UnaryPredicate<A> first,
 171  
             UnaryPredicate<? super A> second ) {
 172  
 
 173  4
             super( first, second );
 174  3
         }
 175  
 
 176  
         public boolean matches( A target ) {
 177  7
             return first.matches( target ) && second.matches( target );
 178  
         }
 179  
 
 180  
         @Override
 181  
         public String describe() {
 182  1
             return format( "<%1$s> and <%2$s>", first.describe(), second.describe() );
 183  
         }
 184  
     }
 185  
 
 186  
     private static class ExclusivelyDisjunctiveUnaryPredicate<A>
 187  
         extends CompositeUnaryPredicate<A> {
 188  
 
 189  
         ExclusivelyDisjunctiveUnaryPredicate( UnaryPredicate<A> first,
 190  
             UnaryPredicate<? super A> second ) {
 191  
 
 192  5
             super( first, second );
 193  4
         }
 194  
 
 195  
         public boolean matches( A target ) {
 196  8
             return first.matches( target ) ^ second.matches( target );
 197  
         }
 198  
 
 199  
         @Override
 200  
         public String describe() {
 201  1
             return format( "either <%1$s> or <%2$s> but not both", first.describe(),
 202  
                 second.describe() );
 203  
         }
 204  
     }
 205  
 }