Thanks for testing guys. Now I'll optimize the internals a bit (and hopefully not break things) and rewrite some jAlbum External Tools and other internal jAlbum logic to use this API instead. There is really no downside to using this API compared to recursive code. It doesn't gather the whole list of all album objects in RAM. Instead, it walks the tree iteratively.
Most developers will probably appreciate the straight forward syntax. Here's a JavaScript example that prints all album object names:
for each(ao in rootFolder.getDescendants()) {
print(ao);
}
Here is the same code in Java/BeanShell:
for (ao : rootFolder.getDescendants()) {
System.out.println(ao);
}
You can also use the new cool Stream API of Java 8 to efficiently filter and perform various tasks on album objects using callback functions (aka "lambdas"). Here's a sample that prints the camera dates on all images (expensive operation as it needs to open each file):
var Category = Java.type("se.datadosen.jalbum.Category");
rootFolder.getDescendants().stream()
.filter(function(ao) { return ao.getCategory() == Category.image } )
.forEach(
function(ao) {
print(ao.getVars().get("originalDate"))
}
);
Now, this may not look as straightforward as the plain for each loop, but now study what happens when you swap stream() to parallelStream():
var Category = Java.type("se.datadosen.jalbum.Category");
rootFolder.getDescendants().parallelStream()
.filter(function(ao) { return ao.getCategory() == Category.image } )
.forEach(
function(ao) {
print(ao.getVars().get("originalDate"))
}
);
The Stream API now splits the work of filtering images and gathering camera dates to multiple CPU cores / threads. This can have a significant impact on performance. If your source images resides on a network drive, you may expect performance gains of several hundred percent without having to manually dabble with thread coding.
In plain compiled Java, the equivalent code looks like this. Notice the short syntax:
rootFolder.getDescendants().parallelStream()
.filter(ao -> ao.getCategory() == Category.image)
.forEach(ao -> System.out.println(ao.getVars().get("originalDate")));
If you want to use these callback methods in BeanShell you have to resort to using anonymous inner classes as BeanShell doesn't support the neat lambda syntax of Java 8:
import java.util.function.*;
rootFolder.getDescendants().parallelStream()
.filter(new Predicate() { boolean test(AlbumObject ao) { ao.getCategory() == Category.image; } } )
.forEach(new Consumer() {
void accept(AlbumObject ao) {
System.out.println(ao.getVars().get("originalDate"));
}
});