Skip to content

Commit

Permalink
Merge pull request #37 from JavaWebStack/dev
Browse files Browse the repository at this point in the history
Release 1.0.2
  • Loading branch information
JanHolger authored Oct 7, 2022
2 parents 4126d21 + a0a1548 commit aafb59e
Show file tree
Hide file tree
Showing 25 changed files with 400 additions and 141 deletions.
29 changes: 24 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<buildVersion>1.0.1-SNAPSHOT</buildVersion>
<buildVersion>1.0.2-SNAPSHOT</buildVersion>
</properties>

<groupId>org.javawebstack</groupId>
Expand All @@ -32,6 +32,18 @@
<organization>JavaWebStack</organization>
<organizationUrl>https://javawebstack.org</organizationUrl>
</developer>
<developer>
<name>Timothy Gillespie</name>
<email>timothy@gillespie.eu</email>
<organization>JavaWebStack</organization>
<organizationUrl>https://javawebstack.org</organizationUrl>
</developer>
<developer>
<name>Julian Gojani</name>
<email>julian@gojani.xyz</email>
<organization>JavaWebStack</organization>
<organizationUrl>https://javawebstack.org</organizationUrl>
</developer>
</developers>

<scm>
Expand All @@ -44,8 +56,15 @@
<dependency>
<groupId>org.javawebstack</groupId>
<artifactId>abstract-data</artifactId>
<version>1.0.0</version>
<version>1.0.4</version>
</dependency>
<!--- Temporary fix for transitive vulnerabilities -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
<!--- ============================================ -->
<dependency>
<groupId>org.atteo</groupId>
<artifactId>evo-inflector</artifactId>
Expand All @@ -59,7 +78,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.1</version>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -71,13 +90,13 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<version>1.18.24</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
<version>8.0.30</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/javawebstack/orm/Accessible.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package org.javawebstack.orm;

import org.javawebstack.orm.query.Query;
import org.javawebstack.orm.query.QueryGroup;

public interface Accessible {
<T extends Model> Query<T> access(Query<T> query, Object accessor);
<T extends Model> QueryGroup<T> access(Query<T> query, QueryGroup<T> accessChecks, Object accessor);
}
9 changes: 4 additions & 5 deletions src/main/java/org/javawebstack/orm/Repo.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Stream;

