diff --git a/measurement-provider/pom.xml b/measurement-provider/pom.xml index 2efb9e7..3137272 100644 --- a/measurement-provider/pom.xml +++ b/measurement-provider/pom.xml @@ -6,13 +6,43 @@ life.qbic data-download-server - 1.0.5 + 1.0.6 life.qbic.data-download measurement-provider - 1.0.5 + 1.0.6 jar + + + org.spockframework + spock-core + 2.4-M4-groovy-4.0 + test + + + org.apache.groovy + groovy-all + 4.0.24 + pom + test + + + + org.junit.platform + junit-platform-launcher + 1.9.2 + test + + + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + test + + diff --git a/measurement-provider/src/main/java/life/qbic/data_download/measurements/api/PathFormatter.java b/measurement-provider/src/main/java/life/qbic/data_download/measurements/api/PathFormatter.java new file mode 100644 index 0000000..1e9c7a8 --- /dev/null +++ b/measurement-provider/src/main/java/life/qbic/data_download/measurements/api/PathFormatter.java @@ -0,0 +1,89 @@ +package life.qbic.data_download.measurements.api; + +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; + +/** + * PathFormatter applies filters to a given String value that represents a path. + * + * @since 1.1.0 + */ +public class PathFormatter { + + private final List filter; + + private PathFormatter() { + filter = new ArrayList<>(); + } + + private PathFormatter(Collection filter) { + this.filter = new ArrayList<>(filter); + } + + /** + * Creates a new instance of {@link PathFormatter} with a collection of filter regex expression. + * + * @param filter the terms to filter out + * @return a {@link PathFormatter} instance + * @since 1.1.0 + */ + public static PathFormatter with(Collection filter) { + Objects.requireNonNull(filter); + return new PathFormatter(filter); + } + + private static String apply(Path p, Collection filter) { + Path result = p.isAbsolute() ? p.getRoot() : Paths.get(""); + + for (Path part : p) { + if (matchesAny(part.toString(), filter)) { + continue; + } + result = result.resolve(part); + } + return result.toString(); + } + + private static boolean matchesAny(String s, Collection filter) { + return filter.stream().anyMatch(s::matches); + } + + /** + * Applies the configured filter to the provided String. + *

+ * The provided String is expected to be a valid {@link java.nio.file.Path}, otherwise an + * {@link InvalidPathException} is thrown. + *

+ * Format iterates through every part of the path and checks them agains the configured filters. + *

+ * The filter matching works the same as {@link Pattern#matches(String, CharSequence)}. + *

+ * The resulting String representation of a path will be removed of any matching filter terms. + * + *

+   *   List filters = Arrays.asList("removeme");
+   *   var formatter = PathFormatter.with(filters);
+   *
+   *   System.out.println(formatter("/example/removeme/path"));
+   *
+   *   // Prints out "/example/path"
+   * 
+ *

+ * Format has an implicit check for {@link Path#isAbsolute()} and preserves an absolute or + * relative path. + * + * @param s the String value to format + * @return the formatted new String, after the filter has been applied + * @throws InvalidPathException in case the String is not a valid path + * @since 1.1.0 + */ + public String format(String s) throws InvalidPathException { + return apply(Path.of(s), filter); + } +} diff --git a/measurement-provider/src/test/groovy/life/qbic/data_download/measurement/api/PathFormatterSpec.groovy b/measurement-provider/src/test/groovy/life/qbic/data_download/measurement/api/PathFormatterSpec.groovy new file mode 100644 index 0000000..0d2189f --- /dev/null +++ b/measurement-provider/src/test/groovy/life/qbic/data_download/measurement/api/PathFormatterSpec.groovy @@ -0,0 +1,45 @@ +package life.qbic.data_download.measurement.api + +import life.qbic.data_download.measurements.api.PathFormatter +import spock.lang.Specification + +class PathFormatterSpec extends Specification { + + def "Given a String with a to filtered part, the filtered part must not be part of the resulting String"() { + given: + var filter = Arrays.asList("awesome", "wehaa") + + and: + var f = PathFormatter.with(filter) + + when: + var result = f.format(input) + + then: + result == expected + + where: + input | expected + "/my/awesome/path/wehaa" | "/my/path" + "a/relative/wehaa/awesome/path" | "a/relative/path" + } + + def "Given a String that contains a UUID-4 in its path, the formatter shall filter it out"() { + given: + var filter = Arrays.asList("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\$") + + and: + var f = PathFormatter.with(filter) + + when: + var result = f.format(input) + + then: + result == expected + + where: + input | expected + "/my/f47ac10b-58cc-4372-a567-0e02b2c3d479/path/" | "/my/path" + "a/relative/f47ac10b-58cc-4372-a567-0e02b2c3d479/path" | "a/relative/path" + } +} diff --git a/openbis-connector/pom.xml b/openbis-connector/pom.xml index 5dcd75d..c6659ae 100644 --- a/openbis-connector/pom.xml +++ b/openbis-connector/pom.xml @@ -7,13 +7,13 @@ life.qbic data-download-server - 1.0.5 + 1.0.6 life.qbic.data-download openbis-connector jar - 1.0.5 + 1.0.6 @@ -66,7 +66,7 @@ life.qbic.data-download measurement-provider - 1.0.5 + 1.0.6 org.junit.jupiter diff --git a/openbis-connector/src/main/java/life/qbic/data_download/openbis/DatasetFileStreamReaderImpl.java b/openbis-connector/src/main/java/life/qbic/data_download/openbis/DatasetFileStreamReaderImpl.java index 936c26a..2dc1307 100644 --- a/openbis-connector/src/main/java/life/qbic/data_download/openbis/DatasetFileStreamReaderImpl.java +++ b/openbis-connector/src/main/java/life/qbic/data_download/openbis/DatasetFileStreamReaderImpl.java @@ -6,10 +6,12 @@ import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.download.DataSetFileDownload; import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.download.DataSetFileDownloadReader; import java.io.InputStream; -import java.util.Optional; +import java.util.List; +import java.util.Objects; import life.qbic.data_download.measurements.api.DataFile; import life.qbic.data_download.measurements.api.FileInfo; import life.qbic.data_download.measurements.api.MeasurementDataReader; +import life.qbic.data_download.measurements.api.PathFormatter; /** * Reads openbis data streams @@ -17,11 +19,16 @@ public class DatasetFileStreamReaderImpl implements MeasurementDataReader { private DataSetFileDownloadReader dataSetFileDownloadReader; - private final String ignoredPrefix; + + private final PathFormatter formatter; + + private static final String UUID_REGEX = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"; public DatasetFileStreamReaderImpl(String ignoredPrefix) { + Objects.requireNonNull(ignoredPrefix); dataSetFileDownloadReader = null; - this.ignoredPrefix = Optional.ofNullable(ignoredPrefix).orElse(""); + var filter = List.of(ignoredPrefix, UUID_REGEX); + this.formatter = PathFormatter.with(filter); } @@ -55,7 +62,10 @@ public DataFile nextDataFile() { .toEpochMilli() : -1; long lastModifiedMillis = nonNull(dataStore) ? dataStore.getModificationDate().toInstant() .toEpochMilli() : -1; - FileInfo fileInfo = new FileInfo(fileDownload.getDataSetFile().getPath().replaceFirst(ignoredPrefix, ""), + + var cleanedPath = formatter.format(fileDownload.getDataSetFile().getPath()); + + FileInfo fileInfo = new FileInfo(cleanedPath, fileDownload.getDataSetFile().getFileLength(), Integer.toUnsignedLong(fileDownload.getDataSetFile().getChecksumCRC32()), creationMillis, diff --git a/pom.xml b/pom.xml index f224478..7e022bf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ life.qbic data-download-server - 1.0.5 + 1.0.6 pom diff --git a/rest-api/pom.xml b/rest-api/pom.xml index 9ad2114..34d1416 100644 --- a/rest-api/pom.xml +++ b/rest-api/pom.xml @@ -7,12 +7,12 @@ life.qbic data-download-server - 1.0.5 + 1.0.6 life.qbic.data-download rest-server - 1.0.5 + 1.0.6 jar @@ -65,17 +65,17 @@ life.qbic.data-download measurement-provider - 1.0.5 + 1.0.6 life.qbic.data-download openbis-connector - 1.0.5 + 1.0.6 life.qbic.data-download zip - 1.0.5 + 1.0.6 diff --git a/zip/pom.xml b/zip/pom.xml index 5589012..76ac382 100644 --- a/zip/pom.xml +++ b/zip/pom.xml @@ -6,7 +6,7 @@ life.qbic data-download-server - 1.0.5 + 1.0.6 life.qbic.data-download