The problem
Let's say we want to check the correct mimetype and file extension of the file being uploaded. In a typical Java way I would write something like this:
boolean isRightType = "image/jpeg".equals(contentType)
|| "image/png".equals(contentType)
|| "image/x-png".equals(contentType);
boolean isRightFileExt = filename.endsWith(".png")
|| filename.endsWith(".jpg")
|| filename.endsWith(".jpeg");
Groovy solution
The Groovy way is much simpler and more elegant.
private static CONTENT_TYPES = ["image/jpeg", "image/png", "image/x-png"]
private static FILE_EXTENTIONS = [".png", ".jpg", ".jpeg"]
...
boolean isRightType = CONTENT_TYPES.any { it.equals(contentType) }
boolean isRightFileExt = FILE_EXTENTIONS.any { filename.endsWith(it) }
This was just a small example. What I really find useful are some of the following constructs that make my programming life really pleasant
Groovy Iteration
each
Simple collection iteration
def fibList = [1, 1, 2, 3, 5, 8, 13]
fibList.each { println it } // prints all of the numbers in the list
any
If you need to find out if any element of the collection meets the condition.
def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.any { it == 3 }
assert fibList.any { it - 2 > 10 }
This is pretty much equivalent to a Java construct
boolean any(Listlist, Condition cond)
for (E e : list) {
if (cond.meets(e)) {
return true;
}
}
return false;
}
every
If you need to find out if any element of the collection meets the condition.
def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.every { it > 0 }
This is pretty much equivalent to a Java construct
boolean every(Listlist, Condition cond)
for (E e : list) {
if (!cond.meets(e)) {
return false;
}
}
return true;
}
collect
If you need to create a new collection that contains each element of the original collection transformed in some way.
def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.collect { it - 1 } == [0, 0, 1, 2, 4, 7, 12]
This is pretty much equivalent to a Java construct
Listevery(List list, Command command)
Listresult = new ArrayList (list.size());
for (E e : list) {
result.add(command(e));
}
return result;
}
findAll
If you need to create a new collection that contains all elements that meet the condition.
def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.findAll { it > 1 && it < 5 } == [2, 3]
This is pretty much equivalent to a Java construct
ListfindAll(List list, Condition cond)
Listresult = new ArrayList (list.size());
for (E e : list) {
if (!cond.meets(e)) {
result.add(e);
}
}
return result;
}
find
If you need to find first element that matches the condition.
def fibList = [1, 1, 2, 3, 5, 8, 13]
assert fibList.find { it > 1 } == 2
This is pretty much equivalent to a Java construct
E findAll(Listlist, Condition cond)
for (E e : list) {
if (!cond.meets(e)) {
return e;
}
}
return null;
}
References
- Groovy Makes Iteration Easy by Ted Naleid
3 comments:
Wouldn't the first example you gave allow for a file to be uploaded as a JPG but with a PNG MIME type? I'd think you'd want to do a map of the mime type and extensions, then check both key/value data against the uploaded file info.
Michael, you are right. But this is an example of how to do an iteration in Groovy, not a perfect solution to file uploads.
Great write-up!
However, if you're stuck in the Java land, you can still use Commons Collections to achieve this, albeit a bit verbose:
* CollectionUtils.forAllDo = Groovy's each
* CollectionUtils.exists = Groovy's any
* CollectionUtils.countMatches can be used to achieve Groovy's every
* CollectionUtils.collect = Groovy's collect
* CollectionUtils.select = Groovy's findAll
* CollectionUtils.find = Groovy's find
Common Collections also provides many commonly used predicates to reduce your pain to write an anonymous class...
You may be interested in Google Collections as well, which has generics support.
But of course, the Java versions are always clumsy to use. I also prefer Groovy's syntax and its use of verbs, which are pretty much aligned with other languages...
Post a Comment