From a04592d7276c8cbc4d446e183cd7cca1ddbb0537 Mon Sep 17 00:00:00 2001 From: Robert Vokac Date: Sat, 14 Sep 2024 13:26:03 +0200 Subject: [PATCH] Bug 16: Implement the Desktop/Android implementation of Storage api --- .../backend/libgdx/AppLibGDXImpl.java | 29 ++- .../libgdx/storage/AndroidStorage.java | 4 +- .../libgdx/storage/DesktopAndroidStorage.java | 199 ++++++++++++++---- .../libgdx/storage/DesktopStorage.java | 6 +- .../libgdx/storage/PreferencesStorage.java | 3 +- .../libgdx/storage/StorageFactory.java | 14 +- 6 files changed, 198 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/pixelgamelibrary/backend/libgdx/AppLibGDXImpl.java b/src/main/java/com/pixelgamelibrary/backend/libgdx/AppLibGDXImpl.java index 78cc088..2389c94 100644 --- a/src/main/java/com/pixelgamelibrary/backend/libgdx/AppLibGDXImpl.java +++ b/src/main/java/com/pixelgamelibrary/backend/libgdx/AppLibGDXImpl.java @@ -34,7 +34,10 @@ import com.pixelgamelibrary.api.interfaces.AppI; */ public class AppLibGDXImpl implements AppI { - + private static final String DEFAULT_APP_NAME = "pixel-app"; + + private String appName = null; + @Override public void exit() { throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody @@ -54,6 +57,7 @@ public class AppLibGDXImpl implements AppI { throw new PixelException("Unsupported platform: " + applicationType); } } + @Override public void log(String msg) { Application app = Gdx.app; @@ -79,4 +83,27 @@ public class AppLibGDXImpl implements AppI { } } + @Override + public void warn(String msg) { + log(msg); + } + + @Override + public void setAppName(String appNameIn) { + if (appNameIn != null) { + throw new UnsupportedOperationException("App name was already set."); + } + this.appName = appNameIn; + } + + @Override + public String getAppName() { + return isAppNameSet() ? appName : DEFAULT_APP_NAME; + } + + @Override + public boolean isAppNameSet() { + return appName != null; + } + } diff --git a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/AndroidStorage.java b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/AndroidStorage.java index 24cc1ec..0cdd202 100644 --- a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/AndroidStorage.java +++ b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/AndroidStorage.java @@ -27,9 +27,11 @@ import com.pixelgamelibrary.api.Platform; */ public class AndroidStorage extends DesktopAndroidStorage { - public AndroidStorage() { + public AndroidStorage(String storageName) { + super(storageName); } + @Override public Platform getPlatform() { return Platform.ANDROID; } diff --git a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopAndroidStorage.java b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopAndroidStorage.java index 7d0037b..4ae58fe 100644 --- a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopAndroidStorage.java +++ b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopAndroidStorage.java @@ -19,11 +19,17 @@ /////////////////////////////////////////////////////////////////////////////////////////////// package com.pixelgamelibrary.backend.libgdx.storage; -import com.pixelgamelibrary.api.Platform; +import com.badlogic.gdx.Gdx; +import com.pixelgamelibrary.api.Pixel; import com.pixelgamelibrary.api.storage.FileType; import com.pixelgamelibrary.api.storage.RegularFileType; import com.pixelgamelibrary.api.storage.Storage; +import com.pixelgamelibrary.api.storage.StorageException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * @@ -31,115 +37,220 @@ import java.util.List; */ public abstract class DesktopAndroidStorage implements Storage { - public DesktopAndroidStorage() { - } + private String workingDirectory = "/"; + private final String storageName; - @Override - public Platform getPlatform() { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public DesktopAndroidStorage(String storageName) { + if (storageName == null || storageName.trim().isEmpty()) { + var msg = "storageName == null || storageName.trim().isEmpty()"; + Pixel.app().error(msg); + throw new StorageException(msg); + } + this.storageName = storageName; + com.badlogic.gdx.files.FileHandle rootFileHandle = createLibGdxFileHandle("/"); + if (!rootFileHandle.exists()) { + rootFileHandle.mkdirs(); + } } @Override public String changeDirectory(String path) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + com.badlogic.gdx.files.FileHandle fh = createLibGdxFileHandle(path); + if (!fh.exists()) { + var msg = "Directory does not exist: " + path; + Pixel.app().error(msg); + return msg; + } + workingDirectory = path; + return ""; + + } + + private com.badlogic.gdx.files.FileHandle createLibGdxFileHandle(String path) { + if (path.equals("/")) { + return Gdx.files.local(storageName); + } else { + return Gdx.files.local(storageName + "/" + path); + } + } @Override - public String createDirectory(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public String createDirectory(String path) { + var dir = createLibGdxFileHandle(path); + if (dir.exists()) { + var msg = "Directory already exists: " + path; + Pixel.app().warn(msg); + return msg; + } else { + dir.mkdirs(); + return ""; + } } @Override public String printWorkingDirectory() { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + return workingDirectory; } @Override public List list(String path) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + path = convertToAbsolutePathIfNeeded(path); + return Arrays.asList(createLibGdxFileHandle(path).list()).stream().map(e -> e.path()).collect(Collectors.toList()); } @Override - public int depth(String path) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody - } - - @Override - public String touch(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public String touch(String path) { + path = convertToAbsolutePathIfNeeded(path); + createLibGdxFileHandle(path).writeString("", false); + return ""; } @Override - public boolean remove(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public boolean remove(String path) { + path = convertToAbsolutePathIfNeeded(path); + return createLibGdxFileHandle(path).delete(); } @Override public String copy(String source, String target) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + + source = convertToAbsolutePathIfNeeded(source); + target = convertToAbsolutePathIfNeeded(target); + createLibGdxFileHandle(source).copyTo(createLibGdxFileHandle(target)); + return ""; + } @Override public String move(String source, String target) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + source = convertToAbsolutePathIfNeeded(source); + target = convertToAbsolutePathIfNeeded(target); + createLibGdxFileHandle(source).moveTo(createLibGdxFileHandle(target)); + return ""; } @Override - public String readString(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public String readString(String path) { + + path = convertToAbsolutePathIfNeeded(path); + return createLibGdxFileHandle(path).readString(); } @Override - public byte[] readBytes(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public byte[] readBytes(String path) { + + try { + path = convertToAbsolutePathIfNeeded(path); + InputStream is = createLibGdxFileHandle(path).read(); + return is.readAllBytes(); + } catch (IOException ex) { + Pixel.app().error(ex.getMessage()); + throw new StorageException(ex.getMessage()); + } } @Override - public String writeString(String name, String text) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public String writeString(String path, String text) { + + path = convertToAbsolutePathIfNeeded(path); + createLibGdxFileHandle(path).writeString(text, false); + return ""; } @Override - public String writeBytes(String name, byte[] data) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public String writeBytes(String path, byte[] data) { + + path = convertToAbsolutePathIfNeeded(path); + createLibGdxFileHandle(path).writeBytes(data, false); + return ""; } @Override - public boolean exists(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public boolean exists(String path) { + + path = convertToAbsolutePathIfNeeded(path); + return createLibGdxFileHandle(path).exists(); } @Override - public boolean isFile(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public boolean isFile(String path) { + + path = convertToAbsolutePathIfNeeded(path); + return !createLibGdxFileHandle(path).isDirectory(); } @Override - public boolean isDirectory(String name) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public boolean isDirectory(String path) { + + path = convertToAbsolutePathIfNeeded(path); + return createLibGdxFileHandle(path).isDirectory(); } @Override public String debug() { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + + return printFileTree(createLibGdxFileHandle(SLASH)); } - + + public String printFileTree(com.badlogic.gdx.files.FileHandle dir) { + StringBuilder sb = new StringBuilder(); + printFileTree(dir, "", sb); + return sb.toString(); + } + + private void printFileTree(com.badlogic.gdx.files.FileHandle file, String indent, StringBuilder sb) { + // Add the current file or folder + sb.append(indent).append(file.name()).append("\n"); + + if (file.isDirectory()) { + // If it's a directory, get its contents and recursively process them + com.badlogic.gdx.files.FileHandle[] children = file.list(); + for (com.badlogic.gdx.files.FileHandle child : children) { + printFileTree(child, indent + " ", sb); // Indentation for subfiles + } + } + } + @Override public void flush() { //nothing to do } - + @Override - public boolean removeDirectory(String dirname) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + public boolean removeDirectory(String path) { + + path = convertToAbsolutePathIfNeeded(path); + return createLibGdxFileHandle(path).deleteDirectory(); } - @Override + + @Override public FileType type(String path) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + + path = convertToAbsolutePathIfNeeded(path); + return isDirectory(path) ? FileType.DIRECTORY : FileType.FILE; } @Override public RegularFileType getRegularFileType(String path) { - throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + + path = convertToAbsolutePathIfNeeded(path); + return isTextFile(createLibGdxFileHandle(path)) ? RegularFileType.TEXT : RegularFileType.BINARY; } + + public static boolean isTextFile(com.badlogic.gdx.files.FileHandle file) { + try { + String content = file.readString(); + // Check if the content contains non-printable characters (indicating binary) + for (char c : content.toCharArray()) { + if (Character.isISOControl(c) && !Character.isWhitespace(c)) { + return false; // It's likely binary if it contains control characters + } + } + return true; + } catch (Exception e) { + return false; // Unable to read as text, so it's likely binary + } + } + } diff --git a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopStorage.java b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopStorage.java index eb0d77e..3099b7d 100644 --- a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopStorage.java +++ b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/DesktopStorage.java @@ -20,8 +20,6 @@ package com.pixelgamelibrary.backend.libgdx.storage; import com.pixelgamelibrary.api.Platform; -import com.pixelgamelibrary.api.storage.FileType; -import com.pixelgamelibrary.api.storage.RegularFileType; /** * @@ -29,9 +27,11 @@ import com.pixelgamelibrary.api.storage.RegularFileType; */ public class DesktopStorage extends DesktopAndroidStorage { - public DesktopStorage() { + public DesktopStorage(String storageName) { + super(storageName); } + @Override public Platform getPlatform() { return Platform.DESKTOP; } diff --git a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/PreferencesStorage.java b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/PreferencesStorage.java index 8e39ed0..310514a 100644 --- a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/PreferencesStorage.java +++ b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/PreferencesStorage.java @@ -30,12 +30,13 @@ import com.pixelgamelibrary.api.storage.map.MapStorage; */ public class PreferencesStorage extends MapStorage { + public Platform getPlatform() { return Platform.WEB; } public PreferencesStorage() { - this("pixel.libgdx.webGL.Local-Storage"); + this("com.pixelgamelibrary.backend.libgdx.storage.PreferencesStorage"); } public PreferencesStorage(String preferencesName) { diff --git a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/StorageFactory.java b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/StorageFactory.java index 5a9e336..a51a3e7 100644 --- a/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/StorageFactory.java +++ b/src/main/java/com/pixelgamelibrary/backend/libgdx/storage/StorageFactory.java @@ -19,7 +19,6 @@ /////////////////////////////////////////////////////////////////////////////////////////////// package com.pixelgamelibrary.backend.libgdx.storage; -import com.pixelgamelibrary.api.storage.map.MemoryStorage; import com.pixelgamelibrary.api.Pixel; import com.pixelgamelibrary.api.Platform; import com.pixelgamelibrary.api.storage.Storage; @@ -38,19 +37,20 @@ public class StorageFactory { public static Storage getStorage() { final Platform platform = Pixel.app().getPlatform(); +// if (storage == null) { +// storage = new PreferencesStorage(); +// }//todo fixme if (storage == null) { - storage = new PreferencesStorage(); - }//todo fixme - if (storage == null) { + final String appName = Pixel.app().getAppName(); if (platform.isDesktop()) { - storage = new DesktopStorage(); + storage = new DesktopStorage(appName); } if (platform.isAndroid()) { - storage = new AndroidStorage(); + storage = new AndroidStorage(appName); } if (platform.isWeb()) { - storage = new PreferencesStorage(); + storage = new PreferencesStorage(appName); } } if (storage == null) {