diff --git a/docs/nextflow_schema/nextflow_schema_specification.md b/docs/nextflow_schema/nextflow_schema_specification.md index 19ac4c1..3f57479 100644 --- a/docs/nextflow_schema/nextflow_schema_specification.md +++ b/docs/nextflow_schema/nextflow_schema_specification.md @@ -328,7 +328,7 @@ Formats can be used to give additional validation checks against `string` values !!! note In addition to _validating_ the strings as the provided format type, nf-validation also _coerces_ the parameter variable type. - That is: if the schema defines `params.input` as a `file-path-exists`, nf-validation will convert the parameter from a `String` into a `Nextflow.File`. + That is: if the schema defines `params.input` as a `file-path`, nf-validation will convert the parameter from a `String` into a `Nextflow.File`. Example usage is as follows: @@ -344,26 +344,35 @@ The available `format` types are below: `file-path` : States if the provided value is a file. Does not check its existence, but it does check that the path is not a directory. -`file-path-exists` -: Automatically checks if the provided value is a file (and not a directory), if it exists and transforms the `String` type to a `Nextflow.File` type, which is usable in Nextflow processes as a `path` input. - `directory-path` -: States if the provided value is a directory. Does not check its existence, but it does check that the path is not a file. - -`directory-path-exists` -: Automatically checks if the provided value is a directory (and not a file), if it exists and transforms the `String` type to a `Nextflow.File` type, which is usable in Nextflow processes as a `path` input. +: States if the provided value is a directory. Does not check its existence, but if it exists, it does check that the path is not a file. `path` : States if the provided value is a path (file or directory). Does not check its existence. -`path-exists` -: Automatically checks if the path (file or directory) exists and transforms the `String` type to a `Nextflow.File` type, which is usable in Nextflow processes as a `path` input. +### `exists` + +When a format is specified for a value, you can provide the key `exists` set to true in order to validate that the provided path exists. + +Example usage is as follows: + +```json +{ + "type": "string", + "format": "file-path", + "exists": true +} +``` + +!!! note + + If `exists` is set to `false`, this validation is ignored. Does not check if the path exists. ### `mimetype` MIME type for a file path. Setting this value informs downstream tools about what _kind_ of file is expected. -Should only be set when `format` is `file-path` or `file-path-exists`. +Should only be set when `format` is `file-path`. - See a [list of common MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) @@ -379,7 +388,7 @@ Should only be set when `format` is `file-path` or `file-path-exists`. Path to a JSON schema file used to validate _the supplied file_. -Should only be set when `format` is `file-path` or `file-path-exists`. +Should only be set when `format` is `file-path`. !!! tip diff --git a/docs/parameters/summary_log.md b/docs/parameters/summary_log.md index 3bc6d0e..9a918c8 100644 --- a/docs/parameters/summary_log.md +++ b/docs/parameters/summary_log.md @@ -10,7 +10,10 @@ This function returns a string that can be logged to the terminal, summarizing t !!! note -The summary prioritizes displaying only the parameters that are **different** the default schema values. This is to streamline the extensive parameter lists often associated with pipelines, and highlight the customized elements. This feature is essential for users to verify their configurations, like checking for typos or confirming proper resolution, without wading through an array of default settings. + The summary prioritizes displaying only the parameters that are **different** the default schema values. + This is to streamline the extensive parameter lists often associated with pipelines, and highlight the customized elements. + This feature is essential for users to verify their configurations, like checking for typos or confirming proper resolution, + without wading through an array of default settings. The function takes two arguments: diff --git a/docs/schema_input.json b/docs/schema_input.json index 7985c64..2673539 100644 --- a/docs/schema_input.json +++ b/docs/schema_input.json @@ -32,16 +32,19 @@ }, "field_7": { "type": "string", - "format": "file-path-exists", + "format": "file-path", + "exists": true, "pattern": "^.*\\.txt$" }, "field_8": { "type": "string", - "format": "directory-path-exists" + "format": "directory-path", + "exists": true }, "field_9": { "type": "string", - "format": "path-exists" + "format": "path", + "exists": true }, "field_10": { "type": "string", diff --git a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathExistsValidator.groovy b/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathExistsValidator.groovy deleted file mode 100644 index 50db2da..0000000 --- a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathExistsValidator.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package nextflow.validation - -import java.nio.file.Path - -import org.everit.json.schema.FormatValidator -import nextflow.Nextflow - -public class DirectoryPathExistsValidator implements FormatValidator { - - @Override - public Optional validate(final String subject) { - Path file = Nextflow.file(subject) as Path - if (!file.exists()) { - return Optional.of("the directory '${subject}' does not exist" as String) - } - else if (!file.isDirectory()) { - return Optional.of("'${subject}' is not a directory" as String) - } - return Optional.empty() - } -} \ No newline at end of file diff --git a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathValidator.groovy b/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathValidator.groovy index 9a14920..ffa52be 100644 --- a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathValidator.groovy +++ b/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/DirectoryPathValidator.groovy @@ -10,7 +10,7 @@ public class DirectoryPathValidator implements FormatValidator { @Override public Optional validate(final String subject) { Path file = Nextflow.file(subject) as Path - if (!file.isDirectory()) { + if (file.exists() && !file.isDirectory()) { return Optional.of("'${subject}' is not a directory, but a file" as String) } return Optional.empty() diff --git a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/FilePathExistsValidator.groovy b/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/FilePathExistsValidator.groovy deleted file mode 100644 index 4ed58c7..0000000 --- a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/FilePathExistsValidator.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package nextflow.validation - -import java.nio.file.Path - -import org.everit.json.schema.FormatValidator -import nextflow.Nextflow - -public class FilePathExistsValidator implements FormatValidator { - - @Override - public Optional validate(final String subject) { - Path file = Nextflow.file(subject) as Path - if (!file.exists()) { - return Optional.of("the file '${subject}' does not exist" as String) - } - else if (file.isDirectory()) { - return Optional.of("'${subject}' is not a file" as String) - } - return Optional.empty() - } -} \ No newline at end of file diff --git a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/PathExistsValidator.groovy b/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/PathExistsValidator.groovy deleted file mode 100644 index e6bfed2..0000000 --- a/plugins/nf-validation/src/main/nextflow/validation/FormatValidators/PathExistsValidator.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package nextflow.validation - -import java.nio.file.Path - -import org.everit.json.schema.FormatValidator -import nextflow.Nextflow - -public class PathExistsValidator implements FormatValidator { - - @Override - public Optional validate(final String subject) { - Path file = Nextflow.file(subject) as Path - if (!file.exists()) { - return Optional.of("the file or directory '${subject}' does not exist" as String) - } - return Optional.empty() - } -} \ No newline at end of file diff --git a/plugins/nf-validation/src/main/nextflow/validation/SchemaValidator.groovy b/plugins/nf-validation/src/main/nextflow/validation/SchemaValidator.groovy index b213626..9be5a95 100644 --- a/plugins/nf-validation/src/main/nextflow/validation/SchemaValidator.groovy +++ b/plugins/nf-validation/src/main/nextflow/validation/SchemaValidator.groovy @@ -269,6 +269,13 @@ class SchemaValidator extends PluginExtensionPoint { def List expectedParams = (List) enumsTuple[0] + addExpectedParams() def Map enums = (Map) enumsTuple[1] + //=====================================================================// + // Check if files or directories exist + def List pathsToCheck = (List) collectExists(schemaParams) + pathsToCheck.each { + pathExists(params[it].toString()) + } + def Boolean lenientMode = params.validationLenientMode ? params.validationLenientMode : false def Boolean failUnrecognisedParams = params.validationFailUnrecognisedParams ? params.validationFailUnrecognisedParams : false @@ -303,6 +310,7 @@ class SchemaValidator extends PluginExtensionPoint { .schemaJson(rawSchema) .addFormatValidator("file-path", new FilePathValidator()) .addFormatValidator("directory-path", new DirectoryPathValidator()) + .addFormatValidator("path", new PathValidator()) .build() final schema = schemaLoader.load().build() @@ -463,11 +471,8 @@ class SchemaValidator extends PluginExtensionPoint { final SchemaLoader schemaLoader = SchemaLoader.builder() .schemaJson(rawSchema) .addFormatValidator("file-path", new FilePathValidator()) - .addFormatValidator("file-path-exists", new FilePathExistsValidator()) .addFormatValidator("directory-path", new DirectoryPathValidator()) - .addFormatValidator("directory-path-exists", new DirectoryPathExistsValidator()) .addFormatValidator("path", new PathValidator()) - .addFormatValidator("path-exists", new PathExistsValidator()) .build() final schema = schemaLoader.load().build() @@ -491,6 +496,19 @@ class SchemaValidator extends PluginExtensionPoint { def List expectedParams = (List) enumsTuple[0] + addExpectedParams() def Map enums = (Map) enumsTuple[1] + //=====================================================================// + // Check if files or directories exist + def List pathsToCheck = (List) collectExists(schemaParams) + pathsToCheck.each { fieldName -> + def String filedName = fieldName + for (int i=0; i < arrayJSON.size(); i++) { + def JSONObject entry = arrayJSON.getJSONObject(i) + if ( entry.has(filedName) ) { + pathExists(entry[filedName].toString()) + } + } + } + //=====================================================================// // Validate try { @@ -514,6 +532,38 @@ class SchemaValidator extends PluginExtensionPoint { } + // + // Function to check if a file or directory exists + // + List pathExists(String path) { + def Path file = Nextflow.file(path) as Path + if (!file.exists()) { + errors << "* The file or directory '${path}' does not exist.".toString() + } + } + + + // + // Function to collect parameters with an exists key in the schema. + // + List collectExists(Map schemaParams) { + def exists = [] + for (group in schemaParams) { + def Map properties = (Map) group.value['properties'] + for (p in properties) { + def String key = (String) p.key + def Map property = properties[key] as Map + if (property.containsKey('exists') && property.containsKey('format')) { + if (property['exists'] && (property['format'] == 'file-path' || property['format'] == 'directory-path' || property['format'] == 'path') ) { + exists.push(key) + } + } + } + } + return exists + } + + // // Function to collect enums (options) of a parameter and expected parameters (present in the schema) // diff --git a/plugins/nf-validation/src/test/nextflow/validation/SamplesheetConverterTest.groovy b/plugins/nf-validation/src/test/nextflow/validation/SamplesheetConverterTest.groovy index f15ab2f..379e36f 100644 --- a/plugins/nf-validation/src/test/nextflow/validation/SamplesheetConverterTest.groovy +++ b/plugins/nf-validation/src/test/nextflow/validation/SamplesheetConverterTest.groovy @@ -352,12 +352,12 @@ class SamplesheetConverterTest extends Dsl2Spec{ def error = thrown(SchemaValidationException) def errorMessages = error.message.readLines() errorMessages[0] == "\033[0;31mThe following errors have been detected:" - errorMessages[2] == '* -- Entry 1 - field_7: string [non_existing_file.tsv] does not match pattern ^.*\\.txt$ (non_existing_file.tsv)' - errorMessages[3] == "* -- Entry 1 - field_7: the file 'non_existing_file.tsv' does not exist (non_existing_file.tsv)" - errorMessages[4] == "* -- Entry 1 - field_8: 'src/testResources/test.txt' is not a directory (src/testResources/test.txt)" - errorMessages[5] == "* -- Entry 1 - field_5: expected type: Number, found: String (string)" - errorMessages[6] == "* -- Entry 1 - field_6: expected type: Boolean, found: String (20)" - errorMessages[7] == "* -- Entry 1 - field_9: the file or directory 'non_existing_path' does not exist (non_existing_path)" + errorMessages[2] == "* The file or directory 'non_existing_path' does not exist." + errorMessages[3] == "* The file or directory 'non_existing_file.tsv' does not exist." + errorMessages[4] == '* -- Entry 1 - field_7: string [non_existing_file.tsv] does not match pattern ^.*\\.txt$ (non_existing_file.tsv)' + errorMessages[5] == "* -- Entry 1 - field_8: 'src/testResources/test.txt' is not a directory, but a file (src/testResources/test.txt)" + errorMessages[6] == "* -- Entry 1 - field_5: expected type: Number, found: String (string)" + errorMessages[7] == "* -- Entry 1 - field_6: expected type: Boolean, found: String (20)" errorMessages[8] == "* -- Entry 2: Missing required value: field_4" errorMessages[9] == "* -- Entry 2: Missing required value: field_5" errorMessages[10] == "* -- Entry 2: Missing required value: field_6" diff --git a/plugins/nf-validation/src/testResources/schema_input.json b/plugins/nf-validation/src/testResources/schema_input.json index 0ed924c..1fb3ff1 100644 --- a/plugins/nf-validation/src/testResources/schema_input.json +++ b/plugins/nf-validation/src/testResources/schema_input.json @@ -34,17 +34,20 @@ }, "field_7": { "type": "string", - "format": "file-path-exists", + "format": "file-path", + "exists": true, "pattern": "^.*\\.txt$" }, "field_8": { "type": "string", - "format": "directory-path-exists" + "format": "directory-path", + "exists": true }, "field_9": { "type": "string", - "format": "path-exists" - }, + "format": "path", + "exists": true + }, "field_10": { "type": "string", "unique": true