Bug 14: Refactor, improve and finish the Storage api

This commit is contained in:
Robert Vokac 2024-09-14 08:16:27 +02:00 committed by Robert Vokac
parent 60a94ab1ec
commit b12309056f
Signed by: robertvokac
GPG Key ID: FB9CE8E20AADA55F
5 changed files with 56 additions and 20 deletions

View File

@ -19,7 +19,9 @@
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
package com.pixelgamelibrary.api.interfaces; package com.pixelgamelibrary.api.interfaces;
import com.badlogic.gdx.utils.Base64Coder; import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* *
@ -38,4 +40,10 @@ public interface UtilsI {
} }
String encodeToBase64(byte[] data); String encodeToBase64(byte[] data);
List<String> listSupportedCompressions();
byte[] compress(byte[] data, String compression, Map<String, String> arguments);
default byte[] compress(byte[] data, String compression) {
return compress(data, compression, new HashMap<>());
}
byte[] decompress(byte[] data, String compression);
} }

View File

@ -47,6 +47,9 @@ public enum MapFileType {
} }
// Retrieve the value associated with the key // Retrieve the value associated with the key
String value = map.getString(key); String value = map.getString(key);
if(value == null) {
throw new StorageException("Value is null for key: " + key);
}
// Determine the MapFileType based on the value // Determine the MapFileType based on the value
if (value.startsWith(FILE.name())) { if (value.startsWith(FILE.name())) {
return FILE; return FILE;

View File

@ -17,10 +17,8 @@
// <https://www.gnu.org/licenses/> or write to the Free Software // <https://www.gnu.org/licenses/> or write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
package com.pixelgamelibrary.api.storage.map; package com.pixelgamelibrary.api.storage.map;
import com.badlogic.gdx.Gdx;
import com.pixelgamelibrary.api.Pixel; import com.pixelgamelibrary.api.Pixel;
import com.pixelgamelibrary.api.Platform; import com.pixelgamelibrary.api.Platform;
import com.pixelgamelibrary.api.storage.StorageException; import com.pixelgamelibrary.api.storage.StorageException;
@ -31,7 +29,7 @@ import java.util.stream.Collectors;
/** /**
* Implementation of the Storage interface for managing a map-based file system. * Implementation of the Storage interface for managing a map-based file system.
* Provides methods to interact with files and directories stored in a map. * Provides methods to interact with files and directories stored in a map.
* *
* @author robertvokac * @author robertvokac
*/ */
public class MapStorage implements Storage { public class MapStorage implements Storage {
@ -40,23 +38,31 @@ public class MapStorage implements Storage {
private final MapStorageCompression mapStorageCompression; private final MapStorageCompression mapStorageCompression;
/** /**
* Constructs a MapStorage instance with the specified map and default compression. * Constructs a MapStorage instance with the specified map and default
* * compression.
*
* @param mapIn the map to be used for storage * @param mapIn the map to be used for storage
*/ */
public MapStorage(SimpleMap mapIn) { public MapStorage(SimpleMap mapIn) {
this(mapIn, MapStorageCompression.NONE); this(mapIn, MapStorageCompression.LZMA);
} }
/** /**
* Constructs a MapStorage instance with the specified map and compression. * Constructs a MapStorage instance with the specified map and compression.
* *
* @param mapIn the map to be used for storage * @param mapIn the map to be used for storage
* @param mapStorageCompressionIn the compression method to be used * @param mapStorageCompressionIn the compression method to be used
*/ */
public MapStorage(SimpleMap mapIn, MapStorageCompression mapStorageCompressionIn) { public MapStorage(SimpleMap mapIn, MapStorageCompression mapStorageCompressionIn) {
this.map = mapIn; this.map = mapIn;
this.mapStorageCompression = mapStorageCompressionIn; this.mapStorageCompression = mapStorageCompressionIn;
if (map.contains("system.compression")) {
if (!map.getString("system.compression").equals(this.mapStorageCompression.name())) {
throw new StorageException("Fatal error, compression method passed to the constructor is different, than the compression method in the map (key system.compression).");
}
} else {
map.putString("system.compression", mapStorageCompression.name());
}
mkdir("/"); // Initialize the root directory mkdir("/"); // Initialize the root directory
} }
@ -70,7 +76,7 @@ public class MapStorage implements Storage {
/** /**
* Converts a path to an absolute path if it is not already absolute. * Converts a path to an absolute path if it is not already absolute.
* *
* @param path the path to convert * @param path the path to convert
* @return the absolute path * @return the absolute path
*/ */
@ -80,7 +86,7 @@ public class MapStorage implements Storage {
} }
return workingDirectory + (workingDirectory.equals("/") ? "" : SLASH) + path; return workingDirectory + (workingDirectory.equals("/") ? "" : SLASH) + path;
} }
private static final String TWO_DOTS = ".."; private static final String TWO_DOTS = "..";
private static final String SLASH = "/"; private static final String SLASH = "/";
private static final String EIGHT_COLONS = "::::::::"; private static final String EIGHT_COLONS = "::::::::";
@ -108,8 +114,13 @@ public class MapStorage implements Storage {
@Override @Override
public String mkdir(String path) { public String mkdir(String path) {
if (path.equals("system")) {
String msg = "Creating directory system is not allowed";
logError(msg);
return msg;
}
// Create a new directory at the specified path // Create a new directory at the specified path
if(path.isEmpty()) { if (path.isEmpty()) {
String msg = "Missing argument"; String msg = "Missing argument";
logError(msg); logError(msg);
return msg; return msg;
@ -137,7 +148,7 @@ public class MapStorage implements Storage {
/** /**
* Retrieves the parent path of the given path. * Retrieves the parent path of the given path.
* *
* @param path the path to get the parent of * @param path the path to get the parent of
* @return the parent path * @return the parent path
* @throws StorageException if the path is null or empty * @throws StorageException if the path is null or empty
@ -219,8 +230,14 @@ public class MapStorage implements Storage {
@Override @Override
public boolean rm(String path) { public boolean rm(String path) {
// Remove the file or directory at the specified path
String absolutePath = convertToAbsolutePathIfNeeded(path); String absolutePath = convertToAbsolutePathIfNeeded(path);
if (map.contains(absolutePath) && isdir(path)) {
logError("Removing directories is not yet supported");
return false;
}
// Remove the file or directory at the specified path
if (!map.contains(absolutePath)) { if (!map.contains(absolutePath)) {
logError("Cannot remove file, because it does not exist: " + absolutePath); logError("Cannot remove file, because it does not exist: " + absolutePath);
@ -242,7 +259,7 @@ public class MapStorage implements Storage {
/** /**
* Moves or copies a file from the source path to the target path. * Moves or copies a file from the source path to the target path.
* *
* @param source the source path * @param source the source path
* @param target the target path * @param target the target path
* @param move whether to move the file (true) or copy it (false) * @param move whether to move the file (true) or copy it (false)
@ -321,7 +338,11 @@ public class MapStorage implements Storage {
return null; return null;
} }
text = text.substring(BINARYFILE.length()); text = text.substring(BINARYFILE.length());
return Pixel.utils().decodeBase64AsByteArray(text); byte[] data = Pixel.utils().decodeBase64AsByteArray(text);
if (this.mapStorageCompression != MapStorageCompression.NONE) {
data = Pixel.utils().decompress(data, mapStorageCompression.name());
}
return data;
} }
@Override @Override
@ -331,6 +352,9 @@ public class MapStorage implements Storage {
@Override @Override
public String savebin(String name, byte[] data) { public String savebin(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 savetext(name, BINARYFILE + Pixel.utils().encodeToBase64(data));
} }
@ -348,7 +372,7 @@ public class MapStorage implements Storage {
@Override @Override
public boolean isdir(String name) { public boolean isdir(String name) {
if(name.equals(SLASH)) { if (name.equals(SLASH)) {
return true; return true;
} }
// Check if the path is a directory // Check if the path is a directory
@ -364,7 +388,7 @@ public class MapStorage implements Storage {
public String debug() { public String debug() {
// Return a debug string of all keys and their values // Return a debug string of all keys and their values
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for(String key: map.keyList()) { for (String key : map.keyList()) {
sb sb
.append(key) .append(key)
.append("=") .append("=")
@ -383,12 +407,12 @@ public class MapStorage implements Storage {
@Override @Override
public boolean rmdir(String dirname) { public boolean rmdir(String dirname) {
// Remove directory is not supported // Remove directory is not supported
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
} }
/** /**
* Logs an error message using the Pixel application logging mechanism. * Logs an error message using the Pixel application logging mechanism.
* *
* @param msg the error message to log * @param msg the error message to log
*/ */
private void logError(String msg) { private void logError(String msg) {

View File

@ -24,5 +24,5 @@ package com.pixelgamelibrary.api.storage.map;
* @author robertvokac * @author robertvokac
*/ */
public enum MapStorageCompression { public enum MapStorageCompression {
NONE; NONE, LZMA;
} }

View File

@ -187,6 +187,7 @@ public class MapStorageTest {
@Test @Test
public void testRmFile() { public void testRmFile() {
when(mockMap.contains("/file.txt")).thenReturn(true); 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.rm("/file.txt");