@Override
    public boolean isValid(final String file, final ConstraintValidatorContext context) {
        final boolean isValid;
        if (file != null) {
            // Use the PathCreator so we can interpret relative paths and paths with '~' in.
            final Path modifiedFile = pathCreator.toAppPath(file);

            LOGGER.debug("Validating file {} (modified to {})", file, modifiedFile);
            final Path path = modifiedFile;
            isValid = Files.isRegularFile(path) && Files.isReadable(path);
            if (!isValid) {
                String msg = context.getDefaultConstraintMessageTemplate();
                if (!modifiedFile.toString().equals(file)) {
                    msg += " (as absolute path: " + modifiedFile + ")";
                }
                context.disableDefaultConstraintViolation();
                context
                        .buildConstraintViolationWithTemplate(msg)
                        .addConstraintViolation();
            }
        } else {
            isValid = true;
        }
        return isValid;
    }
Implements the validation logic.
The state of {@code value} must not be altered.
<p>
This method can be accessed concurrently, thread-safety must be ensured
by the implementation.

@param file    object to validate
@param context context in which the constraint is evaluated
@return {@code false} if {@code value} does not pass the constraint
stroom-util/src/main/java/stroom/util/validation/ValidFilePathValidatorImpl.java