mirror of
https://github.com/dalbodeule/snap-admin.git
synced 2025-06-09 05:48:20 +00:00
Refactored field type system and Enum
support
In order to support the `Enum` field type the `DbFieldType` enum has been converted to an abstract class with an implementation class for each database field type.
This commit is contained in:
parent
d67729ea9d
commit
2cfcf2a8d7
@ -40,6 +40,7 @@ import jakarta.annotation.PostConstruct;
|
|||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.Enumerated;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
import jakarta.persistence.Lob;
|
import jakarta.persistence.Lob;
|
||||||
@ -50,9 +51,12 @@ import jakarta.persistence.OneToOne;
|
|||||||
import tech.ailef.dbadmin.external.annotations.Disable;
|
import tech.ailef.dbadmin.external.annotations.Disable;
|
||||||
import tech.ailef.dbadmin.external.annotations.DisplayFormat;
|
import tech.ailef.dbadmin.external.annotations.DisplayFormat;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.CustomJpaRepository;
|
import tech.ailef.dbadmin.external.dbmapping.CustomJpaRepository;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbField;
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbFieldType;
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbFieldType;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.EnumFieldType;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.StringFieldType;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.TextFieldType;
|
||||||
import tech.ailef.dbadmin.external.dto.MappingError;
|
import tech.ailef.dbadmin.external.dto.MappingError;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminNotFoundException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminNotFoundException;
|
||||||
@ -285,16 +289,26 @@ public class DbAdmin {
|
|||||||
// foreign key, if any
|
// foreign key, if any
|
||||||
Class<?> connectedType = null;
|
Class<?> connectedType = null;
|
||||||
|
|
||||||
// Try to assign default field type
|
// Try to assign default field type determining it by the raw field type and its annotations
|
||||||
DbFieldType fieldType = null;
|
DbFieldType fieldType = null;
|
||||||
try {
|
try {
|
||||||
fieldType = DbFieldType.fromClass(f.getType());
|
Class<? extends DbFieldType> fieldTypeClass = DbFieldType.fromClass(f.getType());
|
||||||
|
|
||||||
if (fieldType != null && lob != null && fieldType == DbFieldType.STRING) {
|
if (fieldTypeClass == StringFieldType.class && lob != null) {
|
||||||
fieldType = DbFieldType.TEXT;
|
fieldTypeClass = TextFieldType.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enums are instantiated later because they call a different constructor
|
||||||
|
if (fieldTypeClass != EnumFieldType.class) {
|
||||||
|
try {
|
||||||
|
fieldType = fieldTypeClass.getConstructor().newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||||
|
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||||
|
// If failure, we try to map a relationship on this field later
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (DbAdminException e) {
|
} catch (DbAdminException e) {
|
||||||
// If failure, we try to map a relationship on this field
|
// If failure, we try to map a relationship on this field later
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manyToOne != null || oneToOne != null) {
|
if (manyToOne != null || oneToOne != null) {
|
||||||
@ -310,6 +324,14 @@ public class DbAdmin {
|
|||||||
connectedType = targetEntityClass;
|
connectedType = targetEntityClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if field has @Enumerated annotation and process accordingly
|
||||||
|
if (fieldType == null) {
|
||||||
|
Enumerated enumerated = f.getAnnotation(Enumerated.class);
|
||||||
|
if (enumerated != null) {
|
||||||
|
fieldType = new EnumFieldType(f.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fieldType == null) {
|
if (fieldType == null) {
|
||||||
throw new UnsupportedFieldTypeException("Unable to determine fieldType for " + f.getType());
|
throw new UnsupportedFieldTypeException("Unable to determine fieldType for " + f.getType());
|
||||||
}
|
}
|
||||||
@ -367,7 +389,7 @@ public class DbAdmin {
|
|||||||
if (linkType == null)
|
if (linkType == null)
|
||||||
throw new DbAdminException("Unable to find @Id field in Entity class " + entityClass);
|
throw new DbAdminException("Unable to find @Id field in Entity class " + entityClass);
|
||||||
|
|
||||||
return DbFieldType.fromClass(linkType);
|
return DbFieldType.fromClass(linkType).getConstructor().newInstance();
|
||||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||||
throw new DbAdminException(e);
|
throw new DbAdminException(e);
|
||||||
|
@ -57,10 +57,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
|
|
||||||
import tech.ailef.dbadmin.external.DbAdmin;
|
import tech.ailef.dbadmin.external.DbAdmin;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbAdminRepository;
|
import tech.ailef.dbadmin.external.dbmapping.DbAdminRepository;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbField;
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbFieldValue;
|
import tech.ailef.dbadmin.external.dbmapping.DbFieldValue;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbObject;
|
import tech.ailef.dbadmin.external.dbmapping.DbObject;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResult;
|
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResult;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResultRow;
|
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResultRow;
|
||||||
import tech.ailef.dbadmin.external.dto.DataExportFormat;
|
import tech.ailef.dbadmin.external.dto.DataExportFormat;
|
||||||
|
@ -40,6 +40,9 @@ import jakarta.persistence.criteria.CriteriaUpdate;
|
|||||||
import jakarta.persistence.criteria.Path;
|
import jakarta.persistence.criteria.Path;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
import jakarta.persistence.criteria.Root;
|
import jakarta.persistence.criteria.Root;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.StringFieldType;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.TextFieldType;
|
||||||
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
import tech.ailef.dbadmin.external.dto.QueryFilter;
|
import tech.ailef.dbadmin.external.dto.QueryFilter;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
@ -163,7 +166,7 @@ public class CustomJpaRepository extends SimpleJpaRepository {
|
|||||||
List<Predicate> finalPredicates = new ArrayList<>();
|
List<Predicate> finalPredicates = new ArrayList<>();
|
||||||
|
|
||||||
List<DbField> stringFields =
|
List<DbField> stringFields =
|
||||||
schema.getSortedFields().stream().filter(f -> f.getType() == DbFieldType.STRING || f.getType() == DbFieldType.TEXT)
|
schema.getSortedFields().stream().filter(f -> f.getType() instanceof StringFieldType || f.getType() instanceof TextFieldType)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
List<Predicate> queryPredicates = new ArrayList<>();
|
List<Predicate> queryPredicates = new ArrayList<>();
|
||||||
|
@ -46,6 +46,7 @@ import jakarta.validation.Validation;
|
|||||||
import jakarta.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
import tech.ailef.dbadmin.external.DbAdmin;
|
import tech.ailef.dbadmin.external.DbAdmin;
|
||||||
import tech.ailef.dbadmin.external.annotations.ReadOnly;
|
import tech.ailef.dbadmin.external.annotations.ReadOnly;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryOutputField;
|
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryOutputField;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResult;
|
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResult;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResultRow;
|
import tech.ailef.dbadmin.external.dbmapping.query.DbQueryResultRow;
|
||||||
|
@ -1,675 +0,0 @@
|
|||||||
/*
|
|
||||||
* Spring Boot Database Admin - An automatically generated CRUD admin UI for Spring Boot apps
|
|
||||||
* Copyright (C) 2023 Ailef (http://ailef.tech)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package tech.ailef.dbadmin.external.dbmapping;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.sql.Date;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import jakarta.persistence.ManyToMany;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import jakarta.persistence.OneToOne;
|
|
||||||
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
|
||||||
import tech.ailef.dbadmin.external.exceptions.UnsupportedFieldTypeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The enum for supported database field types.
|
|
||||||
*/
|
|
||||||
public enum DbFieldType {
|
|
||||||
SHORT {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return Short.parseShort(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Short.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
BIG_INTEGER {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return new BigInteger(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return BigInteger.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
INTEGER {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return Integer.parseInt(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Integer.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DOUBLE {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return Double.parseDouble(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Double.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LONG {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return Long.parseLong(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Long.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
FLOAT {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return Float.parseFloat(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Float.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
OFFSET_DATE_TIME {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "datetime";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return OffsetDateTime.parse(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return OffsetDateTime.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
DATE {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "date";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
|
|
||||||
try {
|
|
||||||
return format.parse(value.toString());
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Date.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LOCAL_DATE {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "date";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return LocalDate.parse(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Float.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LOCAL_DATE_TIME {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "datetime";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return LocalDateTime.parse(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return LocalDateTime.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
INSTANT {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "datetime";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return LocalDateTime.parse(value.toString()).toInstant(ZoneOffset.UTC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Instant.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
STRING {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "text";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TEXT {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "textarea";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
BOOLEAN {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "text";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return Boolean.parseBoolean(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return Boolean.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.EQ);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
BIG_DECIMAL {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return new BigDecimal(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return BigDecimal.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CHAR {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "char";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
if (value.toString().isBlank()) return null;
|
|
||||||
return value.toString().charAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return char.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.STRING_EQ);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
BYTE {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
return value.toString().getBytes()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return byte.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
throw new DbAdminException("Binary fields are not comparable");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
BYTE_ARRAY {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "file";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
if (value == null || value.toString().isBlank()) return null;
|
|
||||||
try {
|
|
||||||
return ((MultipartFile)value).getBytes();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new DbAdminException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return byte[].class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
throw new DbAdminException("Binary fields are not comparable");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UUID {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
return "text";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
return java.util.UUID.fromString(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return java.util.UUID.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
return List.of(CompareOperator.STRING_EQ, CompareOperator.CONTAINS);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
ONE_TO_MANY {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return OneToMany.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRelationship() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "One to Many";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
throw new DbAdminException();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ONE_TO_ONE {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return OneToOne.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRelationship() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "One to One";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
throw new DbAdminException();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MANY_TO_MANY {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
return ManyToMany.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRelationship() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Many to Many";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
throw new DbAdminException();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
COMPUTED {
|
|
||||||
@Override
|
|
||||||
public String getFragmentName() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object parseValue(Object value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getJavaClass() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CompareOperator> getCompareOperators() {
|
|
||||||
throw new DbAdminException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the Thymeleaf fragments in the 'inputs.html'
|
|
||||||
* file, used to render an input field for this specific type.
|
|
||||||
* For example, a fragment using a file input is used for binary fields.
|
|
||||||
*/
|
|
||||||
public abstract String getFragmentName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the value received through an HTML form into a instance
|
|
||||||
* of an object of this specific type. This usually involves a conversion
|
|
||||||
* from string, but, for example, files are sent as MultipartFile instead.
|
|
||||||
* @param value the value to parse
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract Object parseValue(Object value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Java class corresponding to this field type.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract Class<?> getJavaClass();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of compare operators that can be used to compare
|
|
||||||
* two values for this field type. Used in the faceted search to provide
|
|
||||||
* more operators than just equality (e.g. after/before for dates).
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract List<CompareOperator> getCompareOperators();
|
|
||||||
|
|
||||||
public boolean isRelationship() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the corresponding {@linkplain DbFieldType} from a Class object.
|
|
||||||
* @param klass
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static DbFieldType fromClass(Class<?> klass) {
|
|
||||||
if (klass == Boolean.class || klass == boolean.class) {
|
|
||||||
return BOOLEAN;
|
|
||||||
} else if (klass == Long.class || klass == long.class) {
|
|
||||||
return LONG;
|
|
||||||
} else if (klass == Integer.class || klass == int.class) {
|
|
||||||
return INTEGER;
|
|
||||||
} else if (klass == BigInteger.class) {
|
|
||||||
return BIG_INTEGER;
|
|
||||||
} else if (klass == Short.class || klass == short.class) {
|
|
||||||
return SHORT;
|
|
||||||
} else if (klass == String.class) {
|
|
||||||
return STRING;
|
|
||||||
} else if (klass == LocalDate.class) {
|
|
||||||
return LOCAL_DATE;
|
|
||||||
} else if (klass == Date.class) {
|
|
||||||
return DATE;
|
|
||||||
} else if (klass == LocalDateTime.class) {
|
|
||||||
return LOCAL_DATE_TIME;
|
|
||||||
} else if (klass == Instant.class) {
|
|
||||||
return INSTANT;
|
|
||||||
} else if (klass == Float.class || klass == float.class) {
|
|
||||||
return FLOAT;
|
|
||||||
} else if (klass == Double.class || klass == double.class) {
|
|
||||||
return DOUBLE;
|
|
||||||
} else if (klass == BigDecimal.class) {
|
|
||||||
return BIG_DECIMAL;
|
|
||||||
} else if (klass == byte[].class) {
|
|
||||||
return BYTE_ARRAY;
|
|
||||||
} else if (klass == OffsetDateTime.class) {
|
|
||||||
return OFFSET_DATE_TIME;
|
|
||||||
} else if (klass == byte.class || klass == Byte.class) {
|
|
||||||
return BYTE;
|
|
||||||
} else if (klass == java.util.UUID.class) {
|
|
||||||
return UUID;
|
|
||||||
} else if (klass == char.class || klass == Character.class) {
|
|
||||||
return CHAR;
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedFieldTypeException("Unsupported field type: " + klass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,6 +27,8 @@ import java.util.Objects;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for the value of a field
|
* Wrapper for the value of a field
|
||||||
*
|
*
|
||||||
|
@ -33,6 +33,8 @@ import jakarta.persistence.ManyToOne;
|
|||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import tech.ailef.dbadmin.external.annotations.DisplayName;
|
import tech.ailef.dbadmin.external.annotations.DisplayName;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.BooleanFieldType;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -246,7 +248,7 @@ public class DbObject {
|
|||||||
if (dbField == null) return null;
|
if (dbField == null) return null;
|
||||||
|
|
||||||
String prefix = "get";
|
String prefix = "get";
|
||||||
if (dbField.getType() == DbFieldType.BOOLEAN) {
|
if (dbField.getType() instanceof BooleanFieldType) {
|
||||||
prefix = "is";
|
prefix = "is";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ import tech.ailef.dbadmin.external.annotations.DisableDelete;
|
|||||||
import tech.ailef.dbadmin.external.annotations.DisableEdit;
|
import tech.ailef.dbadmin.external.annotations.DisableEdit;
|
||||||
import tech.ailef.dbadmin.external.annotations.DisableExport;
|
import tech.ailef.dbadmin.external.annotations.DisableExport;
|
||||||
import tech.ailef.dbadmin.external.annotations.HiddenColumn;
|
import tech.ailef.dbadmin.external.annotations.HiddenColumn;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
import tech.ailef.dbadmin.external.dto.MappingError;
|
import tech.ailef.dbadmin.external.dto.MappingError;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
import tech.ailef.dbadmin.external.misc.Utils;
|
import tech.ailef.dbadmin.external.misc.Utils;
|
||||||
|
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/BigDecimalFieldType.java
vendored
Normal file
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/BigDecimalFieldType.java
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class BigDecimalFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return new BigDecimal(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return BigDecimal.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/BigIntegerFieldType.java
vendored
Normal file
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/BigIntegerFieldType.java
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class BigIntegerFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return new BigInteger(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return BigInteger.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/BooleanFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/BooleanFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class BooleanFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "text";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return Boolean.parseBoolean(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Boolean.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.EQ);
|
||||||
|
}
|
||||||
|
}
|
35
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ByteArrayFieldType.java
vendored
Normal file
35
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ByteArrayFieldType.java
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class ByteArrayFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "file";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
try {
|
||||||
|
return ((MultipartFile)value).getBytes();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new DbAdminException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return byte[].class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
throw new DbAdminException("Binary fields are not comparable");
|
||||||
|
}
|
||||||
|
}
|
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ByteFieldType.java
vendored
Normal file
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ByteFieldType.java
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class ByteFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return value.toString().getBytes()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return byte.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
throw new DbAdminException("Binary fields are not comparable");
|
||||||
|
}
|
||||||
|
}
|
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/CharFieldType.java
vendored
Normal file
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/CharFieldType.java
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class CharFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "char";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
if (value.toString().isBlank()) return null;
|
||||||
|
return value.toString().charAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return char.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.STRING_EQ);
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ComputedFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ComputedFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class ComputedFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
throw new DbAdminException();
|
||||||
|
}
|
||||||
|
}
|
37
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/DateFieldType.java
vendored
Normal file
37
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/DateFieldType.java
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class DateFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "date";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
|
||||||
|
try {
|
||||||
|
return format.parse(value.toString());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Date.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package tech.ailef.dbadmin.external.dbmapping;
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -36,6 +36,9 @@ import tech.ailef.dbadmin.external.annotations.DisplayImage;
|
|||||||
import tech.ailef.dbadmin.external.annotations.Filterable;
|
import tech.ailef.dbadmin.external.annotations.Filterable;
|
||||||
import tech.ailef.dbadmin.external.annotations.FilterableType;
|
import tech.ailef.dbadmin.external.annotations.FilterableType;
|
||||||
import tech.ailef.dbadmin.external.annotations.ReadOnly;
|
import tech.ailef.dbadmin.external.annotations.ReadOnly;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.DbFieldValue;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.DbObject;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent a field on the database, generated from an Entity class instance variable.
|
* Represent a field on the database, generated from an Entity class instance variable.
|
||||||
@ -172,7 +175,7 @@ public class DbField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBinary() {
|
public boolean isBinary() {
|
||||||
return type == DbFieldType.BYTE_ARRAY;
|
return type instanceof ByteArrayFieldType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isImage() {
|
public boolean isImage() {
|
||||||
@ -184,7 +187,7 @@ public class DbField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isText() {
|
public boolean isText() {
|
||||||
return type == DbFieldType.TEXT;
|
return type instanceof TextFieldType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
115
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/DbFieldType.java
vendored
Normal file
115
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/DbFieldType.java
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.UnsupportedFieldTypeException;
|
||||||
|
import tech.ailef.dbadmin.external.misc.Utils;
|
||||||
|
|
||||||
|
public abstract class DbFieldType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the Thymeleaf fragments in the 'inputs.html'
|
||||||
|
* file, used to render an input field for this specific type.
|
||||||
|
* For example, a fragment using a file input is used for binary fields.
|
||||||
|
*/
|
||||||
|
public abstract String getFragmentName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the value received through an HTML form into a instance
|
||||||
|
* of an object of this specific type. This usually involves a conversion
|
||||||
|
* from string, but, for example, files are sent as MultipartFile instead.
|
||||||
|
* @param value the value to parse
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract Object parseValue(Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Java class corresponding to this field type.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract Class<?> getJavaClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of compare operators that can be used to compare
|
||||||
|
* two values for this field type. Used in the faceted search to provide
|
||||||
|
* more operators than just equality (e.g. after/before for dates).
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract List<CompareOperator> getCompareOperators();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the possible values that this field can have.
|
||||||
|
* This method is by default unsupported, and it's implemented only
|
||||||
|
* in subclasses where this is applicable, e.g. EnumFieldType.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<?> getValues() {
|
||||||
|
throw new UnsupportedOperationException("getValues only supported on Enum type: called on " + this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return Utils.camelToSnake(this.getClass().getSimpleName().replace("FieldType", "")).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRelationship() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding {@linkplain DbFieldType} from a Class object.
|
||||||
|
* @param klass
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Class<? extends DbFieldType> fromClass(Class<?> klass) {
|
||||||
|
if (klass == Boolean.class || klass == boolean.class) {
|
||||||
|
return BooleanFieldType.class;
|
||||||
|
} else if (klass == Long.class || klass == long.class) {
|
||||||
|
return LongFieldType.class;
|
||||||
|
} else if (klass == Integer.class || klass == int.class) {
|
||||||
|
return IntegerFieldType.class;
|
||||||
|
} else if (klass == BigInteger.class) {
|
||||||
|
return BigIntegerFieldType.class;
|
||||||
|
} else if (klass == Short.class || klass == short.class) {
|
||||||
|
return ShortFieldType.class;
|
||||||
|
} else if (klass == String.class) {
|
||||||
|
return StringFieldType.class;
|
||||||
|
} else if (klass == LocalDate.class) {
|
||||||
|
return LocalDateFieldType.class;
|
||||||
|
} else if (klass == Date.class) {
|
||||||
|
return DateFieldType.class;
|
||||||
|
} else if (klass == LocalDateTime.class) {
|
||||||
|
return LocalDateTimeFieldType.class;
|
||||||
|
} else if (klass == Instant.class) {
|
||||||
|
return InstantFieldType.class;
|
||||||
|
} else if (klass == Float.class || klass == float.class) {
|
||||||
|
return FloatFieldType.class;
|
||||||
|
} else if (klass == Double.class || klass == double.class) {
|
||||||
|
return DoubleFieldType.class;
|
||||||
|
} else if (klass == BigDecimal.class) {
|
||||||
|
return BigDecimalFieldType.class;
|
||||||
|
} else if (klass == byte[].class) {
|
||||||
|
return ByteArrayFieldType.class;
|
||||||
|
} else if (klass == OffsetDateTime.class) {
|
||||||
|
return OffsetDateTimeFieldType.class;
|
||||||
|
} else if (klass == byte.class || klass == Byte.class) {
|
||||||
|
return ByteFieldType.class;
|
||||||
|
} else if (klass == java.util.UUID.class) {
|
||||||
|
return UUIDFieldType.class;
|
||||||
|
} else if (klass == char.class || klass == Character.class) {
|
||||||
|
return CharFieldType.class;
|
||||||
|
} else if (Enum.class.isAssignableFrom(klass)) {
|
||||||
|
return EnumFieldType.class;
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedFieldTypeException("Unsupported field type: " + klass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/DoubleFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/DoubleFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class DoubleFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return Double.parseDouble(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Double.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
62
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/EnumFieldType.java
vendored
Normal file
62
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/EnumFieldType.java
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class EnumFieldType extends DbFieldType {
|
||||||
|
|
||||||
|
private Class<?> klass;
|
||||||
|
|
||||||
|
public EnumFieldType(Class<?> klass) {
|
||||||
|
this.klass = klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "select";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<?> getValues() {
|
||||||
|
try {
|
||||||
|
Method method = getJavaClass().getMethod("values");
|
||||||
|
Object[] invoke = (Object[])method.invoke(null);
|
||||||
|
return Arrays.stream(invoke).collect(Collectors.toList());
|
||||||
|
} catch (NoSuchMethodException | SecurityException | InvocationTargetException
|
||||||
|
| IllegalAccessException | IllegalArgumentException e) {
|
||||||
|
throw new DbAdminException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
try {
|
||||||
|
Method valueOf = getJavaClass().getMethod("valueOf", String.class);
|
||||||
|
return valueOf.invoke(null, value.toString());
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
if (e.getCause() instanceof IllegalArgumentException)
|
||||||
|
throw new DbAdminException("Invalid value " + value + " for enum type " + getJavaClass().getSimpleName());
|
||||||
|
else
|
||||||
|
throw new DbAdminException(e);
|
||||||
|
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
|
||||||
|
throw new DbAdminException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.STRING_EQ);
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/FloatFieldType.java
vendored
Normal file
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/FloatFieldType.java
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class FloatFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return Float.parseFloat(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Float.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
31
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/InstantFieldType.java
vendored
Normal file
31
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/InstantFieldType.java
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class InstantFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "datetime";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return LocalDateTime.parse(value.toString()).toInstant(ZoneOffset.UTC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Instant.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/IntegerFieldType.java
vendored
Normal file
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/IntegerFieldType.java
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class IntegerFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return Integer.parseInt(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Integer.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/LocalDateFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/LocalDateFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class LocalDateFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "date";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return LocalDate.parse(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Float.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
}
|
||||||
|
}
|
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/LocalDateTimeFieldType.java
vendored
Normal file
29
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/LocalDateTimeFieldType.java
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class LocalDateTimeFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "datetime";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return LocalDateTime.parse(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return LocalDateTime.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/LongFieldType.java
vendored
Normal file
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/LongFieldType.java
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class LongFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return Long.parseLong(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Long.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
38
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ManyToManyFieldType.java
vendored
Normal file
38
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ManyToManyFieldType.java
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.persistence.ManyToMany;
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class ManyToManyFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return ManyToMany.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRelationship() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Many to Many";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
throw new DbAdminException();
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OffsetDateTimeFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OffsetDateTimeFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class OffsetDateTimeFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "datetime";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return OffsetDateTime.parse(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return OffsetDateTime.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
}
|
||||||
|
}
|
695
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OldDbFieldType.java
vendored
Normal file
695
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OldDbFieldType.java
vendored
Normal file
@ -0,0 +1,695 @@
|
|||||||
|
///*
|
||||||
|
// * Spring Boot Database Admin - An automatically generated CRUD admin UI for Spring Boot apps
|
||||||
|
// * Copyright (C) 2023 Ailef (http://ailef.tech)
|
||||||
|
// *
|
||||||
|
// * This program is free software: you can redistribute it and/or modify
|
||||||
|
// * it under the terms of the GNU General Public License as published by
|
||||||
|
// * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// * (at your option) any later version.
|
||||||
|
// *
|
||||||
|
// * This program is distributed in the hope that it will be useful,
|
||||||
|
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// * GNU General Public License for more details.
|
||||||
|
// *
|
||||||
|
// * You should have received a copy of the GNU General Public License
|
||||||
|
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//package tech.ailef.dbadmin.external.dbmapping;
|
||||||
|
//
|
||||||
|
//import java.io.IOException;
|
||||||
|
//import java.lang.reflect.InvocationTargetException;
|
||||||
|
//import java.lang.reflect.Method;
|
||||||
|
//import java.math.BigDecimal;
|
||||||
|
//import java.math.BigInteger;
|
||||||
|
//import java.sql.Date;
|
||||||
|
//import java.text.ParseException;
|
||||||
|
//import java.text.SimpleDateFormat;
|
||||||
|
//import java.time.Instant;
|
||||||
|
//import java.time.LocalDate;
|
||||||
|
//import java.time.LocalDateTime;
|
||||||
|
//import java.time.OffsetDateTime;
|
||||||
|
//import java.time.ZoneOffset;
|
||||||
|
//import java.util.List;
|
||||||
|
//import java.util.Locale;
|
||||||
|
//
|
||||||
|
//import org.springframework.web.multipart.MultipartFile;
|
||||||
|
//
|
||||||
|
//import jakarta.persistence.ManyToMany;
|
||||||
|
//import jakarta.persistence.OneToMany;
|
||||||
|
//import jakarta.persistence.OneToOne;
|
||||||
|
//import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
//import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
//import tech.ailef.dbadmin.external.exceptions.UnsupportedFieldTypeException;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * The enum for supported database field types.
|
||||||
|
// */
|
||||||
|
//public enum OldDbFieldType {
|
||||||
|
// BIG_INTEGER {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return new BigInteger(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return BigInteger.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// INTEGER {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return Integer.parseInt(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Integer.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// DOUBLE {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return Double.parseDouble(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Double.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// LONG {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return Long.parseLong(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Long.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// FLOAT {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return Float.parseFloat(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Float.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// OFFSET_DATE_TIME {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "datetime";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return OffsetDateTime.parse(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return OffsetDateTime.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// DATE {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "date";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
|
||||||
|
// try {
|
||||||
|
// return format.parse(value.toString());
|
||||||
|
// } catch (ParseException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Date.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// LOCAL_DATE {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "date";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return LocalDate.parse(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Float.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// LOCAL_DATE_TIME {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "datetime";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return LocalDateTime.parse(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return LocalDateTime.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// INSTANT {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "datetime";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return LocalDateTime.parse(value.toString()).toInstant(ZoneOffset.UTC);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Instant.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// STRING {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "text";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return value.toString();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return String.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// TEXT {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "textarea";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return value.toString();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return String.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// BOOLEAN {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "text";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return Boolean.parseBoolean(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Boolean.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.EQ);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// BIG_DECIMAL {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return new BigDecimal(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return BigDecimal.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// CHAR {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "char";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// if (value.toString().isBlank()) return null;
|
||||||
|
// return value.toString().charAt(0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return char.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.STRING_EQ);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// BYTE {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "number";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// return value.toString().getBytes()[0];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return byte.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// throw new DbAdminException("Binary fields are not comparable");
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// BYTE_ARRAY {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "file";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// try {
|
||||||
|
// return ((MultipartFile)value).getBytes();
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// throw new DbAdminException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return byte[].class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// throw new DbAdminException("Binary fields are not comparable");
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// UUID {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "text";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// return java.util.UUID.fromString(value.toString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return java.util.UUID.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.STRING_EQ, CompareOperator.CONTAINS);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// ENUM_STRING {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// return "text";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// if (value == null || value.toString().isBlank()) return null;
|
||||||
|
// try {
|
||||||
|
// Method valueOf = getJavaClass().getMethod("valueOf", String.class);
|
||||||
|
// return valueOf.invoke(null, value.toString());
|
||||||
|
// } catch (NoSuchMethodException | SecurityException | IllegalAccessException
|
||||||
|
// | IllegalArgumentException | InvocationTargetException e) {
|
||||||
|
// throw new DbAdminException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return Enum.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// return List.of(CompareOperator.STRING_EQ);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// ONE_TO_MANY {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return OneToMany.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean isRelationship() {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public String toString() {
|
||||||
|
// return "One to Many";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// throw new DbAdminException();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ONE_TO_ONE {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return OneToOne.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean isRelationship() {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public String toString() {
|
||||||
|
// return "One to One";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// throw new DbAdminException();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// MANY_TO_MANY {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// return ManyToMany.class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean isRelationship() {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public String toString() {
|
||||||
|
// return "Many to Many";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// throw new DbAdminException();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// COMPUTED {
|
||||||
|
// @Override
|
||||||
|
// public String getFragmentName() {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Object parseValue(Object value) {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Class<?> getJavaClass() {
|
||||||
|
// throw new UnsupportedOperationException();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public List<CompareOperator> getCompareOperators() {
|
||||||
|
// throw new DbAdminException();
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the name of the Thymeleaf fragments in the 'inputs.html'
|
||||||
|
// * file, used to render an input field for this specific type.
|
||||||
|
// * For example, a fragment using a file input is used for binary fields.
|
||||||
|
// */
|
||||||
|
// public abstract String getFragmentName();
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Parse the value received through an HTML form into a instance
|
||||||
|
// * of an object of this specific type. This usually involves a conversion
|
||||||
|
// * from string, but, for example, files are sent as MultipartFile instead.
|
||||||
|
// * @param value the value to parse
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// public abstract Object parseValue(Object value);
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the Java class corresponding to this field type.
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// public abstract Class<?> getJavaClass();
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns a list of compare operators that can be used to compare
|
||||||
|
// * two values for this field type. Used in the faceted search to provide
|
||||||
|
// * more operators than just equality (e.g. after/before for dates).
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// public abstract List<CompareOperator> getCompareOperators();
|
||||||
|
//
|
||||||
|
// public boolean isRelationship() {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// private DbFieldType() {
|
||||||
|
////
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// private DbFieldType(String className) {
|
||||||
|
//// this.className = className;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// private String className;
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the corresponding {@linkplain DbFieldType} from a Class object.
|
||||||
|
// * @param klass
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// public static DbFieldType fromClass(Class<?> klass) {
|
||||||
|
// if (klass == Boolean.class || klass == boolean.class) {
|
||||||
|
// return BOOLEAN;
|
||||||
|
// } else if (klass == Long.class || klass == long.class) {
|
||||||
|
// return LONG;
|
||||||
|
// } else if (klass == Integer.class || klass == int.class) {
|
||||||
|
// return INTEGER;
|
||||||
|
// } else if (klass == BigInteger.class) {
|
||||||
|
// return BIG_INTEGER;
|
||||||
|
// } else if (klass == Short.class || klass == short.class) {
|
||||||
|
// return SHORT;
|
||||||
|
// } else if (klass == String.class) {
|
||||||
|
// return STRING;
|
||||||
|
// } else if (klass == LocalDate.class) {
|
||||||
|
// return LOCAL_DATE;
|
||||||
|
// } else if (klass == Date.class) {
|
||||||
|
// return DATE;
|
||||||
|
// } else if (klass == LocalDateTime.class) {
|
||||||
|
// return LOCAL_DATE_TIME;
|
||||||
|
// } else if (klass == Instant.class) {
|
||||||
|
// return INSTANT;
|
||||||
|
// } else if (klass == Float.class || klass == float.class) {
|
||||||
|
// return FLOAT;
|
||||||
|
// } else if (klass == Double.class || klass == double.class) {
|
||||||
|
// return DOUBLE;
|
||||||
|
// } else if (klass == BigDecimal.class) {
|
||||||
|
// return BIG_DECIMAL;
|
||||||
|
// } else if (klass == byte[].class) {
|
||||||
|
// return BYTE_ARRAY;
|
||||||
|
// } else if (klass == OffsetDateTime.class) {
|
||||||
|
// return OFFSET_DATE_TIME;
|
||||||
|
// } else if (klass == byte.class || klass == Byte.class) {
|
||||||
|
// return BYTE;
|
||||||
|
// } else if (klass == java.util.UUID.class) {
|
||||||
|
// return UUID;
|
||||||
|
// } else if (klass == char.class || klass == Character.class) {
|
||||||
|
// return CHAR;
|
||||||
|
// } else if (Enum.class.isAssignableFrom(klass)) {
|
||||||
|
// return ENUM_STRING;
|
||||||
|
// } else {
|
||||||
|
// throw new UnsupportedFieldTypeException("Unsupported field type: " + klass);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
39
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OneToManyFieldType.java
vendored
Normal file
39
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OneToManyFieldType.java
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class OneToManyFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return OneToMany.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRelationship() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "One to Many";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
throw new DbAdminException();
|
||||||
|
}
|
||||||
|
}
|
38
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OneToOneFieldType.java
vendored
Normal file
38
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/OneToOneFieldType.java
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.persistence.OneToOne;
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
|
public class OneToOneFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return OneToOne.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRelationship() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "One to One";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
throw new DbAdminException();
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ShortFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/ShortFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class ShortFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return Short.parseShort(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return Short.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT);
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/StringFieldType.java
vendored
Normal file
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/StringFieldType.java
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class StringFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "text";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ);
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/TextFieldType.java
vendored
Normal file
28
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/TextFieldType.java
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class TextFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "textarea";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
if (value == null || value.toString().isBlank()) return null;
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ);
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/UUIDFieldType.java
vendored
Normal file
27
src/main/java/tech/ailef/dbadmin/external/dbmapping/fields/UUIDFieldType.java
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package tech.ailef.dbadmin.external.dbmapping.fields;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
|
|
||||||
|
public class UUIDFieldType extends DbFieldType {
|
||||||
|
@Override
|
||||||
|
public String getFragmentName() {
|
||||||
|
return "text";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseValue(Object value) {
|
||||||
|
return java.util.UUID.fromString(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getJavaClass() {
|
||||||
|
return java.util.UUID.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CompareOperator> getCompareOperators() {
|
||||||
|
return List.of(CompareOperator.STRING_EQ, CompareOperator.CONTAINS);
|
||||||
|
}
|
||||||
|
}
|
@ -20,12 +20,13 @@
|
|||||||
|
|
||||||
package tech.ailef.dbadmin.external.dbmapping.query;
|
package tech.ailef.dbadmin.external.dbmapping.query;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import tech.ailef.dbadmin.external.DbAdmin;
|
import tech.ailef.dbadmin.external.DbAdmin;
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbField;
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbFieldType;
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbFieldType;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
import tech.ailef.dbadmin.external.exceptions.UnsupportedFieldTypeException;
|
import tech.ailef.dbadmin.external.exceptions.UnsupportedFieldTypeException;
|
||||||
|
|
||||||
@ -127,9 +128,10 @@ public class DbQueryOutputField {
|
|||||||
// If the row this fields belongs to is defined
|
// If the row this fields belongs to is defined
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
try {
|
try {
|
||||||
DbFieldType type = DbFieldType.fromClass(result.get(this).getClass());
|
DbFieldType type = DbFieldType.fromClass(result.get(this).getClass()).getConstructor().newInstance();
|
||||||
return type.toString();
|
return type.toString();
|
||||||
} catch (UnsupportedFieldTypeException e) {
|
} catch (UnsupportedFieldTypeException | InstantiationException | IllegalAccessException |
|
||||||
|
IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ package tech.ailef.dbadmin.external.dto;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbField;
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,8 +26,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbField;
|
|
||||||
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
|
||||||
|
import tech.ailef.dbadmin.external.dbmapping.fields.DbField;
|
||||||
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
import tech.ailef.dbadmin.external.dto.CompareOperator;
|
||||||
import tech.ailef.dbadmin.external.dto.QueryFilter;
|
import tech.ailef.dbadmin.external.dto.QueryFilter;
|
||||||
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
|
||||||
|
@ -77,6 +77,18 @@
|
|||||||
></input>
|
></input>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
<th:block th:fragment="select(field, create, name, value)">
|
||||||
|
<select th:name="${name}" class="form-select">
|
||||||
|
<option value=""
|
||||||
|
th:selected="${value == null}">NULL</option>
|
||||||
|
<option th:each="v : ${field.getType().getValues()}"
|
||||||
|
th:text="${v}"
|
||||||
|
th:value="${v}"
|
||||||
|
th:selected="${value == v}">
|
||||||
|
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</th:block>
|
||||||
<!--
|
<!--
|
||||||
<th:block th:fragment="offset_datetime(field, create, name, value)">
|
<th:block th:fragment="offset_datetime(field, create, name, value)">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user