Skip to content

Commit 56f73dc

Browse files
committed
Added support for custom encoders and decoders for class data types (as long they're not one of the built-in ones)
1 parent e44fe24 commit 56f73dc

File tree

4 files changed

+94
-17
lines changed

4 files changed

+94
-17
lines changed

core/src/main/java/com/github/fernthedev/fernapi/universal/data/database/ColumnData.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,10 @@ public static ColumnData fromField(Field field, String value) throws IllegalAcce
6868

6969
// Code snatched from Petr Panteleyev's MySQL annotation API
7070
switch (typeName) {
71+
72+
7173
case TYPE_STRING:
72-
if (column.isJson()) {
73-
mySQLType = "JSON";
74-
} else {
75-
mySQLType = "VARCHAR("
76-
+ column.length()
77-
+ ")";
78-
}
74+
mySQLType = stringSQL(column);
7975
break;
8076
case TYPE_ENUM:
8177
mySQLType = "VARCHAR("
@@ -116,14 +112,24 @@ public static ColumnData fromField(Field field, String value) throws IllegalAcce
116112
}
117113
break;
118114
default:
119-
throw new IllegalStateException(BAD_FIELD_TYPE + typeName);
115+
if (!MySQLData.hasEncoder(type))
116+
throw new IllegalStateException(BAD_FIELD_TYPE + typeName + "Register to " + MySQLData.class.getName() + ".registerEncoder()");
117+
else
118+
mySQLType = stringSQL(column);
120119
}
121120

122121

123-
124-
125122
return new ColumnData(columnName, value, mySQLType, length, nullable, autoIncrement, primaryKey);
126123
}
127124

125+
private static String stringSQL(Column column) {
126+
if (column.isJson()) {
127+
return "JSON";
128+
} else {
129+
return "VARCHAR("
130+
+ column.length()
131+
+ ")";
132+
}
133+
}
128134

129135
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.github.fernthedev.fernapi.universal.data.database;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import java.util.function.Function;
6+
7+
public class MySQLData {
8+
9+
private static final Map<Class<?>, Function<String, ?>> DECODERS = new HashMap<>();
10+
private static final Map<Class<?>, Function<?, String>> ENCODERS = new HashMap<>();
11+
12+
13+
public static <T> void registerEncoder(Class<T> clazz, Function<T, String> encoder) {
14+
ENCODERS.put(clazz, encoder);
15+
}
16+
17+
public static <T> void registerDecoder(Class<T> clazz, Function<String, T> decoder) {
18+
DECODERS.put(clazz, decoder);
19+
}
20+
21+
public static boolean hasEncoder(Class<?> clazz) {
22+
return ENCODERS.containsKey(clazz);
23+
}
24+
25+
public static boolean hasDecoder(Class<?> clazz) {
26+
return DECODERS.containsKey(clazz);
27+
}
28+
29+
public static <T> T decode(Class<? extends T> clazz, String value) {
30+
return (T) DECODERS.get(clazz).apply(value);
31+
}
32+
33+
public static <T> String encode(Class<? extends T> clazz, T value) {
34+
Function<T, String> stringFunction = (Function<T, String>) ENCODERS.get(clazz);
35+
36+
return stringFunction.apply(value);
37+
}
38+
}

