@Override
    public List<TransferItem> normalize(final List<TransferItem> roots) {
        final List<TransferItem> normalized = new ArrayList<>();
        for(TransferItem upload : roots) {
            boolean duplicate = false;
            for(Iterator<TransferItem> iter = normalized.iterator(); iter.hasNext(); ) {
                TransferItem n = iter.next();
                if(upload.local.isChild(n.local)) {
                    // The selected file is a child of a directory already included
                    duplicate = true;
                    break;
                }
                if(n.local.isChild(upload.local)) {
                    iter.remove();
                }
                if(upload.remote.equals(n.remote)) {
                    // The selected file has the same name; if uploaded as a root element
                    // it would overwrite the earlier
                    final Path parent = upload.remote.getParent();
                    final String filename = upload.remote.getName();
                    String proposal;
                    int no = 0;
                    int index = filename.lastIndexOf('.');
                    Path remote;
                    do {
                        if(index != -1 && index != 0) {
                            proposal = String.format("%s-%d%s", filename.substring(0, index), ++no, filename.substring(index));
                        }
                        else {
                            proposal = String.format("%s-%d", filename, ++no);
                        }
                        remote = new Path(parent, proposal, upload.remote.getType());
                    }
                    while(false);//(upload.exists());
                    if(log.isInfoEnabled()) {
                        log.info(String.format("Changed name from %s to %s", filename, remote.getName()));
                    }
                    upload.remote = remote;
                }
            }
            // 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(upload.remote, upload.local));
            }
        }
        return normalized;
    }
@Test
    public void testNormalize() {
        UploadRootPathsNormalizer n = new UploadRootPathsNormalizer();
        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") {
            @Override
            public boolean isDirectory() {
                return true;
            }

            @Override
            public boolean isFile() {
                return false;
            }
        }));
        list.add(new TransferItem(new Path("/a", EnumSet.of(Path.Type.file)), new NullLocal(System.getProperty("java.io.tmpdir"), "a" + File.separator + "b")));
        final List<TransferItem> normalized = n.normalize(list);
        assertEquals(1, normalized.size());
        final TransferItem i = normalized.iterator().next();
        assertEquals(new Path("/a", EnumSet.of(Path.Type.directory)), i.remote);
    }