// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/FileAttribute.java
// public enum FileAttribute {
//     FILESIZE,
//     LAST_MODIFIED
// }
// 
// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/FileHandle.java
// public interface FileHandle {
//     InputStream readDocument();
// }
// 
// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/FileSystemProvider.java
// public interface FileSystemProvider {
//     /**
//      * Returs true if, and only if, the item represented by the given Path is a directory.
//      *
//      * @param path Path to check
//      * @return true if is directory
//      */
//     boolean isDirectory(Path path);
// 
//     /**
//      * Returns list of Paths (sub entries) for a given Path or an empty list otherwise.
//      *
//      * @param path path Path to look for sub entries
//      * @return List of Paths
//      */
//     Iterable<Path> getEntries(Path path);
// 
//     /**
//      * Returns the requested File Attribute or null if not applicable.
//      *
//      * @param path Path to get the Attribute for
//      * @param attr Type of Attribute accortidng to FileAttribute
//      * @return Attribute value or null
//      */
//     Object getAttribute(Path path, FileAttribute attr);
// 
//     FileHandle openDocument(Path path);
// }
// 
// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/Path.java
// public final class Path {
//     private final List<String> paths;
// 
//     public Path(String path) {
//         this(Arrays.asList(path.split("/")));
//     }
// 
//     private Path(List<String> list) {
//         this.paths = list;
//     }
// 
//     public static Path createWithAppended(Path path, String... appendToPath) {
//         final List<String> paths = new ArrayList<>(path.paths);
//         for (String appendix : appendToPath) {
//             if (appendix.indexOf('/') != -1) {
//                 paths.addAll(Arrays.asList(appendix.split("/")));
//             } else {
//                 paths.add(appendix);
//             }
//         }
//         return new Path(paths);
//     }
// 
//     /**
//      * Returns parent.
//      *
//      * @return parent path or null
//      */
//     public Path getParent() {
//         if (paths.size() < 3) {
//             return null;
//         }
// 
//         List<String> parentPaths = paths.subList(0, paths.size() - 1);
//         return new Path(parentPaths);
//     }
// 
//     public String getName() {
//         if (paths.size() < 2) {
//             return null;
//         }
// 
//         return paths.get(paths.size() - 1);
//     }
// 
//     public String getDeviceId() {
//         if (paths.get(0).isEmpty()) {
//             return null;
//         }
// 
//         return paths.get(0);
//     }
// 
//     public final Iterable<String> getIterator() {
//         return paths.subList(1, paths.size());
//     }
// 
//     public String toAbsolute() {
//         StringBuilder sb = new StringBuilder();
//         boolean firstTime = true;
// 
//         for (String token : paths) {
//             if (firstTime) {
//                 firstTime = false;
//             } else {
//                 sb.append('/');
//             }
//             sb.append(token);
//         }
// 
//         return sb.toString();
//     }
// 
//     public boolean isRoot() {
//         return paths.size() == 1;
//     }
// }