core/src/main/java/com/github/fernthedev/fernapi/universal/data/database/RowData.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ protected void initiateRowData(DbRow rowData) {
6060
ColumnData columnData;
6161
try {
6262
Column column = field.getAnnotation(Column.class);
63-
columnData = ColumnData.fromField(field, rowData.get(column.value()).toString());
63+
64+
columnData = ColumnData.fromField(field, getValue(rowData.get(column.value())));
6465
addField(field, columnData, rowData.get(columnData.getColumnName()));
6566
} catch (IllegalAccessException e) {
6667
e.printStackTrace();
@@ -85,7 +86,7 @@ protected void initiateRowData() {
8586
ColumnData columnData;
8687
try {
8788
field.setAccessible(true);
88-
columnData = ColumnData.fromField(field, field.get(instance).toString());
89+
columnData = ColumnData.fromField(field, getValue(field.get(instance)));
8990
addField(field, columnData);
9091
} catch (IllegalAccessException e) {
9192
e.printStackTrace();
@@ -94,6 +95,17 @@ protected void initiateRowData() {
9495
}
9596
}
9697

98+
protected String getValue(Object object) {
99+
if (mySqlProxy.getReaderMap().containsKey(object.getClass().toString()))
100+
return object.getClass().toString();
101+
102+
if (MySQLData.hasEncoder(object.getClass()))
103+
return MySQLData.encode(object.getClass(), object);
104+
105+
106+
return String.valueOf(object);
107+
}
108+
97109
/**
98110
* Validates that the row data fields are properly configured.
99111
* @param rowData
@@ -129,10 +141,26 @@ private void addField(Field field, ColumnData columnData, Object value) {
129141
cachedDataStr.put(field.getAnnotation(Column.class).value(), columnData);
130142

131143
try {
132-
Object val = mySqlProxy.getFieldValue(field.getType(), value);
144+
Object val;
145+
146+
if (
147+
value instanceof String &&
148+
!String.class.isAssignableFrom(field.getType()) &&
149+
!mySqlProxy.getReaderMap().containsKey(field.getType().getName())
150+
) {
151+
if (!MySQLData.hasDecoder(field.getType()))
152+
throw new IllegalStateException(
153+
"Field could not be parsed: " + field.getType().getName() + ". " +
154+
"Register to " + MySQLData.class.getName() + ".registerDecoder()");
155+
156+
val = MySQLData.decode(field.getType(), (String) value);
157+
} else {
158+
val = mySqlProxy.getFieldValue(field.getType(), value);
159+
}
133160

134161
field.setAccessible(true);
135162

163+
136164
field.set(this, val);
137165
} catch (IllegalAccessException e) {
138166
e.printStackTrace();

core/src/main/java/com/github/fernthedev/fernapi/universal/mysql/DatabaseListener.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.github.fernthedev.fernapi.universal.exceptions.database.DatabaseException;
1010
import lombok.*;
1111
import org.intellij.lang.annotations.Language;
12+
import org.panteleyev.mysqlapi.DataTypes;
1213
import org.panteleyev.mysqlapi.MySqlProxy;
1314
import org.panteleyev.mysqlapi.annotations.Column;
1415
import org.panteleyev.mysqlapi.annotations.ForeignKey;
@@ -152,14 +153,14 @@ public CompletableFuture<List<DbRow>> getTableRows(String name) {
152153
* @return
153154
*/
154155
public <T extends RowData> CompletableFuture<Void> removeRowIfColumnContainsValue(TableInfo<T> tableInfo, String columnName, String value) {
155-
@Language("SQL") String sql = "DELETE FROM " + tableInfo.getTableName() + " WHERE ? = ?;";
156+
@Language("SQL") String sql = "DELETE FROM " + tableInfo.getTableName() + " WHERE " + columnName + " = ?;";
156157

157158

158159

159160
return database.queryAsync(sql).thenAccept(dbStatement -> {
160161
try (DbStatement statement = dbStatement) {
161-
statement.execute(columnName, value);
162-
Universal.debug("Executing {} {} {} {}",sql, tableInfo.getTableName(), columnName, value);
162+
statement.execute(value);
163+
Universal.debug("Executing {} {} ",sql, value);
163164
tableInfo.loadFromDB(this);
164165
} catch (SQLException throwables) {
165166
throwables.printStackTrace();
@@ -332,7 +333,7 @@ public <T extends RowData> String getColumnName(@NonNull TableInfo<T> tableDataI
332333
* @return
333334
*/
334335
public <T extends RowData> CompletableFuture<Void> createTable(@NonNull TableInfo<T> tableDataInfo) {
335-
@Language("SQL") String q = "CREATE TABLE IF NOT EXISTS " + tableDataInfo .getTableName() + " (";
336+
@Language("SQL") String q = "CREATE TABLE IF NOT EXISTS " + tableDataInfo.getTableName() + " (";
336337

337338
StringBuilder sql = new StringBuilder(q);
338339

@@ -361,6 +362,10 @@ public <T extends RowData> CompletableFuture<Void> createTable(@NonNull TableInf
361362
}
362363
first = false;
363364

365+
366+
if (MySQLData.hasEncoder(getterType) && !mysqlProxy.getReaderMap().containsKey(typeName))
367+
typeName = DataTypes.TYPE_STRING;
368+
364369
sql.append(fName).append(" ")
365370
.append(mysqlProxy.getColumnString(column, field.getAnnotation(PrimaryKey.class),
366371
field.getAnnotation(ForeignKey.class), typeName, constraints));

0 commit comments

Comments
 (0)