001    package fj.test;
002    
003    import fj.F;
004    import fj.P1;
005    import fj.data.List;
006    import fj.data.Option;
007    import static fj.data.Option.none;
008    import static fj.data.Option.some;
009    
010    /**
011     * The result of evaluating a property.
012     *
013     * @version %build.number%<br>
014     *          <ul>
015     *          <li>$LastChangedRevision: 126 $</li>
016     *          <li>$LastChangedDate: 2009-05-05 13:39:54 +1000 (Tue, 05 May 2009) $</li>
017     *          <li>$LastChangedBy: tonymorris $</li>
018     *          </ul>
019     */
020    public final class Result {
021      private final Option<List<Arg<?>>> args;
022      private final R r;
023      private final Option<Throwable> t;
024    
025      private enum R {
026        Unfalsified, Falsified, Proven, Exception, NoResult
027      }
028    
029      private Result(final Option<List<Arg<?>>> args, final R r, final Option<Throwable> t) {
030        this.args = args;
031        this.r = r;
032        this.t = t;
033      }
034    
035      /**
036       * Returns the potential arguments associated with this result. This will only have a value, if
037       * and only if {@link #noResult(Option) !noResult()} holds.
038       *
039       * @return The potential arguments associated with this result.
040       */
041      public Option<List<Arg<?>>> args() {
042        return args;
043      }
044    
045      /**
046       * Returns the potential exception associated with this result. This will only have a value if and
047       * only if this result is an exception result.
048       *
049       * @return The potential exception associated with this result.
050       */
051      public Option<Throwable> exception() {
052        return t;
053      }
054    
055      /**
056       * Returns <code>true</code> if this result is unfalsified; otherwise, <code>false</code>.
057       *
058       * @return <code>true</code> if this result is unfalsified; otherwise, <code>false</code>.
059       */
060      public boolean isUnfalsified() {
061        return r == R.Unfalsified;
062      }
063    
064      /**
065       * Returns <code>true</code> if this result is falsified; otherwise, <code>false</code>.
066       *
067       * @return <code>true</code> if this result is falsified; otherwise, <code>false</code>.
068       */
069      public boolean isFalsified() {
070        return r == R.Falsified;
071      }
072    
073      /**
074       * Returns <code>true</code> if this result is proven; otherwise, <code>false</code>.
075       *
076       * @return <code>true</code> if this result is proven; otherwise, <code>false</code>.
077       */
078      public boolean isProven() {
079        return r == R.Proven;
080      }
081    
082      /**
083       * Returns <code>true</code> if this result is an exception; otherwise, <code>false</code>.
084       *
085       * @return <code>true</code> if this result is an exception; otherwise, <code>false</code>.
086       */
087      public boolean isException() {
088        return r == R.Exception;
089      }
090    
091      /**
092       * Returns <code>true</code> if this result is no result; otherwise, <code>false</code>.
093       *
094       * @return <code>true</code> if this result is no result; otherwise, <code>false</code>.
095       */
096      public boolean isNoResult() {
097        return r == R.NoResult;
098      }
099    
100      /**
101       * Returns <code>true</code> if this result is falsified or an exception; otherwise,
102       * <code>false</code>.
103       *
104       * @return <code>true</code> if this result is falsified or an exception; otherwise,
105       * <code>false</code>.
106       */
107      public boolean failed() {
108        return isFalsified() || isException();
109      }
110    
111      /**
112       * Returns <code>true</code> if this result is unfalsified or proven; otherwise,
113       * <code>false</code>.
114       *
115       * @return <code>true</code> if this result is unfalsified or proven; otherwise,
116       * <code>false</code>.
117       */
118      public boolean passed() {
119        return isUnfalsified() || isProven();
120      }
121    
122      /**
123       * If this result is proven, alter it to be unfalsified with the same arguments; otherwise, return
124       * <code>this</code>.
125       *
126       * @return If this result is proven, alter it to be unfalsified with the same arguments;
127       * otherwise, return <code>this</code>.
128       */
129      public Result provenAsUnfalsified() {
130        if(isProven())
131          return unfalsified(args.some());
132        else
133          return this;
134      }
135    
136      /**
137       * Adds an argument to this result.
138       *
139       * @param a The argument to add.
140       * @return A result with the new argument.
141       */
142      public Result addArg(final Arg<?> a) {
143        final F<Arg<?>, F<List<Arg<?>>, List<Arg<?>>>> cons = List.cons();
144        return new Result(args.map(cons.f(a)), r, t);
145      }
146    
147      /**
148       * Returns a potential result for this result. This will have a value if this result is
149       * {@link #noResult(Option) !noResult()}.
150       *
151       * @return A potential result for this result.
152       */
153      public Option<Result> toOption() {
154        if(isNoResult())
155          return none();
156        else
157          return some(this);
158      }
159    
160      /**
161       * Returns a result from the given potential result.
162       *
163       * @param r The potential result.
164       * @return The result that may be {@link #noResult() noResult()}.
165       */
166      public static Result noResult(final Option<Result> r) {
167        return r.orSome(new P1<Result>() {
168          public Result _1() {
169            return noResult();
170          }
171        });
172      }
173    
174      /**
175       * Returns a result representing no result.
176       *
177       * @return A result representing no result.
178       */
179      public static Result noResult() {
180        return new Result(Option.<List<Arg<?>>>none(), R.NoResult, Option.<Throwable>none());
181      }
182    
183      /**
184       * Returns an unfalsified result.
185       *
186       * @param args The arguments used during the failure of falsification.
187       * @return An unfalsified result.
188       */
189      public static Result unfalsified(final List<Arg<?>> args) {
190        return new Result(some(args), R.Unfalsified, Option.<Throwable>none());
191      }
192    
193      /**
194       * Returns a falsified result.
195       *
196       * @param args The arguments used during falsification.
197       * @return A falsified result.
198       */
199      public static Result falsified(final List<Arg<?>> args) {
200        return new Result(some(args), R.Falsified, Option.<Throwable>none());
201      }
202    
203      /**
204       * Returns a proven result.
205       *
206       * @param args The arguments used during proof.
207       * @return A proven result.
208       */
209      public static Result proven(final List<Arg<?>> args) {
210        return new Result(some(args), R.Proven, Option.<Throwable>none());
211      }
212    
213      /**
214       * Returns an exception result.
215       *
216       * @param args The arguments used when the exception occurred.
217       * @param t The exception that occurred.
218       * @return A exception result.
219       */
220      public static Result exception(final List<Arg<?>> args, final Throwable t) {
221        return new Result(some(args), R.Exception, some(t));
222      }
223    }