import net.alphadev.usbstorage.api.filesystem.FileAttribute;
import net.alphadev.usbstorage.api.filesystem.FileHandle;
import net.alphadev.usbstorage.api.filesystem.FileSystemProvider;
import net.alphadev.usbstorage.api.filesystem.Path;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import de.waldheinz.fs.FsDirectoryEntry;
import de.waldheinz.fs.fat.FatFile;
import de.waldheinz.fs.fat.FatFileSystem;
import de.waldheinz.fs.fat.FatLfnDirectory;
import de.waldheinz.fs.fat.FatLfnDirectoryEntry;
                return getFileSize(path);
            case LAST_MODIFIED:
                return getLastModified(path);
            default:
                return null;
        }
    }

    private long getFileSize(Path path) {
        final FatFile file = getFileOrNull(path);
        return file != null ? file.getLength() : 0;
    }

    private long getLastModified(Path path) {
        final FatLfnDirectoryEntry entry = getEntry(path);
        if (entry != null && entry.isFile()) {
            try {
                return entry.getLastModified();
            } catch (IOException e) {
                return 0;
            }
        }

        return 0;
    }

    @Override
    public FileHandle openDocument(Path path) {
        final FatFile fatFile = getFileOrNull(path);

// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/FileAttribute.java
// public enum FileAttribute {
//     FILESIZE,
//     LAST_MODIFIED
// }
// 
// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/FileHandle.java
// public interface FileHandle {
//     InputStream readDocument();
// }
// 
// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/FileSystemProvider.java
// public interface FileSystemProvider {
//     /**
//      * Returs true if, and only if, the item represented by the given Path is a directory.
//      *
//      * @param path Path to check
//      * @return true if is directory
//      */
//     boolean isDirectory(Path path);
// 
//     /**
//      * Returns list of Paths (sub entries) for a given Path or an empty list otherwise.
//      *
//      * @param path path Path to look for sub entries
//      * @return List of Paths
//      */
//     Iterable<Path> getEntries(Path path);
// 
//     /**
//      * Returns the requested File Attribute or null if not applicable.
//      *
//      * @param path Path to get the Attribute for
//      * @param attr Type of Attribute accortidng to FileAttribute
//      * @return Attribute value or null
//      */
//     Object getAttribute(Path path, FileAttribute attr);
// 
//     FileHandle openDocument(Path path);
// }
// 
// Path: api/src/main/java/net/alphadev/usbstorage/api/filesystem/Path.java
// public final class Path {
//     private final List<String> paths;
// 
//     public Path(String path) {
//         this(Arrays.asList(path.split("/")));
//     }
// 
//     private Path(List<String> list) {
//         this.paths = list;
//     }
// 
//     public static Path createWithAppended(Path path, String... appendToPath) {
//         final List<String> paths = new ArrayList<>(path.paths);
//         for (String appendix : appendToPath) {
//             if (appendix.indexOf('/') != -1) {
//                 paths.addAll(Arrays.asList(appendix.split("/")));
//             } else {
//                 paths.add(appendix);
//             }
//         }
//         return new Path(paths);
//     }
// 
//     /**
//      * Returns parent.
//      *
//      * @return parent path or null
//      */
//     public Path getParent() {
//         if (paths.size() < 3) {
//             return null;
//         }
// 
//         List<String> parentPaths = paths.subList(0, paths.size() - 1);
//         return new Path(parentPaths);
//     }
// 
//     public String getName() {
//         if (paths.size() < 2) {
//             return null;
//         }
// 
//         return paths.get(paths.size() - 1);
//     }
// 
//     public String getDeviceId() {
//         if (paths.get(0).isEmpty()) {
//             return null;
//         }
// 
//         return paths.get(0);
//     }
// 
//     public final Iterable<String> getIterator() {
//         return paths.subList(1, paths.size());
//     }
// 
//     public String toAbsolute() {
//         StringBuilder sb = new StringBuilder();
//         boolean firstTime = true;
// 
//         for (String token : paths) {
//             if (firstTime) {
//                 firstTime = false;
//             } else {
//                 sb.append('/');
//             }
//             sb.append(token);
//         }
// 
//         return sb.toString();
//     }
// 
//     public boolean isRoot() {
//         return paths.size() == 1;
//     }
// }


// Path: fat32/src/main/java/net/alphadev/fat32wrapper/Fat32Provider.java
import net.alphadev.usbstorage.api.filesystem.FileAttribute;
import net.alphadev.usbstorage.api.filesystem.FileHandle;
import net.alphadev.usbstorage.api.filesystem.FileSystemProvider;
import net.alphadev.usbstorage.api.filesystem.Path;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import de.waldheinz.fs.FsDirectoryEntry;
import de.waldheinz.fs.fat.FatFile;
import de.waldheinz.fs.fat.FatFileSystem;
import de.waldheinz.fs.fat.FatLfnDirectory;
import de.waldheinz.fs.fat.FatLfnDirectoryEntry;

                return getFileSize(path);
            case LAST_MODIFIED:
                return getLastModified(path);
            default:
                return null;
        }
    }

    private long getFileSize(Path path) {
        final FatFile file = getFileOrNull(path);
        return file != null ? file.getLength() : 0;
    }

    private long getLastModified(Path path) {
        final FatLfnDirectoryEntry entry = getEntry(path);
        if (entry != null && entry.isFile()) {
            try {
                return entry.getLastModified();
            } catch (IOException e) {
                return 0;
            }
        }

        return 0;
    }

    @Override
    public FileHandle openDocument(Path path) {
        final FatFile fatFile = getFileOrNull(path);

        return new FileHandle() {