cat.nyaa.nyaacore.orm.ObjectModifier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rpgitems Show documentation
Show all versions of rpgitems Show documentation
The legacy RPGItems continues. (fork)
package cat.nyaa.nyaacore.orm;
import cat.nyaa.nyaacore.orm.annotations.Column;
import cat.nyaa.nyaacore.orm.annotations.Table;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
* Access a Java object like a database record
* One type needs only one ObjectModifier instance and the instance can be used
* on many different objects.
* All ObjectModifier instances are stored permanently in {@link ObjectModifier#structured_tables}.
*
* @param type of the java object, must have default constructor
*/
public class ObjectModifier {
/* class -> TableStructure cache */
private static final Map, ObjectModifier> structured_tables = new HashMap<>();
// Java object type info
public final Class clz;
public final Constructor ctor;
// SQL table info
public final String tableName;
public final List orderedColumnName = new ArrayList<>();
public final Map columns = new HashMap<>();
public final String primaryKey; // null if no primary key
private ObjectModifier(Class tableClass) throws NoSuchMethodException {
Table annotationTable = tableClass.getDeclaredAnnotation(Table.class);
this.clz = tableClass;
Constructor ctor;
try {
ctor = tableClass.getConstructor();
} catch (NoSuchMethodException e) {
ctor = tableClass.getDeclaredConstructor();
}
this.ctor = ctor;
this.ctor.setAccessible(true);
if (annotationTable == null || annotationTable.value().isEmpty()) {
this.tableName = tableClass.getSimpleName();
} else {
this.tableName = annotationTable.value();
}
String pkColumn = null;
// load all the fields
for (Field f : tableClass.getDeclaredFields()) {
Column columnAnnotation = f.getAnnotation(Column.class);
if (columnAnnotation == null) continue;
ObjectFieldModifier structure = new ObjectFieldModifier(this, f, columnAnnotation);
if (columns.containsKey(structure.getName()))
throw new RuntimeException("Duplicated column name: " + structure.getName());
if (structure.primary) {
if (pkColumn != null) throw new RuntimeException("Duplicated primary key at: " + f.getName());
pkColumn = structure.getName();
}
columns.put(structure.getName(), structure);
}
// load all the getter/setter
for (Method m : tableClass.getDeclaredMethods()) {
Column columnAnnotation = m.getAnnotation(Column.class);
if (columnAnnotation == null) continue;
ObjectFieldModifier structure = new ObjectFieldModifier(this, m, columnAnnotation);
if (columns.containsKey(structure.getName()))
throw new RuntimeException("Duplicated column name: " + structure.getName());
if (structure.primary) {
if (pkColumn != null) throw new RuntimeException("Duplicated primary key at: " + m.getName());
pkColumn = structure.getName();
}
columns.put(structure.getName(), structure);
}
primaryKey = pkColumn;
orderedColumnName.addAll(columns.keySet());
orderedColumnName.sort(String::compareTo);
}
@SuppressWarnings("unchecked")
public static ObjectModifier fromClass(Class cls) {
if (structured_tables.containsKey(cls)) return (ObjectModifier) structured_tables.get(cls);
ObjectModifier ts;
try {
ts = new ObjectModifier<>(cls);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
structured_tables.put(cls, ts);
return ts;
}
/* ********** *
* class info *
* ********** */
public Class getJavaClass() {
return clz;
}
/**
* @return table name, nullable
*/
public String getTableName() {
return tableName;
}
/**
* @return a readonly list of column names
*/
public List getColNames() {
return Collections.unmodifiableList(orderedColumnName);
}
/**
* Get primary key column name
*
* @return the name of primary key, null if no primary key
*/
public String getPkColName() {
return primaryKey;
}
/**
* Check if a column exists, may be faster than getColNames().contains()
*
* @param column column name
* @return exists or not
*/
public boolean hasColumn(String column) {
return columns.containsKey(column);
}
/**
* return comma separated list of column names
*/
public String getColumnNamesString() {
if (orderedColumnName.size() == 0) return "";
StringBuilder sb = new StringBuilder(orderedColumnName.get(0));
for (int i = 1; i < orderedColumnName.size(); i++) {
sb.append(",");
sb.append(orderedColumnName.get(i));
}
return sb.toString();
}
public DataTypeMapping.IDataTypeConverter getTypeConvertorForColumn(String columnName) {
ObjectFieldModifier fm = columns.get(columnName);
if (fm == null) throw new IllegalArgumentException("no such column: " + columnName);
return fm.typeConverter;
}
/* ************************ *
* Object read/modification *
* ************************ */
public Object getSqlValue(T obj, String columnName) {
ObjectFieldModifier fm = columns.get(columnName);
if (fm == null) throw new IllegalArgumentException("no such column: " + columnName);
return fm.getSqlObject(obj);
}
public void setSqlValue(T obj, String columnName, Object newSqlValue) {
ObjectFieldModifier fm = columns.get(columnName);
if (fm == null) throw new IllegalArgumentException("no such column: " + columnName);
fm.setSqlObject(obj, newSqlValue);
}
/**
* Construct ONE table object from Java ResultSet.
* Only CURRENT result row will be picked
*/
public T getObjectFromResultSet(ResultSet rs) throws ReflectiveOperationException, SQLException {
T obj = ctor.newInstance();
for (String colName : getColNames()) {
Object colValue = rs.getObject(colName);
setSqlValue(obj, colName, colValue);
}
return obj;
}
/**
* Get certain columns(fields) from a table object
* and the column objects should have been converted to database acceptable objects: long/float/string
*
* @param obj the java object
* @param columns the column names, or null for all columns
* @return columnName to columnData map
*/
public Map getColumnObjectMap(T obj, String... columns) {
List columnList = new ArrayList<>();
Map objects = new HashMap<>();
if (columns == null || columns.length == 0) {
columnList.addAll(orderedColumnName);
} else {
columnList.addAll(Arrays.asList(columns));
}
for (String colName : columnList) {
if (!this.columns.containsKey(colName))
throw new RuntimeException("column " + colName + " not in object " + getJavaClass().getCanonicalName());
objects.put(colName, this.columns.get(colName).getSqlObject(obj));
}
return objects;
}
}