diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProvider.java index 31a549ef986560ad78262a92c6d98cccd30cfed2..90ce73e550bfb7114bc57c2ccc6703957c9d7ccb 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProvider.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProvider.java @@ -91,14 +91,16 @@ public class DatabaseBasedDataSetPathInfoProvider implements IDataSetPathInfoPro String relativePathLikeExpression); @Select(SELECT_DATA_SET_FILES - + "WHERE dase_id = ?{1} AND relative_path = '?{2}' AND file_name ~ ?{3}") - public List<DataSetFileRecord> listDataSetFilesByFilenameRegex(long dataSetId, - String startingPath, String filenameRegex); + + "WHERE dase_id = ?{1} AND relative_path = ?{2} || file_name AND file_name ~ ?{3}") + public List<DataSetFileRecord> listDataSetFilesByFilenameRegex( + long dataSetId, String startingPath, String filenameRegex); @Select(SELECT_DATA_SET_FILES - + "WHERE dase_id = ?{1} AND relative_path = '?{2}' AND file_name LIKE ?{3}") - public List<DataSetFileRecord> listDataSetFilesByFilenameLikeExpression(long dataSetId, - String startingPath, String filenameLikeExpression); + + "WHERE dase_id = ?{1} AND relative_path = ?{2} || file_name AND file_name LIKE ?{3}") + public List<DataSetFileRecord> listDataSetFilesByFilenameLikeExpression( + long dataSetId, String startingPath, + String filenameLikeExpression); + } private static interface ILoader @@ -162,7 +164,8 @@ public class DatabaseBasedDataSetPathInfoProvider implements IDataSetPathInfoPro Map<String, Integer> files = new HashMap<String, Integer>(); IPathInfoDAO queries = getDao(); Long id = queries.tryToGetDataSetId(dataSetCode); - if (id == null) { + if (id == null) + { return files; } List<DataSetFileRecord> records = getDao().listDataSetFiles(id); @@ -255,18 +258,31 @@ public class DatabaseBasedDataSetPathInfoProvider implements IDataSetPathInfoPro public List<DataSetPathInfo> listMatchingPathInfos(String startingPath, String fileNamePattern) { + String aStartingPath = null; + + if (startingPath == null || startingPath.trim().length() == 0) + { + aStartingPath = ""; + } else if (startingPath.endsWith("/")) + { + aStartingPath = startingPath; + } else + { + aStartingPath = startingPath + "/"; + } + String likeExpressionOrNull = DBUtils.tryToTranslateRegExpToLikePattern(prepareDBStyleRegex(fileNamePattern)); List<DataSetFileRecord> records; if (likeExpressionOrNull == null) { records = - dao.listDataSetFilesByFilenameRegex(dataSetId, startingPath, + dao.listDataSetFilesByFilenameRegex(dataSetId, aStartingPath, prepareDBStyleRegex(fileNamePattern)); } else { records = - dao.listDataSetFilesByFilenameLikeExpression(dataSetId, startingPath, + dao.listDataSetFilesByFilenameLikeExpression(dataSetId, aStartingPath, likeExpressionOrNull); } return asPathInfos(records); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/PathInfoDatabaseTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/PathInfoDatabaseTest.java index f02dd0138849f1590966b2a3cdff96167a30842a..c1c5b5171297a7cf1821a6fce2958194d913b0c7 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/PathInfoDatabaseTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/PathInfoDatabaseTest.java @@ -31,9 +31,12 @@ import javax.sql.DataSource; import net.lemnik.eodsql.QueryTool; import org.apache.commons.lang.time.StopWatch; +import org.testng.Assert; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import ch.systemsx.cisd.etlserver.path.IPathsInfoDAO; +import ch.systemsx.cisd.openbis.dss.generic.shared.ISingleDataSetPathInfoProvider; import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetPathInfo; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PathInfoDataSourceProvider; @@ -44,19 +47,34 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PathInfoDataSourceProvi @Test(groups = "slow") public class PathInfoDatabaseTest extends SystemTestCase { - @Test - public void testPathInfoDatabase() throws Exception + + @BeforeTest + private void initDatabase() throws Exception { DataSource dataSource = PathInfoDataSourceProvider.getDataSource(); - cleanUpDatabase(dataSource); StopWatch stopWatch = new StopWatch(); stopWatch.start(); + + cleanUpDatabase(dataSource); + + System.out.println(stopWatch.getTime() + " msec for cleaning up old entries"); + + stopWatch.reset(); + stopWatch.start(); + int n = feedDataBase(dataSource); + System.out.println(stopWatch.getTime() + " msec for creating " + n + " entries"); + } - stopWatch.reset(); + @Test + public void testPathInfoDatabase() throws Exception + { + DataSource dataSource = PathInfoDataSourceProvider.getDataSource(); + StopWatch stopWatch = new StopWatch(); List<String> paths = new ArrayList<String>(); + Connection connection = null; String regex = ".*file-[2-3].*81.*(25|49).*36.*"; try @@ -123,15 +141,209 @@ public class PathInfoDatabaseTest extends SystemTestCase + "file-3-9/file-9-81/file-7-49/file-6-36-xyz.xml]", paths.toString()); } + @Test + public void testListMatchingPathInfosWithRelativePathPatternWithExactMatch() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider + .listMatchingPathInfos("file-9-81/file-9-81/file-9-81/file-9-81-xyz.xml"); + + assertRelativePaths(actualFiles, "file-9-81/file-9-81/file-9-81/file-9-81-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithRelativePathPatternWithoutAnyMatch() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider + .listMatchingPathInfos("file-9-81/file-9-81/file-9-81/file-9-81-xyz.xml.notexisting"); + + assertRelativePaths(actualFiles, new String[] {}); + } + + @Test + public void testListMatchingPathInfosWithRelativePathPatternWithSpecialCharactersConvertableToLike() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-2"); + + List<DataSetPathInfo> actualFiles = provider + .listMatchingPathInfos("special_characters_%\\?\\.file-9-81/.*file.*1.*xml"); + + assertRelativePaths(actualFiles, "special_characters_%?.file-9-81/special_characters_%?.file-1-1-xyz.xml", + "special_characters_%?.file-9-81/special_characters_%?.file-4-16-xyz.xml", + "special_characters_%?.file-9-81/special_characters_%?.file-9-81-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithRelativePathPatternWithSpecialCharactersNotConvertableToLike() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-2"); + + List<DataSetPathInfo> actualFiles = provider + .listMatchingPathInfos("special_characters_%\\?\\.file-9-81/.*(file-0-0|file-2-4).*"); + + assertRelativePaths(actualFiles, "special_characters_%?.file-9-81/special_characters_%?.file-0-0-xyz.xml", + "special_characters_%?.file-9-81/special_characters_%?.file-2-4-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithStartingPathAndFileNamePatternWithExactMatch() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "file-9-81/file-9-81/file-9-81", "file-9-81-xyz.xml"); + + assertRelativePaths(actualFiles, "file-9-81/file-9-81/file-9-81/file-9-81-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithEmptyStartingPath() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-2"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos("", "special_characters_%\\?\\.file-8-64"); + + assertRelativePaths(actualFiles, "special_characters_%?.file-8-64"); + } + + @Test + public void testListMatchingPathInfosWithNullStartingPath() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-2"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos(null, "special_characters_%\\?\\.file-8-64"); + + assertRelativePaths(actualFiles, "special_characters_%?.file-8-64"); + } + + @Test + public void testListMatchingPathInfosWithStartingPathWithoutSlash() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "file-9-81/file-9-81/file-9-81", "file-9-81-xyz.xml"); + + assertRelativePaths(actualFiles, "file-9-81/file-9-81/file-9-81/file-9-81-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithStartingPathWithSlash() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "file-9-81/file-9-81/file-9-81/", "file-9-81-xyz.xml"); + + assertRelativePaths(actualFiles, "file-9-81/file-9-81/file-9-81/file-9-81-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithStartingPathAndFileNamePatternWithoutAnyMatch() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "file-9-81/file-9-81/file-9-81", "file-9-81-xyz.xml.notexisting"); + + assertRelativePaths(actualFiles, new String[] {}); + } + + @Test + public void testListMatchingPathInfosWithStartingPathThatMatchesRelativePathAndEmptyFileNamePattern() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-1"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "file-9-81/file-9-81/file-9-81-xyz.xml", ""); + + assertRelativePaths(actualFiles, new String[] {}); + } + + @Test + public void testListMatchingPathInfosWithStartingPathWithSpecialCharactersAndFileNamePatternConvertableToLike() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-2"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "special_characters_%?.file-9-81", ".*file.*1.*xml"); + + assertRelativePaths(actualFiles, "special_characters_%?.file-9-81/special_characters_%?.file-1-1-xyz.xml", + "special_characters_%?.file-9-81/special_characters_%?.file-4-16-xyz.xml", + "special_characters_%?.file-9-81/special_characters_%?.file-9-81-xyz.xml"); + } + + @Test + public void testListMatchingPathInfosWithStartingPathWithSpecialCharactersAndFileNamePatternNotConvertableToLike() + { + ISingleDataSetPathInfoProvider provider = ServiceProvider + .getDataSetPathInfoProvider() + .tryGetSingleDataSetPathInfoProvider("ds-2"); + + List<DataSetPathInfo> actualFiles = provider.listMatchingPathInfos( + "special_characters_%?.file-9-81", ".*(file-0-0|file-2-4).*"); + + assertRelativePaths(actualFiles, "special_characters_%?.file-9-81/special_characters_%?.file-0-0-xyz.xml", + "special_characters_%?.file-9-81/special_characters_%?.file-2-4-xyz.xml"); + } + + private void assertRelativePaths(List<DataSetPathInfo> actualFiles, String... expectedRelativePaths) + { + Assert.assertEquals(actualFiles.size(), expectedRelativePaths.length); + + for (int i = 0; i < expectedRelativePaths.length; i++) + { + String expectedRelativePath = expectedRelativePaths[i]; + DataSetPathInfo actualFile = actualFiles.get(i); + + Assert.assertEquals(actualFile.getRelativePath(), expectedRelativePath); + } + } + private int feedDataBase(DataSource dataSource) { int numberOfEntries = 0; IPathsInfoDAO dao = QueryTool.getQuery(dataSource, IPathsInfoDAO.class); try { - long id = dao.createDataSet("ds-1", "a/b/c/"); - long parentId = dao.createDataSetFile(id, null, "", "ds-1", 0, true, new Date(4711)); - numberOfEntries += feedDataBase(dao, id, parentId, 3, ""); + long id; + long parentId; + + id = dao.createDataSet("ds-1", "a/b/c/"); + parentId = dao.createDataSetFile(id, null, "", "ds-1", 0, true, new Date(4711)); + numberOfEntries += feedDataBase(dao, id, parentId, 3, "", ""); + + id = dao.createDataSet("ds-2", "a2/b2/c2/"); + parentId = dao.createDataSetFile(id, null, "", "ds-2", 0, true, new Date(4722)); + numberOfEntries += feedDataBase(dao, id, parentId, 1, "", "special_characters_%?."); + dao.commit(); } catch (Exception ex) { @@ -143,13 +355,13 @@ public class PathInfoDatabaseTest extends SystemTestCase } private int feedDataBase(IPathsInfoDAO dao, long dataSetId, Long parentId, int level, - String prefix) + String prefix, String fileNamePrefix) { int numberOfEntries = 0; for (int i = 0; i < 10; i++) { boolean directory = level > 0; - String fileName = "file-" + i + "-" + (i * i) + (directory ? "" : "-xyz.xml"); + String fileName = fileNamePrefix + "file-" + i + "-" + (i * i) + (directory ? "" : "-xyz.xml"); long id = dao.createDataSetFile(dataSetId, parentId, prefix + fileName, fileName, level * 100 + i, directory, new Date(4711)); @@ -157,7 +369,7 @@ public class PathInfoDatabaseTest extends SystemTestCase if (directory) { numberOfEntries += - feedDataBase(dao, dataSetId, id, level - 1, prefix + fileName + "/"); + feedDataBase(dao, dataSetId, id, level - 1, prefix + fileName + "/", fileNamePrefix); } } return numberOfEntries; @@ -183,7 +395,7 @@ public class PathInfoDatabaseTest extends SystemTestCase try { connection = dataSource.getConnection(); - connection.createStatement().execute("delete from data_sets where code like 'ds-1'"); + connection.createStatement().execute("delete from data_sets where code like 'ds-1' or code like 'ds-2'"); } finally { close(connection); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java index 2b2acca96c79f3021dba2e60f8b6ea57482163be..73b740ab0d20a24c9829ffe466992554f636c966 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DatabaseBasedDataSetPathInfoProviderTest.java @@ -39,9 +39,9 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetPathInfo; /** * @author Franz-Josef Elmer */ -@Friend(toClasses = {DatabaseBasedDataSetPathInfoProvider.class, - DatabaseBasedDataSetPathInfoProvider.IPathInfoDAO.class, - DatabaseBasedDataSetPathInfoProvider.DataSetFileRecord.class}) +@Friend(toClasses = { DatabaseBasedDataSetPathInfoProvider.class, + DatabaseBasedDataSetPathInfoProvider.IPathInfoDAO.class, + DatabaseBasedDataSetPathInfoProvider.DataSetFileRecord.class }) public class DatabaseBasedDataSetPathInfoProviderTest extends AssertJUnit { private static final Long DATA_SET_ID = 41L; @@ -351,7 +351,7 @@ public class DatabaseBasedDataSetPathInfoProviderTest extends AssertJUnit context.checking(new Expectations() { { - one(dao).listDataSetFilesByFilenameRegex(DATA_SET_ID, startingPath, + one(dao).listDataSetFilesByFilenameRegex(DATA_SET_ID, startingPath + "/", "^" + regex + "$"); will(returnValue(Arrays.asList(rc1, rc2))); } @@ -378,7 +378,7 @@ public class DatabaseBasedDataSetPathInfoProviderTest extends AssertJUnit context.checking(new Expectations() { { - one(dao).listDataSetFilesByFilenameLikeExpression(DATA_SET_ID, startingPath, + one(dao).listDataSetFilesByFilenameLikeExpression(DATA_SET_ID, startingPath + "/", "child%"); will(returnValue(Arrays.asList(rc1, rc2))); }