stream.process(new CopyActionProcessingStreamAction() {
public void processFile(FileCopyDetailsInternal details) {
if (details.isDirectory()) {
RelativePath path = details.getRelativePath();
if (!visitedDirs.contains(path)) {
pendingDirs.put(path, details);
}
} else {
maybeVisit(details.getRelativePath().getParent(), details.isIncludeEmptyDirs(), action);
action.processFile(details);
}
}
});
for (RelativePath path : new LinkedHashSet<RelativePath>(pendingDirs.keySet())) {
List<FileCopyDetailsInternal> detailsList = new ArrayList<FileCopyDetailsInternal>(pendingDirs.get(path));
for (FileCopyDetailsInternal details : detailsList) {
if (details.isIncludeEmptyDirs()) {
maybeVisit(path, details.isIncludeEmptyDirs(), action);
}
}
}
visitedDirs.clear();
pendingDirs.clear();
}
private void maybeVisit(RelativePath path, boolean includeEmptyDirs, CopyActionProcessingStreamAction delegateAction) {
if (path == null || path.getParent() == null || !visitedDirs.add(path)) {
return;
}
maybeVisit(path.getParent(), includeEmptyDirs, delegateAction);
List<FileCopyDetailsInternal> detailsForPath = pendingDirs.removeAll(path);
FileCopyDetailsInternal dir;
if (detailsForPath.isEmpty()) {
// TODO - this is pretty nasty, look at avoiding using a time bomb stub here