class FileSource implements Source {
    private final Path path;

    private final int hashCode;

    /**
     * Creates a new source backed by the specified file.
     *
     * @param file The file, must not be {@code null}.
     * @deprecated Use {@link #FileSource(Path)} instead.
     */
    @Deprecated
    public FileSource(File file) {
        this(Objects.requireNonNull(file, "file cannot be null").toPath());
    }

    /**
     * Creates a new source backed by the specified file.
     *
     * @param path The file, must not be {@code null}.
     * @since 4.0.0
     */
    public FileSource(Path path) {
        this.path = Objects.requireNonNull(path, "path cannot be null").toAbsolutePath();
        this.hashCode = Objects.hash(path);
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return Files.newInputStream(path);
    }

    @Override
    public String getLocation() {
        return path.toString();
    }

    /**
     * Gets the file of this source.
     *
     * @return The underlying file, never {@code null}.
     * @deprecated Use {@link #getPath()} instead.
     */
    @Deprecated
    public File getFile() {
        return path.toFile();
    }

    /**
     * Gets the file of this source.
     *
     * @return The underlying file, never {@code null}.
     * @since 4.0.0
     */
    public Path getPath() {
        return path;
    }

    @Override
    public String toString() {
        return getLocation();
    }

    @Override
    public int hashCode() {
        return hashCode;
    }

    @Override
    public boolean equals(Object obj) {<FILL_FUNCTION_BODY>}
}

        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (!FileSource.class.equals(obj.getClass())) {
            return false;
        }

        FileSource other = (FileSource) obj;
        return this.path.equals(other.path);
    
<no_super_class>