Google Guava's Predicates
Join the DZone community and get the full member experience.
Join For FreeSo the other day I was working away on some rather tricky rules for validating an incoming identifier code. Like
999392304II+TJAJEIAJTI901119
or
EPFOOMNNVLLALOWEIITOE
Now, the system where this code is going is rather picky about what
these codes should look like. (For the sake of this blog-post, I'll
invent some business rules here on the fly, in reality they are a bit
different, but the nature of them are the same):
- A code cannot be null, or an empty string (of course)
- If there are only letters (A-Z) in the code, it must be longer than 10 characters, but fewer than 20
- On the other hand, if there are letters mixed with numbers, it must be exactly 10 or 15 characters
- Numbers only are not allowed
- No other symbols are allowed, but + signs are allowed, if the code starts with 999. In this case, the max length is 10.
I've created a little project on Github that demonstrates the above rules. There are two branches:
Both branches pass the same test suite. I won't swear on the correctness of the implementation, as it's currently 01:59 in the night, and the tests aren't really extensive.
Here's a quick look of what I ended up with using if's and else's:
public static boolean isCodeAllowed(String code) { return isNotNullOrEmpty(code) && onlyLettersCorrectLength(code) && lettersAndNumbersCorrectLength(code) && numbersOnlyNotAllowed(code) && plusSignOnlyParticularity(code); }
And here's using predicates:
(Source on Github)
public static boolean isCodeAllowed(String code) { Predicate<String> predicate = and( not(NULL_OR_EMPTY), ONLY_LETTERS_CORRECT_LENGTH, LETTERS_AND_NUMBERS_CORRECT_LENGTH, not(matching(NUMBERS_ONLY)), PLUS_SIGN_PARTICULARITY); return predicate.apply(code); }
I'm not saying that the predicates way is easier to read or write, but there is something functional and declarative about it that feels kind of.. powerful. A nice thing about those predicates is that they can easily be combined with eachother, and re-used in other places, like in filtering collections using other Guava utils.
Note that the full predicate style solution is much larger, but much to blame are those base-predicates I'm defining for saying matching, shorterThan, longerThan and exactLength.
If we were dealing with a language that properly supported functions (a predicate is a function that evalutes to true/false), it would probably look a lot nicer. Perhaps with Java 8, I can slim down the code quite a bit..
new FluentPredicate().not(NULL_OR_EMPTY).and(ONLY_LETTERS).build().
For other Guava resources, check out my collection here.
From http://blog.tfnico.com/2011/12/google-guavas-predicates.html
Opinions expressed by DZone contributors are their own.
Comments