From 50eba8238b88aea93381ee1eb6bf6e5152df8f74 Mon Sep 17 00:00:00 2001 From: Robert Vokac Date: Sat, 14 Sep 2024 10:18:18 +0200 Subject: [PATCH] Bug 14: Added FileHandle and FileHandleImpl --- .../api/storage/FileHandle.java | 65 +++++ .../api/storage/FileHandleImpl.java | 224 ++++++++++++++++++ .../api/storage/FileType.java | 32 +++ .../api/storage/RegularFileType.java | 32 +++ .../pixelgamelibrary/api/storage/Storage.java | 65 ++--- .../storage/command/StorageCommandLine.java | 14 +- .../api/storage/map/MapFileType.java | 13 +- .../api/storage/map/MapStorage.java | 71 +++--- .../api/storage/FileHandleImplTest.java | 170 +++++++++++++ .../command/StorageCommandLineTest.java | 12 +- .../api/storage/map/MapStorageTest.java | 18 +- 11 files changed, 633 insertions(+), 83 deletions(-) create mode 100644 src/main/java/com/pixelgamelibrary/api/storage/FileHandle.java create mode 100644 src/main/java/com/pixelgamelibrary/api/storage/FileHandleImpl.java create mode 100644 src/main/java/com/pixelgamelibrary/api/storage/FileType.java create mode 100644 src/main/java/com/pixelgamelibrary/api/storage/RegularFileType.java create mode 100644 src/test/java/com/pixelgamelibrary/api/storage/FileHandleImplTest.java diff --git a/src/main/java/com/pixelgamelibrary/api/storage/FileHandle.java b/src/main/java/com/pixelgamelibrary/api/storage/FileHandle.java new file mode 100644 index 0000000..3c9aee9 --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/storage/FileHandle.java @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// + +package com.pixelgamelibrary.api.storage; + +import java.util.List; + +/** + * + * @author robertvokac + */ +public interface FileHandle { + FileType type(); + String path (); + String name (); + String extension (); + String nameWithoutExtension (); + List list(); + default boolean isDirectory() { + return type() == FileType.DIRECTORY; + } + + default boolean isRegularFile() { + return type() == FileType.FILE; + } + FileHandle child(String name); + FileHandle sibling(String name); + FileHandle parent(); + boolean mkdir(); + boolean mkdirs(); + boolean exists(); + boolean delete(); + boolean deleteDirectory(); + boolean emptyDirectory(); + boolean copyTo(FileHandle destination); + boolean moveTo(FileHandle destination); + + long length(); + FileHandle tempFile (String prefix); + FileHandle tempDirectory (String prefix); + int depth(); + boolean writeString(String text); + boolean appendString(String text); + String readString(); + + boolean writeBytes(byte[] data); + byte[] readBytes(); +} diff --git a/src/main/java/com/pixelgamelibrary/api/storage/FileHandleImpl.java b/src/main/java/com/pixelgamelibrary/api/storage/FileHandleImpl.java new file mode 100644 index 0000000..2fae8af --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/storage/FileHandleImpl.java @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.pixelgamelibrary.api.storage; + +import static com.pixelgamelibrary.api.storage.RegularFileType.TEXT; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author robertvokac + */ +public class FileHandleImpl implements FileHandle { + + private final Storage storage; + private final String path; + private String name; + + public FileHandleImpl(Storage storage, String path) { + this.storage = storage; + this.path = path.equals(".") ? storage.printWorkingDirectory() : path; + { + if (path.equals("/")) { + name = path; + } else { + String[] array = path.split("/"); + name = array[array.length - 1]; + } + } + } + + @Override + public FileType type() { + return storage.type(path); + } + + @Override + public String path() { + return path; + } + + @Override + public String name() { + return name; + } + + @Override + public String extension() { + String extension = ""; + + int i = name.lastIndexOf('.'); + if (i > 0) { + extension = name.substring(i + 1); + } + return extension; + } + + @Override + public String nameWithoutExtension() { + return name.substring(0, name.length() - extension().length() -1); + } + + @Override + public List list() { + List list = storage.list(path); + List files = new ArrayList<>(); + for(String s:list) { + files.add(new FileHandleImpl(storage, s)); + } + return files; + } + + @Override + public FileHandle child(String name) { + return new FileHandleImpl(storage, path + "/" + name); + } + + @Override + public FileHandle sibling(String siblingName) { + int nameLength = name.length(); + String f = path.substring(0, path.length() - nameLength - 1) + "/" + siblingName; + + return new FileHandleImpl(storage, f); + } + + @Override + public FileHandle parent() { + return new FileHandleImpl(storage, path.substring(0, path.length() - name.length() - 1)); + } + + @Override + public boolean mkdir() { + return storage.createDirectory(path).isEmpty(); + } + + @Override + public boolean mkdirs() { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public boolean exists() { + return storage.exists(path); + } + + @Override + public boolean delete() { + return storage.remove(path); + } + + @Override + public boolean deleteDirectory() { + return storage.removeDirectory(path); + } + + @Override + public boolean emptyDirectory() { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public boolean copyTo(FileHandle destination) { + return storage.copy(path, destination.path()).isEmpty(); + } + + @Override + public boolean moveTo(FileHandle destination) { + return storage.move(path, destination.path()).isEmpty(); + } + + @Override + public long length() { + if(isDirectory()) { + return 0; + } + RegularFileType rft = storage.getRegularFileType(path); + switch(rft){ + case TEXT: return readString().length(); + case BINARY: return readBytes().length; + default: throw new UnsupportedOperationException("Unsupported RegularFileType: " + rft); + } + } + + @Override + public FileHandle tempFile(String prefix) { + createTmpDirectoryIfDoesNotYetExist(); + String r = createRandomName(); + storage.touch(r); + return new FileHandleImpl(storage, "/tmp/"+r); + } + + private String createRandomName() { + return + String.valueOf((int)(Math.random() * 1000000)) + + String.valueOf((int)(Math.random() * 1000000)) + + String.valueOf((int)(Math.random() * 1000000)); + } + + private void createTmpDirectoryIfDoesNotYetExist() { + if(!storage.exists("/tmp")) { + storage.createDirectory("/tmp"); + } + } + + @Override + public FileHandle tempDirectory(String prefix) { + createTmpDirectoryIfDoesNotYetExist(); + + String r = createRandomName(); + storage.createDirectory(r); + return new FileHandleImpl(storage, "/tmp/"+r); + } + + @Override + public int depth() { + return storage.depth(path); + } + + @Override + public boolean writeString(String text) { + return storage.writeString(path, text).isEmpty(); + } + + @Override + public boolean appendString(String text + ) { + String textCurrent = readString(); + return storage.writeString(path, textCurrent + text).isEmpty(); + } + + @Override + public String readString() { + return storage.readString(path); + } + + @Override + public boolean writeBytes(byte[] data + ) { + return storage.writeBytes(path, data).isEmpty(); + } + + @Override + public byte[] readBytes() { + return storage.readBytes(path); + } + +} diff --git a/src/main/java/com/pixelgamelibrary/api/storage/FileType.java b/src/main/java/com/pixelgamelibrary/api/storage/FileType.java new file mode 100644 index 0000000..1527215 --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/storage/FileType.java @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// + +package com.pixelgamelibrary.api.storage; + + +/** + * Enum representing the types of files or directories in the map. + * It can either be a FILE or a DIRECTORY. + * + * @author robertvokac + */ +public enum FileType { + FILE, DIRECTORY; +} diff --git a/src/main/java/com/pixelgamelibrary/api/storage/RegularFileType.java b/src/main/java/com/pixelgamelibrary/api/storage/RegularFileType.java new file mode 100644 index 0000000..fc9255c --- /dev/null +++ b/src/main/java/com/pixelgamelibrary/api/storage/RegularFileType.java @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Pixel: Game library. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// + +package com.pixelgamelibrary.api.storage; + + +/** + * Enum representing the types of regular files. + * It can either be a TEXT or a BINARY. + * + * @author robertvokac + */ +public enum RegularFileType { + TEXT, BINARY; +} diff --git a/src/main/java/com/pixelgamelibrary/api/storage/Storage.java b/src/main/java/com/pixelgamelibrary/api/storage/Storage.java index d64c2f2..f5f71b6 100644 --- a/src/main/java/com/pixelgamelibrary/api/storage/Storage.java +++ b/src/main/java/com/pixelgamelibrary/api/storage/Storage.java @@ -44,7 +44,7 @@ public interface Storage { * @param path the path to change to. * @return a result message or an empty string if successful. */ - public String cd(String path); + public String changeDirectory(String path); /** * Changes the directory to the default "home/user" directory, creating the necessary @@ -52,12 +52,12 @@ public interface Storage { * * @return a result message or an empty string if successful. */ - default String cd() { - cd("/"); - mkdir("home"); - cd("home"); - mkdir(uname()); - cd(uname()); + default String changeDirectory() { + Storage.this.changeDirectory("/"); + createDirectory("home"); + Storage.this.changeDirectory("home"); + createDirectory(getUserName()); + Storage.this.changeDirectory(getUserName()); return ""; } @@ -67,7 +67,7 @@ public interface Storage { * @param argument the name of the directory to create. * @return a result message or an empty string if successful. */ - public String mkdir(String argument); + public String createDirectory(String argument); /** * Creates multiple directories specified by the arguments. @@ -75,12 +75,12 @@ public interface Storage { * @param argument the names of the directories to create. * @return a result message or an empty string if successful. */ - default String mkdirmore(String... argument) { + default String createDirectories(String... argument) { if (argument.length == 0) { return "Missing argument"; } for (String n : argument) { - String result = mkdir(n); + String result = createDirectory(n); if (!result.isEmpty()) { return result; } @@ -93,7 +93,7 @@ public interface Storage { * * @return the path of the current working directory. */ - public String pwd(); + public String printWorkingDirectory(); /** * Lists the contents of the specified directory. @@ -101,15 +101,15 @@ public interface Storage { * @param workingDirectory the directory to list. * @return a list of file and directory names in the specified directory. */ - public List ls(String workingDirectory); + public List list(String workingDirectory); /** * Lists the contents of the current working directory. * * @return a list of file and directory names in the current working directory. */ - default List ls() { - return ls(pwd()); + default List list() { + return list(printWorkingDirectory()); } /** @@ -126,7 +126,7 @@ public interface Storage { * @return the depth of the current working directory. */ default int depth() { - return depth(pwd()); + return depth(printWorkingDirectory()); } /** @@ -143,7 +143,7 @@ public interface Storage { * @param name the name of the file to remove. * @return true if the file was successfully removed, false otherwise. */ - public boolean rm(String name); + public boolean remove(String name); /** * Removes the directory with the specified name. @@ -151,7 +151,7 @@ public interface Storage { * @param dirname the name of the directory to remove. * @return true if the directory was successfully removed, false otherwise. */ - public boolean rmdir(String dirname); + public boolean removeDirectory(String dirname); /** * Copies a file from the source path to the target path. @@ -160,7 +160,7 @@ public interface Storage { * @param target the target file path. * @return a result message or an empty string if successful. */ - public String cp(String source, String target); + public String copy(String source, String target); /** * Moves a file from the source path to the target path. @@ -169,7 +169,7 @@ public interface Storage { * @param target the target file path. * @return a result message or an empty string if successful. */ - public String mv(String source, String target); + public String move(String source, String target); /** * Reads the contents of a text file with the specified name. @@ -177,7 +177,7 @@ public interface Storage { * @param name the name of the file to read. * @return the text content of the file. */ - public String readtext(String name); + public String readString(String name); /** * Reads the contents of a binary file with the specified name. @@ -185,7 +185,7 @@ public interface Storage { * @param name the name of the file to read. * @return the binary content of the file. */ - public byte[] readbin(String name); + public byte[] readBytes(String name); /** * Saves the specified text content to a file with the given name. @@ -194,7 +194,7 @@ public interface Storage { * @param text the text content to save. * @return a result message or an empty string if successful. */ - public String savetext(String name, String text); + public String writeString(String name, String text); /** * Saves the specified binary data to a file with the given name. @@ -203,7 +203,7 @@ public interface Storage { * @param data the binary data to save. * @return a result message or an empty string if successful. */ - public String savebin(String name, byte[] data); + public String writeBytes(String name, byte[] data); /** * Checks whether a file or directory with the specified name exists. @@ -219,7 +219,7 @@ public interface Storage { * @param name the name to check. * @return true if the name refers to a file, false otherwise. */ - public boolean isfile(String name); + public boolean isFile(String name); /** * Checks whether the specified name refers to a directory. @@ -227,7 +227,7 @@ public interface Storage { * @param name the name to check. * @return true if the name refers to a directory, false otherwise. */ - public boolean isdir(String name); + public boolean isDirectory(String name); /** * Returns a debug string with information about the current state of the storage. @@ -246,7 +246,7 @@ public interface Storage { * * @return the username. */ - default String uname() { + default String getUserName() { return USER; } @@ -256,7 +256,7 @@ public interface Storage { * * @return the size limit in bytes, or 0 if there is no limit. */ - default long sizelimitedto() { + default long getSizeLimit() { return 0; } @@ -264,4 +264,15 @@ public interface Storage { * The default username for the storage. */ static final String USER = "user"; + + default FileHandle file(String path) { + return new FileHandleImpl(this, path); + } + default FileHandle file() { + return file(printWorkingDirectory()); + } + + FileType type(String path); + + RegularFileType getRegularFileType(String path); } diff --git a/src/main/java/com/pixelgamelibrary/api/storage/command/StorageCommandLine.java b/src/main/java/com/pixelgamelibrary/api/storage/command/StorageCommandLine.java index cafe8e7..83fc4c9 100644 --- a/src/main/java/com/pixelgamelibrary/api/storage/command/StorageCommandLine.java +++ b/src/main/java/com/pixelgamelibrary/api/storage/command/StorageCommandLine.java @@ -50,7 +50,7 @@ public class StorageCommandLine { * @return the command line prompt string */ public String getCommandLineStart() { - return user + "@" + hostname + ":" + storage.pwd() + "$ "; + return user + "@" + hostname + ":" + storage.printWorkingDirectory() + "$ "; } /** @@ -106,7 +106,7 @@ public class StorageCommandLine { ))); addCommand("ls", arguments -> provideOutput(result -> result.setOutput(storage - .ls() + .list() .stream() .map(l -> { String[] a = l.split("/"); @@ -114,12 +114,12 @@ public class StorageCommandLine { }) .collect(Collectors.joining("\n"))))); - addCommand("pwd", arguments -> provideOutput(result -> result.setOutput(storage.pwd()))); + addCommand("pwd", arguments -> provideOutput(result -> result.setOutput(storage.printWorkingDirectory()))); addCommand("depth", arguments -> provideOutput(result -> result.setOutput(storage.depth()))); addCommand("mkdir", arguments -> provideOutput(result -> { - String string = storage.mkdirmore(extractArguments(arguments)); + String string = storage.createDirectories(extractArguments(arguments)); if (string.isEmpty()) { result.setOutput("New directory was successfully created"); } else { @@ -214,7 +214,7 @@ public class StorageCommandLine { } break; case "readtext": - String rr = storage.readtext(argument1.get()); + String rr = storage.readString(argument1.get()); if (rr != null) { finalResult.setOutput("Text file was successfully loaded" + "\n\n" + rr); } else { @@ -222,7 +222,7 @@ public class StorageCommandLine { } break; case "savetext": - String result = storage.savetext(argument1.get(), argument2.get()); + String result = storage.writeString(argument1.get(), argument2.get()); if (result.isEmpty()) { finalResult.setOutput("Text file was successfully saved"); } else { @@ -230,7 +230,7 @@ public class StorageCommandLine { } break; case "cd": - String rrr = argument1.isEmpty() ? storage.cd() : storage.cd(argument1.get()); + String rrr = argument1.isEmpty() ? storage.changeDirectory() : storage.changeDirectory(argument1.get()); if (rrr.isEmpty()) { finalResult.setOutput("Changing working directory was successfully created"); } else { diff --git a/src/main/java/com/pixelgamelibrary/api/storage/map/MapFileType.java b/src/main/java/com/pixelgamelibrary/api/storage/map/MapFileType.java index 0468c66..9d666c6 100644 --- a/src/main/java/com/pixelgamelibrary/api/storage/map/MapFileType.java +++ b/src/main/java/com/pixelgamelibrary/api/storage/map/MapFileType.java @@ -20,16 +20,19 @@ package com.pixelgamelibrary.api.storage.map; +import com.pixelgamelibrary.api.storage.FileType; import com.pixelgamelibrary.api.storage.StorageException; +import static com.pixelgamelibrary.api.storage.FileType.DIRECTORY; +import static com.pixelgamelibrary.api.storage.FileType.FILE; /** - * Enum representing the types of files or directories in the map. - * It can either be a FILE or a DIRECTORY. * * @author robertvokac */ -public enum MapFileType { - FILE, DIRECTORY; +public class MapFileType { + private MapFileType() { + //Not meant to be instantiated. + } /** * Determines the MapFileType based on the value associated with the specified key in the map. @@ -40,7 +43,7 @@ public enum MapFileType { * @return the MapFileType corresponding to the value in the map * @throws StorageException if the key is not present in the map or if the value does not match FILE or DIRECTORY */ - public static MapFileType ofKey(String key, SimpleMap map) { + public static FileType ofKey(String key, SimpleMap map) { // Check if the map contains the specified key if (!map.contains(key)) { throw new StorageException("Map does not contain key: " + key); diff --git a/src/main/java/com/pixelgamelibrary/api/storage/map/MapStorage.java b/src/main/java/com/pixelgamelibrary/api/storage/map/MapStorage.java index 1a04063..d25350c 100644 --- a/src/main/java/com/pixelgamelibrary/api/storage/map/MapStorage.java +++ b/src/main/java/com/pixelgamelibrary/api/storage/map/MapStorage.java @@ -21,6 +21,8 @@ package com.pixelgamelibrary.api.storage.map; import com.pixelgamelibrary.api.Pixel; import com.pixelgamelibrary.api.Platform; +import com.pixelgamelibrary.api.storage.FileType; +import com.pixelgamelibrary.api.storage.RegularFileType; import com.pixelgamelibrary.api.storage.StorageException; import com.pixelgamelibrary.api.storage.Storage; import java.util.List; @@ -63,7 +65,7 @@ public class MapStorage implements Storage { } else { map.putString("system.compression", mapStorageCompression.name()); } - mkdir("/"); // Initialize the root directory + createDirectory("/"); // Initialize the root directory } private String workingDirectory = "/"; @@ -93,7 +95,7 @@ public class MapStorage implements Storage { private static final String BINARYFILE = "BINARYFILE"; @Override - public String cd(String path) { + public String changeDirectory(String path) { // Change directory to the specified path String absolutePath = path.equals(TWO_DOTS) ? getParentPath(workingDirectory) : convertToAbsolutePathIfNeeded(path); @@ -102,7 +104,7 @@ public class MapStorage implements Storage { logError(msg); return msg; } - if (!isdir(absolutePath)) { + if (!isDirectory(absolutePath)) { final String msg = "Path is not directory: " + absolutePath; logError(msg); return msg; @@ -113,7 +115,7 @@ public class MapStorage implements Storage { } @Override - public String mkdir(String path) { + public String createDirectory(String path) { if (path.equals("system")) { String msg = "Creating directory system is not allowed"; logError(msg); @@ -132,7 +134,7 @@ public class MapStorage implements Storage { logError(msg); return msg; } - if (!path.equals(SLASH) && !isdir(parentPath)) { + if (!path.equals(SLASH) && !isDirectory(parentPath)) { var msg = "Cannot create new directory, because parent path is not directory: " + parentPath; logError(msg); return msg; @@ -142,7 +144,7 @@ public class MapStorage implements Storage { logError(msg); return msg; } - map.putString(absolutePath, MapFileType.DIRECTORY + EIGHT_COLONS); + map.putString(absolutePath, FileType.DIRECTORY + EIGHT_COLONS); return ""; } @@ -172,7 +174,7 @@ public class MapStorage implements Storage { } @Override - public String pwd() { + public String printWorkingDirectory() { // Return the current working directory return workingDirectory; } @@ -189,7 +191,7 @@ public class MapStorage implements Storage { } @Override - public List ls(String path) { + public List list(String path) { // List all files and directories at the specified path int currentDepth = depth(path); return map @@ -214,7 +216,7 @@ public class MapStorage implements Storage { logError(msg); return msg; } - if (!isdir(parentPath)) { + if (!isDirectory(parentPath)) { var msg = "Cannot create new file, because parent path is not directory: " + parentPath; logError(msg); return msg; @@ -224,15 +226,15 @@ public class MapStorage implements Storage { logError(msg); return msg; } - map.putString(absolutePath, MapFileType.FILE + EIGHT_COLONS + content); + map.putString(absolutePath, FileType.FILE + EIGHT_COLONS + content); return ""; } @Override - public boolean rm(String path) { + public boolean remove(String path) { String absolutePath = convertToAbsolutePathIfNeeded(path); - if (map.contains(absolutePath) && isdir(path)) { + if (map.contains(absolutePath) && isDirectory(path)) { logError("Removing directories is not yet supported"); return false; } @@ -248,12 +250,12 @@ public class MapStorage implements Storage { } @Override - public String cp(String source, String target) { + public String copy(String source, String target) { return moveOrCp(source, target, false, true); } @Override - public String mv(String source, String target) { + public String move(String source, String target) { return moveOrCp(source, target, true, false); } @@ -282,7 +284,7 @@ public class MapStorage implements Storage { logError(msg); return msg; } - if (isdir(absolutePathSource)) { + if (isDirectory(absolutePathSource)) { final String msg = "absolutePathSource is directory: " + absolutePathSource; logError(msg); return msg; @@ -292,7 +294,7 @@ public class MapStorage implements Storage { logError(msg); return msg; } - if (!isdir(targetParentPath)) { + if (!isDirectory(targetParentPath)) { final String msg = "targetParentPath is not directory: " + absolutePathSource; logError(msg); return msg; @@ -313,14 +315,14 @@ public class MapStorage implements Storage { } @Override - public String readtext(String path) { + public String readString(String path) { // Read the text content of a file at the specified path String absolutePath = convertToAbsolutePathIfNeeded(path); if (!exists(absolutePath)) { logError("absolutePathSource does not exist: " + absolutePath); return null; } - if (isdir(absolutePath)) { + if (isDirectory(absolutePath)) { logError("absolutePathSource is directory: " + absolutePath); return null; } @@ -329,10 +331,10 @@ public class MapStorage implements Storage { } @Override - public byte[] readbin(String path) { + public byte[] readBytes(String path) { // Read binary data from a file at the specified path String absolutePath = convertToAbsolutePathIfNeeded(path); - String text = readtext(absolutePath); + String text = readString(absolutePath); if (!text.startsWith(BINARYFILE)) { logError("File is not binary: " + absolutePath); return null; @@ -346,16 +348,16 @@ public class MapStorage implements Storage { } @Override - public String savetext(String name, String text) { + public String writeString(String name, String text) { return touch(name, text); } @Override - public String savebin(String name, byte[] data) { + public String writeBytes(String name, byte[] data) { if (this.mapStorageCompression != MapStorageCompression.NONE) { data = Pixel.utils().compress(data, mapStorageCompression.name()); } - return savetext(name, BINARYFILE + Pixel.utils().encodeToBase64(data)); + return writeString(name, BINARYFILE + Pixel.utils().encodeToBase64(data)); } @Override @@ -365,21 +367,22 @@ public class MapStorage implements Storage { } @Override - public boolean isfile(String name) { + public boolean isFile(String name) { // Check if the path is a file - return filetype(name) == MapFileType.FILE; + return type(name) == FileType.FILE; } @Override - public boolean isdir(String name) { + public boolean isDirectory(String name) { if (name.equals(SLASH)) { return true; } // Check if the path is a directory - return filetype(name) == MapFileType.DIRECTORY; + return type(name) == FileType.DIRECTORY; } - public MapFileType filetype(String name) { + @Override + public FileType type(String name) { // Get the file type for the given path return MapFileType.ofKey(convertToAbsolutePathIfNeeded(name), map); } @@ -405,7 +408,7 @@ public class MapStorage implements Storage { } @Override - public boolean rmdir(String dirname) { + public boolean removeDirectory(String dirname) { // Remove directory is not supported throw new UnsupportedOperationException("Not supported yet."); } @@ -418,4 +421,14 @@ public class MapStorage implements Storage { private void logError(String msg) { Pixel.app().error(msg); } + + @Override + public RegularFileType getRegularFileType(String path) { + if(isDirectory(path)) { + throw new UnsupportedOperationException("Cannot find out RegularFileType, because this is a directory: " + path); + }; + String text = readString(path); + + return text.startsWith(BINARYFILE) ? RegularFileType.BINARY : RegularFileType.TEXT; + } } diff --git a/src/test/java/com/pixelgamelibrary/api/storage/FileHandleImplTest.java b/src/test/java/com/pixelgamelibrary/api/storage/FileHandleImplTest.java new file mode 100644 index 0000000..ba6ff39 --- /dev/null +++ b/src/test/java/com/pixelgamelibrary/api/storage/FileHandleImplTest.java @@ -0,0 +1,170 @@ +package com.pixelgamelibrary.api.storage; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class FileHandleImplTest { + + private Storage mockStorage; + private FileHandleImpl fileHandle; + + @BeforeEach + public void setUp() { + mockStorage = mock(Storage.class); + fileHandle = new FileHandleImpl(mockStorage, "/example/path/file.txt"); + } + + @Test + public void testType() { + // Arrange + when(mockStorage.type("/example/path/file.txt")).thenReturn(FileType.FILE); + + // Act + FileType result = fileHandle.type(); + + // Assert + assertEquals(FileType.FILE, result); + } + + @Test + public void testPath() { + assertEquals("/example/path/file.txt", fileHandle.path()); + } + + @Test + public void testName() { + assertEquals("file.txt", fileHandle.name()); + } + + @Test + public void testExtension() { + assertEquals("txt", fileHandle.extension()); + } + + @Test + public void testNameWithoutExtension() { + assertEquals("file", fileHandle.nameWithoutExtension()); + } + + @Test + public void testList() { + // Arrange + when(mockStorage.list("/example/path/file.txt")).thenReturn(Arrays.asList("child1", "child2")); + + // Act + List files = fileHandle.list(); + + // Assert + assertEquals(2, files.size()); + assertEquals("child1", files.get(0).name()); + assertEquals("child2", files.get(1).name()); + } + + @Test + public void testChild() { + // Act + FileHandle child = fileHandle.child("child.txt"); + + // Assert + assertEquals("/example/path/file.txt/child.txt", child.path()); + } + + @Test + public void testSibling() { + // Act + FileHandle sibling = fileHandle.sibling("sibling.txt"); + + // Assert + assertEquals("/example/path/sibling.txt", sibling.path()); + } + + @Test + public void testParent() { + // Act + FileHandle parent = fileHandle.parent(); + + // Assert + assertEquals("/example/path", parent.path()); + } + + @Test + public void testMkdir() { + // Arrange + when(mockStorage.createDirectory("/example/path/file.txt")).thenReturn(""); + + // Act + boolean result = fileHandle.mkdir(); + + // Assert + assertTrue(result); + } + + @Test + public void testExists() { + // Arrange + when(mockStorage.exists("/example/path/file.txt")).thenReturn(true); + + // Act + boolean result = fileHandle.exists(); + + // Assert + assertTrue(result); + } + + @Test + public void testDelete() { + // Arrange + when(mockStorage.remove("/example/path/file.txt")).thenReturn(true); + + // Act + boolean result = fileHandle.delete(); + + // Assert + assertTrue(result); + } + + @Test + public void testCopyTo() { + // Arrange + FileHandleImpl destination = new FileHandleImpl(mockStorage, "/destination/path"); + when(mockStorage.copy("/example/path/file.txt", "/destination/path")).thenReturn(""); + + // Act + boolean result = fileHandle.copyTo(destination); + + // Assert + assertTrue(result); + } + + @Test + public void testMoveTo() { + // Arrange + FileHandleImpl destination = new FileHandleImpl(mockStorage, "/destination/path"); + when(mockStorage.move("/example/path/file.txt", "/destination/path")).thenReturn(""); + + // Act + boolean result = fileHandle.moveTo(destination); + + // Assert + assertTrue(result); + } + + @Test + public void testLength() { + // Arrange + when(mockStorage.getRegularFileType("/example/path/file.txt")).thenReturn(RegularFileType.TEXT); + when(mockStorage.readString("/example/path/file.txt")).thenReturn("Hello, World!"); + + // Act + long length = fileHandle.length(); + + // Assert + assertEquals(13, length); + } +} diff --git a/src/test/java/com/pixelgamelibrary/api/storage/command/StorageCommandLineTest.java b/src/test/java/com/pixelgamelibrary/api/storage/command/StorageCommandLineTest.java index 165b609..de5edf2 100644 --- a/src/test/java/com/pixelgamelibrary/api/storage/command/StorageCommandLineTest.java +++ b/src/test/java/com/pixelgamelibrary/api/storage/command/StorageCommandLineTest.java @@ -19,8 +19,8 @@ class StorageCommandLineTest { @BeforeEach void setUp() { mockStorage = mock(Storage.class); - when(mockStorage.pwd()).thenReturn("/mock/path"); - when(mockStorage.ls()).thenReturn(Arrays.asList("file1.txt", "file2.txt")); + when(mockStorage.printWorkingDirectory()).thenReturn("/mock/path"); + when(mockStorage.list()).thenReturn(Arrays.asList("file1.txt", "file2.txt")); commandLine = new StorageCommandLine("user", "hostname", mockStorage); } @@ -97,14 +97,14 @@ class StorageCommandLineTest { @Test void testExecuteMkdirCommand() { - when(mockStorage.mkdirmore(any())).thenReturn(""); + when(mockStorage.createDirectories(any())).thenReturn(""); StorageCommandResult result = commandLine.execute("mkdir newDir"); assertEquals("New directory was successfully created", result.getOutput().trim()); } @Test void testExecuteCdCommand() { - when(mockStorage.cd(any())).thenReturn(""); + when(mockStorage.changeDirectory(any())).thenReturn(""); StorageCommandResult result = commandLine.execute("cd newDir"); assertEquals("Changing working directory was successfully created", result.getOutput().trim()); } @@ -118,14 +118,14 @@ class StorageCommandLineTest { @Test void testExecuteReadtextCommand() { - when(mockStorage.readtext(any())).thenReturn("file content"); + when(mockStorage.readString(any())).thenReturn("file content"); StorageCommandResult result = commandLine.execute("readtext file.txt"); assertEquals("Text file was successfully loaded\n\nfile content", result.getOutput().trim()); } @Test void testExecuteSavetextCommand() { - when(mockStorage.savetext(any(), any())).thenReturn(""); + when(mockStorage.writeString(any(), any())).thenReturn(""); StorageCommandResult result = commandLine.execute("savetext file.txt content"); assertEquals("Text file was successfully saved", result.getOutput().trim()); } diff --git a/src/test/java/com/pixelgamelibrary/api/storage/map/MapStorageTest.java b/src/test/java/com/pixelgamelibrary/api/storage/map/MapStorageTest.java index d56fc4a..da33b2d 100644 --- a/src/test/java/com/pixelgamelibrary/api/storage/map/MapStorageTest.java +++ b/src/test/java/com/pixelgamelibrary/api/storage/map/MapStorageTest.java @@ -107,7 +107,7 @@ public class MapStorageTest { when(mockMap.contains("/")).thenReturn(true); // Simulate no directory exists when(mockMap.contains("/newDir")).thenReturn(false); // Simulate no directory exists - String result = mapStorage.mkdir("/newDir"); + String result = mapStorage.createDirectory("/newDir"); assertEquals("", result); // Success should return an empty string verify(mockMap).putString("/newDir", "DIRECTORY::::::::"); @@ -118,7 +118,7 @@ public class MapStorageTest { when(mockMap.contains("/")).thenReturn(true); // Root irectory already exists when(mockMap.contains("/newDir")).thenReturn(true); // Directory already exists - String result = mapStorage.mkdir("/newDir"); + String result = mapStorage.createDirectory("/newDir"); assertEquals("Cannot create new directory, because path already exists: /newDir", result); } @@ -130,7 +130,7 @@ public class MapStorageTest { when(mockMap.getString("/")).thenReturn("DIRECTORY::::::::"); when(mockMap.getString("/newDir")).thenReturn("DIRECTORY::::::::"); - String result = mapStorage.cd("/newDir"); + String result = mapStorage.changeDirectory("/newDir"); assertEquals("", result); // Success should return an empty string } @@ -139,7 +139,7 @@ public class MapStorageTest { public void testCdPathDoesNotExist() { when(mockMap.contains("/nonExistent")).thenReturn(false); - String result = mapStorage.cd("/nonExistent"); + String result = mapStorage.changeDirectory("/nonExistent"); assertEquals("Path does not exist: /nonExistent", result); } @@ -170,7 +170,7 @@ public class MapStorageTest { when(mockMap.contains("/file.txt")).thenReturn(true); when(mockMap.getString("/file.txt")).thenReturn("FILE::::::::Hello World"); - String content = mapStorage.readtext("/file.txt"); + String content = mapStorage.readString("/file.txt"); assertEquals("Hello World", content); } @@ -179,7 +179,7 @@ public class MapStorageTest { public void testReadTextFileDoesNotExist() { when(mockMap.contains("/file.txt")).thenReturn(false); - String content = mapStorage.readtext("/file.txt"); + String content = mapStorage.readString("/file.txt"); assertNull(content); } @@ -189,7 +189,7 @@ public class MapStorageTest { when(mockMap.contains("/file.txt")).thenReturn(true); when(mockMap.getString("/file.txt")).thenReturn("FILE::::::::Hello World"); - boolean result = mapStorage.rm("/file.txt"); + boolean result = mapStorage.remove("/file.txt"); assertTrue(result); // File successfully removed verify(mockMap).remove("/file.txt"); @@ -199,7 +199,7 @@ public class MapStorageTest { public void testRmFileDoesNotExist() { when(mockMap.contains("/file.txt")).thenReturn(false); - boolean result = mapStorage.rm("/file.txt"); + boolean result = mapStorage.remove("/file.txt"); assertFalse(result); // File does not exist, so removal fails } @@ -215,7 +215,7 @@ public class MapStorageTest { public void testLs() { when(mockMap.keyList()).thenReturn(List.of("/dir/file1", "/dir/file2", "/dir/subdir/file3")); - List files = mapStorage.ls("/dir"); + List files = mapStorage.list("/dir"); assertEquals(2, files.size()); assertTrue(files.contains("/dir/file1"));