Commit 00e5a331 authored by Matija Obreza's avatar Matija Obreza
Browse files

#listPaths returns all paths in repository, including specified prefix

parent 695d75c5
......@@ -16,6 +16,7 @@
package org.genesys.filerepository.persistence;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
......@@ -49,7 +50,16 @@ public interface RepositoryFilePersistence extends JpaRepository<RepositoryFile,
List<RepositoryFile> findByPath(String repositoryPath);
/**
* List distinct paths.
* List repository files at specified paths
*
* @param path
* @return
*/
@Query("select rf from RepositoryFile rf where rf.path in ?1")
List<RepositoryFile> findByPath(Collection<String> paths);
/**
* List distinct paths starting with the prefix
*
* @param prefix the prefix
* @param pageable the pagination
......@@ -59,7 +69,7 @@ public interface RepositoryFilePersistence extends JpaRepository<RepositoryFile,
List<String> listDistinctPaths(String prefix, Pageable pageable);
/**
* List all distinct paths (FTP)
* List distinct paths starting with the prefix
*
* @param prefix the prefix
* @return the list of paths
......
......@@ -188,21 +188,21 @@ public interface RepositoryService {
List<RepositoryImage> listImages(String path);
/**
* List distinct paths within the prefix.
* List all paths within the prefix, including prefix itself if such paths exist
*
* @param prefix The prefix
* @param pageRequest Pagination
* @return Distinct list of paths in repository starting with prefix
* @throws InvalidRepositoryPathException
* @throws InvalidRepositoryPathException
*/
List<String> listPaths(String prefix, Pageable pageRequest) throws InvalidRepositoryPathException;
/**
* List all paths within the prefix.
* List all paths within the prefix, including prefix itself if such paths exist
*
* @param prefix
* @return
* @throws InvalidRepositoryPathException
* @throws InvalidRepositoryPathException
*/
List<String> listPaths(String prefix) throws InvalidRepositoryPathException;
......@@ -231,8 +231,17 @@ public interface RepositoryService {
*
* @param path
* @return true if at least one entry exists at specified path
* @throws InvalidRepositoryPathException
* @throws InvalidRepositoryPathException
*/
boolean hasPath(Path path) throws InvalidRepositoryPathException;
/**
* Move all repository items to a new path
*
* @param currentPath
* @param newPath
* @throws InvalidRepositoryPathException
*/
void renamePath(String currentPath, String newPath) throws InvalidRepositoryPathException;
}
......@@ -26,6 +26,7 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.imageio.ImageIO;
......@@ -534,9 +535,14 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@Override
public List<String> listPaths(final String prefix, final Pageable pageable) throws InvalidRepositoryPathException {
PathValidator.checkValidPath(prefix);
// note the trailing slash
final String prefixSlash = "/".equals(prefix) ? prefix : prefix + "/";
LOG.debug("Listing paths under prefix={} page={}", prefix, pageable);
final List<String> paths = repositoryFilePersistence.listDistinctPaths(prefix, pageable);
paths.remove(prefix);
List<String> paths = repositoryFilePersistence.listDistinctPaths(prefix, pageable).stream().filter(path -> {
return path.startsWith(prefixSlash) || path.equals(prefix);
}).collect(Collectors.toList());
LOG.trace("Paths under prefix={}: {}", prefix, paths);
return paths;
}
......@@ -544,11 +550,33 @@ public class RepositoryServiceImpl implements RepositoryService, InitializingBea
@Override
public List<String> listPaths(String prefix) throws InvalidRepositoryPathException {
PathValidator.checkValidPath(prefix);
// note the trailing slash
final String prefixSlash = "/".equals(prefix) ? prefix : prefix + "/";
LOG.debug("Listing paths under prefix={}", prefix);
final List<String> paths = repositoryFilePersistence.listDistinctPaths(prefix);
paths.remove(prefix);
final List<String> paths = repositoryFilePersistence.listDistinctPaths(prefix).stream().filter(path -> {
return path.startsWith(prefixSlash) || path.equals(prefix);
}).collect(Collectors.toList());
LOG.trace("Paths under prefix={}: {}", prefix, paths);
return paths;
}
@Override
@Transactional
public void renamePath(String currentPath, String newPath) throws InvalidRepositoryPathException {
PathValidator.checkValidPath(currentPath);
PathValidator.checkValidPath(newPath);
Path cPath = Paths.get(currentPath);
Path nPath = Paths.get(newPath);
for (RepositoryFile repositoryFile : repositoryFilePersistence.findByPath(listPaths(currentPath))) {
Path rfPath = Paths.get(repositoryFile.getPath());
Path relative = cPath.relativize(rfPath);
LOG.debug("Base={} rfPath={} relative={} to={}", cPath, rfPath, relative, nPath.resolve(relative));
repositoryFile.setPath(nPath.resolve(relative).toAbsolutePath().toString());
repositoryFilePersistence.save(repositoryFile);
}
}
}
......@@ -98,16 +98,16 @@ public class FileRepositoryDirectoryTest {
// paths.stream().forEach(path -> {
// System.err.println("Distinct path=" + path);
// });
assertThat("Paths definitely exist", paths, hasSize(3));
assertThat("Paths not in correct order", paths, contains(PATH + "aa/dd", PATH + "aa/dd/ee", PATH + "aa/dd/ee/gg"));
assertThat("Paths definitely exist", paths, hasSize(4));
assertThat("Paths not in correct order", paths, contains(PATH + "aa", PATH + "aa/dd", PATH + "aa/dd/ee", PATH + "aa/dd/ee/gg"));
paths = fileRepoService.listPaths(PATH + "bb", new PageRequest(0, 10));
assertThat("Paths definitely exist", paths, notNullValue());
// paths.stream().forEach(path -> {
// System.err.println("Distinct path=" + path);
// });
assertThat("Paths definitely exist", paths, hasSize(3));
assertThat("Paths not in correct order", paths, contains(PATH + "bb/cc", PATH + "bb/cc/ee", PATH + "bb/cc/ee/ff"));
assertThat("Paths definitely exist", paths, hasSize(4));
assertThat("Paths not in correct order", paths, contains(PATH + "bb", PATH + "bb/cc", PATH + "bb/cc/ee", PATH + "bb/cc/ee/ff"));
for (final RepositoryFile repoFile : repoFiles) {
fileRepoService.removeFile(repoFile);
......@@ -117,4 +117,71 @@ public class FileRepositoryDirectoryTest {
assertThat("Paths should no longer exist", paths, hasSize(0));
}
@Test
public void testListPaths() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException, NoSuchRepositoryFileException {
final String contentType = "text/plain;charset=UTF-8";
final String extension = ".txt";
final String originalFilename = "folderfile" + extension;
final List<RepositoryFile> repoFiles = new ArrayList<RepositoryFile>(20);
repoFiles.add(fileRepoService.addFile(PATH + "aa", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aaa", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aaaa/bb", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aaaa/bbb", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aaaa/cc", 1 + originalFilename, contentType, SOME_BYTES, null));
assertThat(fileRepoService.listPaths(PATH + "aa"), hasSize(1));
assertThat(fileRepoService.listPaths(PATH + "aaa"), hasSize(1));
assertThat(fileRepoService.listPaths(PATH + "aaaa"), hasSize(3));
assertThat(fileRepoService.listPaths(PATH + "aaaa/bb"), hasSize(1));
for (final RepositoryFile repoFile : repoFiles) {
fileRepoService.removeFile(repoFile);
}
}
/**
* Test path listing.
*
* @throws InvalidRepositoryPathException the invalid repository path exception
* @throws InvalidRepositoryFileDataException the invalid repository file data exception
* @throws NoSuchRepositoryFileException the no such repository file exception
* @throws IOException Signals that an I/O exception has occurred.
*/
@Test
public void testRenamePath() throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, NoSuchRepositoryFileException, IOException {
final String contentType = "text/plain;charset=UTF-8";
final String extension = ".txt";
final String originalFilename = "folderfile" + extension;
final List<RepositoryFile> repoFiles = new ArrayList<RepositoryFile>(20);
repoFiles.add(fileRepoService.addFile(PATH + "aa", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa", 2 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa/dd", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa/dd", 2 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa/dd/ee", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa/dd/ee", 2 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa/dd/ee/gg", 1 + originalFilename, contentType, SOME_BYTES, null));
repoFiles.add(fileRepoService.addFile(PATH + "aa/dd/ee/gg", 2 + originalFilename, contentType, SOME_BYTES, null));
List<String> paths = fileRepoService.listPaths(PATH + "aa", new PageRequest(0, 10));
assertThat("Paths definitely exist", paths, notNullValue());
assertThat("Paths definitely exist", paths, hasSize(4));
assertThat("Paths not in correct order", paths, contains(PATH + "aa", PATH + "aa/dd", PATH + "aa/dd/ee", PATH + "aa/dd/ee/gg"));
fileRepoService.renamePath(PATH + "aa/dd/ee/gg", PATH + "aa/dd/ee/zz");
assertThat("Paths not renamed correctly", fileRepoService.listPaths(PATH + "aa/dd/ee"), contains(PATH + "aa/dd/ee", PATH + "aa/dd/ee/zz"));
fileRepoService.renamePath(PATH + "aa/dd", PATH + "aa/zz");
assertThat("Paths not renamed correctly", fileRepoService.listPaths(PATH + "aa/zz"), contains(PATH + "aa/zz", PATH + "aa/zz/ee", PATH + "aa/zz/ee/zz"));
for (String repositoryPath : fileRepoService.listPaths(PATH + "aa")) {
for (final RepositoryFile repoFile : fileRepoService.getFiles(repositoryPath)) {
fileRepoService.removeFile(repoFile);
}
}
paths = fileRepoService.listPaths(PATH, new PageRequest(0, 10));
assertThat("Paths should no longer exist", paths, hasSize(0));
}
}
......@@ -124,8 +124,13 @@ public class RepositoryFileSystemFactory implements FileSystemFactory, Initializ
@Override
public boolean move(FtpFile destination) {
LOG.info("Move directory={} to dest={}", this.getAbsolutePath(), destination.getAbsolutePath());
// TODO Auto-generated method stub
return false;
try {
repositoryService.renamePath(this.getAbsolutePath(), destination.getAbsolutePath());
return true;
} catch (InvalidRepositoryPathException e) {
LOG.error("Failed to rename directory", e);
return false;
}
}
@Override
......@@ -142,6 +147,31 @@ public class RepositoryFileSystemFactory implements FileSystemFactory, Initializ
ArrayList<FtpFile> all = new ArrayList<>();
final Path root = Paths.get(currentPath);
all.addAll(repositoryService.getFiles(currentPath).stream().peek(rf -> {
// System.err.println("repoFile " + rf.getPath() + " " + rf.getOriginalFilename());
}).map(rf -> file(rf)).collect(Collectors.toList()));
try {
all.addAll(repositoryService.listPaths(currentPath).stream()
// remove from temporaryDir if exists in the repository
.peek(path -> {
session.temporaryDirs.remove(path);
})
// filter out current path
.filter(path -> !currentPath.equals(path))
// get the first subfolder name within currentPath
.map(path -> {
Path foo = Paths.get(path.substring(currentPath.length()));
LOG.trace("Sub cp=" + currentPath + " p=" + path + " x=" + foo.getName(0));
return foo.getName(0).toString();
})
// remove duplicates and make directories
.distinct().map(path -> directory(path, session)).collect(Collectors.toList()));
} catch (InvalidRepositoryPathException e) {
LOG.warn("Error listing paths for {}: {}", currentPath, e.getMessage());
}
all.addAll(session.temporaryDirs.stream().filter(path -> path.startsWith(currentPath) && !path.equals(currentPath))
// we have full paths as string, filter the ones that are direct children
.map(path -> {
......@@ -156,20 +186,11 @@ public class RepositoryFileSystemFactory implements FileSystemFactory, Initializ
// map to RepositoryFtpDirectory
.map(path -> directory(path, session)).collect(Collectors.toList()));
all.addAll(repositoryService.getFiles(currentPath).stream().map(rf -> file(rf)).collect(Collectors.toList()));
try {
all.addAll(repositoryService.listPaths(currentPath).stream().map(path -> {
Path foo = Paths.get(path.substring(currentPath.length()));
LOG.trace("Sub cp=" + currentPath + " p=" + path + " x=" + foo.getName(0));
return foo.getName(0).toString();
}).distinct().map(path -> directory(path, session)).collect(Collectors.toList()));
} catch (InvalidRepositoryPathException e) {
LOG.warn("Error listing paths for {}: {}", currentPath, e.getMessage());
}
// Distinct sorted list of everything
return Collections.unmodifiableList(all.stream().distinct().sorted((a, b) -> {
return a.getName().compareTo(b.getName());
}).peek(path -> {
// System.err.println("listFiles " + path.getName());
}).collect(Collectors.toList()));
}
......
......@@ -272,7 +272,7 @@ public class FtpServerTest {
debugListFiles(ftp);
FTPFile[] files = ftp.listFiles();
assertThat(Arrays.asList(files), hasSize(1));
assertThat(Arrays.asList(files).stream().map(file -> file.getName()).collect(Collectors.toList()), contains("file"));
FTPFile theFile = files[0];
LOG.debug("Uploaded file={}", theFile);
......@@ -354,7 +354,7 @@ public class FtpServerTest {
}
FTPFile[] files = ftp.listFiles();
assertThat(Arrays.asList(files), hasSize(1));
assertThat(Arrays.asList(files).stream().map(file -> file.getName()).collect(Collectors.toList()), contains("rewrite"));
FTPFile theFile = files[0];
LOG.debug("Uploaded file={}", theFile);
......@@ -404,7 +404,8 @@ public class FtpServerTest {
}
FTPFile[] files = ftp.listFiles();
assertThat(Arrays.asList(files), hasSize(1));
System.err.println(Arrays.asList(files));
assertThat(Arrays.asList(files).stream().map(file -> file.getName()).collect(Collectors.toList()), contains("append.txt"));
FTPFile theFile = files[0];
LOG.debug("Uploaded file={}", theFile);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment