@Override
    public List<TransferItem> normalize(final List<TransferItem> roots) {
        final List<TransferItem> normalized = new ArrayList<>();
        for(final TransferItem download : roots) {
            boolean duplicate = false;
            for(Iterator<TransferItem> iter = normalized.iterator(); iter.hasNext(); ) {
                TransferItem n = iter.next();
                if(download.remote.isChild(n.remote)) {
                    // The selected file is a child of a directory already included
                    duplicate = true;
                    break;
                }
                if(n.remote.isChild(download.remote)) {
                    iter.remove();
                }
                if(download.local.equals(n.local)) {
                    // The selected file has the same name; if downloaded as a root element
                    // it would overwrite the earlier
                    final String parent = download.local.getParent().getAbsolute();
                    final String filename = download.remote.getName();
                    String proposal;
                    int no = 0;
                    Local local;
                    do {
                        proposal = String.format("%s-%d", FilenameUtils.getBaseName(filename), ++no);
                        if(StringUtils.isNotBlank(Path.getExtension(filename))) {
                            proposal += String.format(".%s", Path.getExtension(filename));
                        }
                        local = LocalFactory.get(parent, proposal);
                    }
                    while(local.exists());
                    if(log.isInfoEnabled()) {
                        log.info(String.format("Changed local name from %s to %s", filename, local.getName()));
                    }
                    download.local = local;
                }
            }
            // Prunes the list of selected files. Files which are a child of an already included directory
            // are removed from the returned list.
            if(!duplicate) {
                normalized.add(new TransferItem(download.remote, download.local));
            }
        }
        return normalized;
    }
@Test
    public void testNormalize() {
        DownloadRootPathsNormalizer n = new DownloadRootPathsNormalizer();
        final List<TransferItem> list = new ArrayList<>();
        list.add(new TransferItem(new Path("/a", EnumSet.of(Path.Type.directory)), new NullLocal(System.getProperty("java.io.tmpdir"), "a")));
        list.add(new TransferItem(new Path("/a/b", EnumSet.of(Path.Type.file)), new NullLocal(System.getProperty("java.io.tmpdir"), "a/b")));
        final List<TransferItem> normalized = n.normalize(list);
        assertEquals(1, normalized.size());
        assertEquals(new Path("/a", EnumSet.of(Path.Type.directory)), normalized.iterator().next().remote);
    }