public class Repo<T extends Model> {

Expand Down Expand Up @@ -73,11 +71,11 @@ public Query<T> whereId(Object right) {
}

public Query<T> accessible(Object accessor) {
return accessible(query(), accessor);
return query().accessible(accessor);
}

public Query<T> accessible(Query<T> query, Object accessor) {
return accessible == null ? query : accessible.access(query, accessor);
public Accessible getAccessible() {
return accessible;
}

public void save(T entry) {
Expand Down Expand Up @@ -122,6 +120,7 @@ private void executeCreate(T entry) {
map.remove(idCol);
}
SQLQueryString qs = getConnection().builder().buildInsert(info, map);
SQL connection = Session.current() != null ? Session.current().getConnection() : this.connection;
int id = connection.write(qs.getQuery(), qs.getParameters().toArray());
if (info.isAutoIncrement())
info.getField(info.getIdField()).set(entry, id);
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/org/javawebstack/orm/Session.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.javawebstack.orm;

import org.javawebstack.orm.wrapper.SQL;

import java.util.function.Consumer;

public class Session {

private static ThreadLocal<Session> sessions = new ThreadLocal<>();

public static Session current() {
return sessions.get();
}

private SQL connection;

private Session() {

}

public Session via(SQL connection) {
this.connection = connection;
return this;
}

public SQL getConnection() {
return connection;
}

public static void session(Consumer<Session> consumer) {
Session session = begin();
consumer.accept(session);
end();
}

public static Session begin() {
Session session = new Session();
sessions.set(session);
return session;
}

public static void end() {
sessions.remove();
}

}
80 changes: 52 additions & 28 deletions src/main/java/org/javawebstack/orm/TableInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.javawebstack.orm.util.Helper;
import org.javawebstack.orm.util.KeyType;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
Expand All @@ -29,7 +28,7 @@ public class TableInfo {
private final Class<? extends Model> modelClass;
private String primaryKey;
private final List<String> uniqueKeys = new ArrayList<>();
private final Constructor<?> constructor;
private Constructor<?> constructor;
private String relationField;
private final Map<String, String> filterable = new HashMap<>();
private final List<String> searchable = new ArrayList<>();
Expand All @@ -42,6 +41,36 @@ public class TableInfo {
public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfigurationException {
this.config = config;
this.modelClass = model;

Stack<Class<?>> superClasses = Helper.getSuperClassesTill(model, Model.class);
while (!superClasses.isEmpty()) {
Class<? extends Model> superClass = (Class<? extends Model>) superClasses.pop();
if (Modifier.isAbstract(superClass.getModifiers())) {
analyzeColumns(superClass);
} else {
throw new ORMConfigurationException("The parent model has to be abstract!");
}
}

constructInfo(model);
}

private void constructInfo (Class<? extends Model> model) throws ORMConfigurationException {
analyzeColumns(model);
analyzeTable(model);

if (!fields.containsKey(idField))
idField = "uuid";
if (!fields.containsKey(idField))
throw new ORMConfigurationException("No id field found!");

if (config.isIdPrimaryKey()) {
if (primaryKey == null)
primaryKey = idField;
}
}

private void analyzeTable(Class<? extends Model> model) throws ORMConfigurationException {
if (model.isAnnotationPresent(Table.class)) {
Table table = model.getDeclaredAnnotationsByType(Table.class)[0];
tableName = table.value();
Expand All @@ -59,6 +88,26 @@ public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfi
} catch (NoSuchMethodException e) {
throw new ORMConfigurationException("The model class has no empty constructor!");
}
if (model.isAnnotationPresent(RelationField.class)) {
relationField = model.getDeclaredAnnotationsByType(RelationField.class)[0].value();
} else {
relationField = Helper.pascalToCamelCase(model.getSimpleName()) + ((getIdType().equals(UUID.class) && !idField.equalsIgnoreCase("id")) ? "UUID" : "Id");
}
if (model.isAnnotationPresent(SoftDelete.class)) {
softDelete = model.getDeclaredAnnotationsByType(SoftDelete.class)[0];
if (!fields.containsKey(softDelete.value()))
throw new ORMConfigurationException("Missing soft-delete field '" + softDelete.value() + "'");
}
if (model.isAnnotationPresent(Dates.class)) {
dates = model.getDeclaredAnnotationsByType(Dates.class)[0];
if (!fields.containsKey(dates.create()))
throw new ORMConfigurationException("Missing dates field '" + dates.create() + "'");
if (!fields.containsKey(dates.update()))
throw new ORMConfigurationException("Missing dates field '" + dates.update() + "'");
}
}

private void analyzeColumns(Class<? extends Model> model) throws ORMConfigurationException {
for (Field field : model.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()))
continue;
Expand All @@ -82,7 +131,7 @@ public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfi
else
fieldSize = fieldConfig.size();

SQLType sqlType = config.getType(field.getType(), fieldSize);
SQLType sqlType = config.getType(field.getType(), fieldSize);
if (sqlType != null) {
sqlTypes.put(fieldName, sqlType);
sqlTypeParameters.put(fieldName, config.getTypeParameters(field.getType(), fieldSize));
Expand All @@ -106,31 +155,6 @@ public TableInfo(Class<? extends Model> model, ORMConfig config) throws ORMConfi
if (field.isAnnotationPresent(Searchable.class))
this.searchable.add(fieldName);
}
if (!fields.containsKey(idField))
idField = "uuid";
if (!fields.containsKey(idField))
throw new ORMConfigurationException("No id field found!");
if (model.isAnnotationPresent(RelationField.class)) {
relationField = model.getDeclaredAnnotationsByType(RelationField.class)[0].value();
} else {
relationField = Helper.pascalToCamelCase(model.getSimpleName()) + ((getIdType().equals(UUID.class) && !idField.equalsIgnoreCase("id")) ? "UUID" : "Id");
}
if (config.isIdPrimaryKey()) {
if (primaryKey == null)
primaryKey = idField;
}
if (model.isAnnotationPresent(SoftDelete.class)) {
softDelete = model.getDeclaredAnnotationsByType(SoftDelete.class)[0];
if (!fields.containsKey(softDelete.value()))
throw new ORMConfigurationException("Missing soft-delete field '" + softDelete.value() + "'");
}
if (model.isAnnotationPresent(Dates.class)) {
dates = model.getDeclaredAnnotationsByType(Dates.class)[0];
if (!fields.containsKey(dates.create()))
throw new ORMConfigurationException("Missing dates field '" + dates.create() + "'");
if (!fields.containsKey(dates.update()))
throw new ORMConfigurationException("Missing dates field '" + dates.update() + "'");
}
}

public boolean isSoftDelete() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
import org.javawebstack.orm.SQLType;

public class AbstractDataTypeMapper implements TypeMapper {

private static final int BYTES_OVERHEAD_TEXT = 2;
private static final int BYTES_OVERHEAD_MEDIUMTEXT = 3;
private static final int BYTES_OVERHEAD_LONGTEXT = 4;

private static final long MAX_SIZE_TEXT = (long) Math.floor((65535 - BYTES_OVERHEAD_TEXT) / 4);
private static final long MAX_SIZE_MEDIUMTEXT = (long) Math.floor((16777215 - BYTES_OVERHEAD_MEDIUMTEXT) / 4);
private static final long MAX_SIZE_LONGTEXT = (long) Math.floor((4294967295L - BYTES_OVERHEAD_LONGTEXT) / 4);

public Object mapToSQL(Object source, Class<?> type) {
if (source == null)
return null;
Expand All @@ -21,8 +30,13 @@ public Object mapToJava(Object source, Class<?> type) {
}

public SQLType getType(Class<?> type, int size) {
if (AbstractElement.class.isAssignableFrom(type))
if (AbstractElement.class.isAssignableFrom(type)) {
if (size > MAX_SIZE_MEDIUMTEXT)
return SQLType.LONGTEXT;
if (size > MAX_SIZE_TEXT)
return SQLType.MEDIUMTEXT;
return SQLType.TEXT;
}
return null;
}

Expand Down
21 changes: 16 additions & 5 deletions src/main/java/org/javawebstack/orm/mapper/DefaultMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public Object mapToJava(Object source, Class<?> type) {
}

public SQLType getType(Class<?> type, int size) {
if (type.equals(String.class) || type.equals(char[].class))
if (type.equals(String.class) || type.equals(char[].class)) {
// Upper limit of 4294967295 exceeds the int boundaries
if (size > MAX_SIZE_MEDIUMTEXT)
return SQLType.LONGTEXT;
Expand All @@ -119,12 +119,18 @@ public SQLType getType(Class<?> type, int size) {
return SQLType.VARCHAR;
if (size == 1)
return SQLType.CHAR;
}
if (type.equals(UUID.class))
return SQLType.VARCHAR;
if (type.equals(char.class))
return SQLType.CHAR;
if (type.isEnum())
return SQLType.ENUM;
if (type.isEnum()) {
if(size < 1) {
return SQLType.ENUM;
} else {
return SQLType.VARCHAR;
}
}
if (type.equals(boolean.class) || type.equals(Boolean.class) || type.equals(byte.class) || type.equals(Byte.class))
return SQLType.TINYINT;
if (type.equals(short.class) || type.equals(Short.class))
Expand All @@ -147,8 +153,13 @@ public SQLType getType(Class<?> type, int size) {
}

public String getTypeParameters(Class<?> type, int size) {
if (type.isEnum())
return Arrays.stream(((Class<? extends Enum<?>>) type).getEnumConstants()).map(c -> "'" + c.name() + "'").collect(Collectors.joining(","));
if (type.isEnum()) {
if(size < 1) {
return Arrays.stream(((Class<? extends Enum<?>>) type).getEnumConstants()).map(c -> "'" + c.name() + "'").collect(Collectors.joining(","));
} else {
return String.valueOf(size);
}
}
if (type.equals(String.class) || type.equals(char[].class))
return size > MAX_SIZE_VARCHAR || size < 1 ? null : String.valueOf(size);
if (type.equals(byte[].class))
Expand Down
Loading

0 comments on commit aafb59e

Please sign in to comment.