Skip to content

Commit

Permalink
Refactor JDB and JDocument for improved readability
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverSchlueter committed Sep 26, 2024
1 parent 9f02e8d commit 8d00224
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 146 deletions.
64 changes: 32 additions & 32 deletions src/main/java/de/oliver/fancylib/jdb/JDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
* The JDB class provides a simple JSON document-based storage system in a specified directory.
*/
public class JDB {

private final static Gson GSON = new GsonBuilder()
.serializeNulls()
.setPrettyPrinting()
.create();

private static final String FILE_EXTENSION = ".json";
private final @NotNull String basePath;
private final @NotNull File baseFolder;
private final @NotNull File baseDirectory;

/**
* Constructs a new JDB instance with the specified base path.
Expand All @@ -32,7 +32,7 @@ public class JDB {
*/
public JDB(@NotNull String basePath) {
this.basePath = basePath;
this.baseFolder = new File(basePath);
this.baseDirectory = new File(basePath);
}

/**
Expand All @@ -45,13 +45,11 @@ public JDB(@NotNull String basePath) {
* @throws IOException if an I/O error occurs during file reading
*/
public <T> T get(@NotNull String path, @NotNull Class<T> clazz) throws IOException {
File file = new File(baseFolder, basePath + path + ".json");
if (!file.exists()) {
File documentFile = new File(baseDirectory, createFilePath(path));
if (!documentFile.exists()) {
return null;
}

BufferedReader bufferedReader = Files.newBufferedReader(file.toPath());

BufferedReader bufferedReader = Files.newBufferedReader(documentFile.toPath());
return GSON.fromJson(bufferedReader, clazz);
}

Expand All @@ -63,14 +61,12 @@ public <T> T get(@NotNull String path, @NotNull Class<T> clazz) throws IOExcepti
* @throws IOException if an I/O error occurs during file reading
*/
public JDocument getDocument(@NotNull String path) throws IOException {
File file = new File(baseFolder, basePath + path + ".json");
if (!file.exists()) {
File documentFile = new File(baseDirectory, createFilePath(path));
if (!documentFile.exists()) {
return null;
}

BufferedReader bufferedReader = Files.newBufferedReader(file.toPath());

Map<String, Object> data = (Map<String, Object>) GSON.fromJson(bufferedReader, JDocument.class);
BufferedReader bufferedReader = Files.newBufferedReader(documentFile.toPath());
Map<String, Object> data = (Map<String, Object>) GSON.fromJson(bufferedReader, Map.class);
return new JDocument(data);
}

Expand All @@ -84,21 +80,18 @@ public JDocument getDocument(@NotNull String path) throws IOException {
* @throws IOException if an I/O error occurs during file reading
*/
public <T> List<T> getAll(@NotNull String path, @NotNull Class<T> clazz) throws IOException {
File folder = new File(baseFolder, basePath + path);
if (!folder.exists()) {
File directory = new File(baseDirectory, basePath + path);
if (!directory.exists()) {
return new ArrayList<>();
}

File[] files = folder.listFiles();
File[] files = directory.listFiles();
if (files == null) {
return new ArrayList<>();
}

List<T> documents = new ArrayList<>(files.length);
for (File file : files) {
documents.add(get(path + "/" + file.getName().replace(".json", ""), clazz));
documents.add(get(path + "/" + file.getName().replace(FILE_EXTENSION, ""), clazz));
}

return documents;
}

Expand All @@ -111,16 +104,13 @@ public <T> List<T> getAll(@NotNull String path, @NotNull Class<T> clazz) throws
* @throws IOException if an I/O error occurs during file writing
*/
public <T> void set(@NotNull String path, @NotNull T value) throws IOException {
File file = new File(baseFolder, basePath + path + ".json");

if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
File documentFile = new File(baseDirectory, createFilePath(path));
if (!documentFile.exists()) {
documentFile.getParentFile().mkdirs();
documentFile.createNewFile();
}

String json = GSON.toJson(value);

Files.write(file.toPath(), json.getBytes());
Files.write(documentFile.toPath(), json.getBytes());
}

/**
Expand All @@ -129,9 +119,19 @@ public <T> void set(@NotNull String path, @NotNull T value) throws IOException {
* @param path the relative path (excluding .json extension) where the document(s) are located
*/
public void delete(@NotNull String path) {
File file = new File(baseFolder, basePath + path + ".json");
if (file.exists()) {
file.delete();
File documentFile = new File(baseDirectory, createFilePath(path));
if (documentFile.exists()) {
documentFile.delete();
}
}

/**
* Creates the file path by appending the base path, provided path, and the file extension.
*
* @param path the relative path (excluding .json extension)
* @return the full file path
*/
private String createFilePath(@NotNull String path) {
return basePath + path + FILE_EXTENSION;
}
}
142 changes: 30 additions & 112 deletions src/main/java/de/oliver/fancylib/jdb/JDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
* Represents a document that holds a map of key-value pairs with support for nested keys.
*/
public class JDocument {

private final @NotNull Map<String, Object> data;

public JDocument(@NotNull Map<String, Object> data) {
Expand All @@ -24,27 +23,7 @@ public JDocument(@NotNull Map<String, Object> data) {
* @return the value associated with the given key, or null if the key is not found
*/
public Object get(String key) {
String[] parts = key.split("\\.");

Map<String, Object> current = data;
for (int i = 0; i < parts.length; i++) {
Object obj = current.get(parts[i]);
if (obj == null) {
return null;
}

if (i == parts.length - 1) {
return obj;
}

if (!(obj instanceof Map)) {
return null;
}

current = (Map<String, Object>) obj;
}

return null;
return getValue(key, Object.class);
}

/**
Expand All @@ -65,18 +44,8 @@ public boolean contains(String key) {
* is not found or the value is not a map
*/
public Set<String> getKeys(String key) {
Object obj = get(key);
if (obj == null) {
return new HashSet<>();
}

if (!isType(obj, Map.class)) {
return new HashSet<>();
}

Map<String, Object> map = (Map<String, Object>) data.get(key);

return map.keySet();
Map<String, Object> map = (Map<String, Object>) getValue(key, Map.class);
return map != null ? map.keySet() : new HashSet<>();
}

/**
Expand All @@ -86,12 +55,7 @@ public Set<String> getKeys(String key) {
* @return the string value associated with the given key, or an empty string if the key is not found or the value is not a string
*/
public String getString(String key) {
Object obj = get(key);
if (obj == null) {
return "";
}

return (String) obj;
return (String) getValueOrDefault(key, String.class, "");
}

/**
Expand All @@ -101,16 +65,7 @@ public String getString(String key) {
* @return the boolean value associated with the given key, or false if the key is not found or the value is not a boolean
*/
public boolean getBoolean(String key) {
Object obj = get(key);
if (obj == null) {
return false;
}

if (!isType(obj, Boolean.class)) {
return false;
}

return (boolean) obj;
return (boolean) getValueOrDefault(key, Boolean.class, false);
}

/**
Expand All @@ -120,16 +75,7 @@ public boolean getBoolean(String key) {
* @return the byte value associated with the given key, or 0 if the key is not found or the value is not a byte
*/
public byte getByte(String key) {
Object obj = get(key);
if (obj == null) {
return 0;
}

if (!isType(obj, Byte.class)) {
return 0;
}

return (byte) obj;
return (byte) getValueOrDefault(key, Byte.class, (byte) 0);
}

/**
Expand All @@ -139,16 +85,7 @@ public byte getByte(String key) {
* @return the short value associated with the given key, or 0 if the key is not found or the value is not a short
*/
public short getShort(String key) {
Object obj = get(key);
if (obj == null) {
return 0;
}

if (!isType(obj, Short.class)) {
return 0;
}

return (short) obj;
return (short) getValueOrDefault(key, Short.class, (short) 0);
}

/**
Expand All @@ -158,16 +95,7 @@ public short getShort(String key) {
* @return the integer value associated with the given key, or 0 if the key is not found or the value is not an integer
*/
public int getInt(String key) {
Object obj = get(key);
if (obj == null) {
return 0;
}

if (!isType(obj, Integer.class)) {
return 0;
}

return (int) obj;
return (int) getValueOrDefault(key, Integer.class, 0);
}

/**
Expand All @@ -177,36 +105,17 @@ public int getInt(String key) {
* @return the long value associated with the given key, or 0 if the key is not found or the value is not a long
*/
public long getLong(String key) {
Object obj = get(key);
if (obj == null) {
return 0;
}

if (!isType(obj, Long.class)) {
return 0;
}

return (long) obj;
return (long) getValueOrDefault(key, Long.class, 0L);
}

/**
* Retrieves a float value associated with the given key.
*
* @param key the dot-separated key used to locate the value in the document (e.g. "foo.bar.baz")
* @return the float value associated with the given key, or 0 if the key is not found
* or the value is not a float
* @return the float value associated with the given key, or 0 if the key is not found or the value is not a float
*/
public float getFloat(String key) {
Object obj = get(key);
if (obj == null) {
return 0;
}

if (!isType(obj, Float.class)) {
return 0;
}

return (float) obj;
return (float) getValueOrDefault(key, Float.class, 0f);
}

/**
Expand All @@ -216,19 +125,28 @@ public float getFloat(String key) {
* @return the double value associated with the given key, or 0 if the key is not found or the value is not a double
*/
public double getDouble(String key) {
Object obj = get(key);
if (obj == null) {
return 0;
}
return (double) getValueOrDefault(key, Double.class, 0d);
}

if (!isType(obj, Double.class)) {
return 0;
}
private Object getValue(String key, Class<?> clazz) {
String[] parts = key.split("\\.");
Map<String, Object> current = data;

return (double) obj;
for (int i = 0; i < parts.length; i++) {
Object value = current.get(parts[i]);
if (value == null || (i < parts.length - 1 && !(value instanceof Map))) {
return null;
}
if (i == parts.length - 1) {
return clazz.isInstance(value) ? value : null;
}
current = (Map<String, Object>) value;
}
return null;
}

private boolean isType(@NotNull Object obj, Class<?> clazz) {
return clazz.isInstance(obj);
private <T> T getValueOrDefault(String key, Class<T> clazz, T defaultValue) {
T value = (T) getValue(key, clazz);
return value != null ? value : defaultValue;
}
}
7 changes: 5 additions & 2 deletions src/test/java/de/oliver/fancylib/jdb/JDBTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,15 @@ public void testGetDocumentWhenFileExists() throws IOException {
String basePath = "./test_files/";
JDB jdb = new JDB(basePath);
String path = "existing_file";
String value = "Test message";
TestObject value = new TestObject("Test message");
jdb.set(path, value);

// Act
JDocument document = jdb.getDocument(path);

// Assert
assertNotNull(document);
assertEquals(value, document.getString("message"));
assertEquals(value.message(), document.getString("message"));
}

// Testing the getDocument method when the file does not exist
Expand All @@ -226,4 +226,7 @@ public void testGetDocumentWhenFileDoesNotExist() throws IOException {
// Assert
assertNull(document);
}

record TestObject(String message) {
}
}

0 comments on commit 8d00224

Please sign in to comment.