Friday, April 1, 2011

Fun with 'fluent interface' and Java

Here is my story about 'fluent interface' and Java. In one project I have to compare in many places BigDecimals and other Comparable objects. So if I have:

BigDecimal requestedAmount = ...
BigDecimal paymentAmount = ...

In Java to compare BigDecimals I should use

if(requestedAmount.compareTo(paymentAmount) == 0) {

}

For me its not natural to compare numbers in such way and I decided to try to write small technical DSL, and here how looks my code now:

import static com.webbfontaine.twm.accounting.epaylog.utils.CompareDSL.*;

if (eq(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}

if (ne(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}

if (gt(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}
.... and etc.

and here is API/DSL code:

public class CompareDSL {

    public static <T extends Comparable<T>> PairToCompare<T> valueOf(T value) {
        return new PairToCompare<T>(value);
    }

    public static <T extends Comparable<T>> boolean eq(PairToCompare<T> pairToCompare) {
        return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) == 0;
    }

    public static <T extends Comparable<T>> boolean ne(PairToCompare<T> pairToCompare) {
        return !eq(pairToCompare);
    }

    public static <T extends Comparable<T>> boolean gt(PairToCompare<T> pairToCompare) {
        return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) > 0;
    }

    public static <T extends Comparable<T>> boolean ge(PairToCompare<T> pairToCompare) {
        return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) >= 0;
    }

    public static <T extends Comparable<T>> boolean lt(PairToCompare<T> pairToCompare) {
        return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) < 0;
    }

    public static <T extends Comparable<T>> boolean le(PairToCompare<T> pairToCompare) {
        return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) <= 0;
    }

    public static class PairToCompare<T extends Comparable<T>> {

        private T firstValue;
        private T secondValue;

        public PairToCompare(T firstValue) {
            this.firstValue = firstValue;
        }

        public PairToCompare<T> comparingWith(T value) {
            this.secondValue = value;
            return this;
        }

    }
}

API of course not the best one, but for me it works fine and it was fun to write it :-)