diff --git a/.classpath b/.classpath
index 827acf2..6c8fcb3 100644
--- a/.classpath
+++ b/.classpath
@@ -23,5 +23,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/kar/archidata/UserDB.java b/src/org/kar/archidata/UserDB.java
index 1e9fb44..a082861 100755
--- a/src/org/kar/archidata/UserDB.java
+++ b/src/org/kar/archidata/UserDB.java
@@ -2,6 +2,7 @@ package org.kar.archidata;
import org.kar.archidata.db.DBEntry;
import org.kar.archidata.model.User;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
import java.io.IOException;
import java.sql.PreparedStatement;
diff --git a/src/org/kar/archidata/annotation/SQLTableLinkGeneric.java b/src/org/kar/archidata/annotation/SQLTableLinkGeneric.java
index b8f9632..e2cbcc6 100644
--- a/src/org/kar/archidata/annotation/SQLTableLinkGeneric.java
+++ b/src/org/kar/archidata/annotation/SQLTableLinkGeneric.java
@@ -11,10 +11,22 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLTableLinkGeneric {
+ public static String AUTOMATIC ="__auto__";
public enum ModelLink {
NONE,
- INTERNAL,
- EXTERNAL
+ INTERNAL, // The list is serialized in a string ',' separated
+ EXTERNAL // an external table is created and
};
+ // Permit to select the link mode.
ModelLink value() default ModelLink.EXTERNAL;
+ // If automatic table name, the table name is: parentTableName_externalTableName__link
+ String tableName() default AUTOMATIC;
+ // If automatic table name, the name of the foreign table is manage with the variable name.
+ String externalTableName() default AUTOMATIC;
+ // If the external link have a field to filter with a specific value (name of the field)
+ String filterField() default AUTOMATIC;
+ // If the external link have a field to filter with a specific value (value of the field)
+ String filterValue() default AUTOMATIC;
+
+
}
diff --git a/src/org/kar/archidata/api/DataResource.java b/src/org/kar/archidata/api/DataResource.java
index 6bb7a46..8a696c9 100644
--- a/src/org/kar/archidata/api/DataResource.java
+++ b/src/org/kar/archidata/api/DataResource.java
@@ -4,7 +4,7 @@ import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.Data;
-import org.kar.archidata.SqlWrapper;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.annotation.security.PermitTokenInURI;
import org.kar.archidata.annotation.security.RolesAllowed;
import org.kar.archidata.util.ConfigBaseVariable;
diff --git a/src/org/kar/archidata/db/DBConfig.java b/src/org/kar/archidata/db/DBConfig.java
index 8fbd47b..6733ea5 100644
--- a/src/org/kar/archidata/db/DBConfig.java
+++ b/src/org/kar/archidata/db/DBConfig.java
@@ -1,6 +1,6 @@
package org.kar.archidata.db;
-import org.kar.archidata.SqlWrapper;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/org/kar/archidata/migration/MigrationEngine.java b/src/org/kar/archidata/migration/MigrationEngine.java
index ff32eb9..62736b6 100644
--- a/src/org/kar/archidata/migration/MigrationEngine.java
+++ b/src/org/kar/archidata/migration/MigrationEngine.java
@@ -5,9 +5,9 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
-import org.kar.archidata.SqlWrapper;
import org.kar.archidata.db.DBConfig;
import org.kar.archidata.db.DBEntry;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/org/kar/archidata/migration/MigrationSqlStep.java b/src/org/kar/archidata/migration/MigrationSqlStep.java
index 94f24b5..d3b956f 100644
--- a/src/org/kar/archidata/migration/MigrationSqlStep.java
+++ b/src/org/kar/archidata/migration/MigrationSqlStep.java
@@ -5,8 +5,8 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
-import org.kar.archidata.SqlWrapper;
import org.kar.archidata.db.DBEntry;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/org/kar/archidata/SqlWrapper.java b/src/org/kar/archidata/sqlWrapper/SqlWrapper.java
similarity index 95%
rename from src/org/kar/archidata/SqlWrapper.java
rename to src/org/kar/archidata/sqlWrapper/SqlWrapper.java
index 9bb672e..f2d5da7 100644
--- a/src/org/kar/archidata/SqlWrapper.java
+++ b/src/org/kar/archidata/sqlWrapper/SqlWrapper.java
@@ -1,4 +1,4 @@
-package org.kar.archidata;
+package org.kar.archidata.sqlWrapper;
import java.io.IOException;
import java.lang.annotation.Annotation;
@@ -11,6 +11,7 @@ import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
+import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.annotation.SQLAutoIncrement;
import org.kar.archidata.annotation.SQLComment;
import org.kar.archidata.annotation.SQLIfNotExists;
@@ -38,6 +39,11 @@ import org.kar.archidata.annotation.SQLDeleted;
public class SqlWrapper {
static final Logger LOGGER = LoggerFactory.getLogger(SqlWrapper.class);
+ static final List addOn = new ArrayList<>();
+
+ public static void addAddOn(SqlWrapperAddOn addOn) {
+ SqlWrapper.addOn.add(addOn);
+ };
public static class ExceptionDBInterface extends Exception {
private static final long serialVersionUID = 1L;
@@ -395,6 +401,10 @@ public class SqlWrapper {
boolean firstField = true;
int count = 0;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
continue;
@@ -445,6 +455,10 @@ public class SqlWrapper {
Field primaryKeyField = null;
int iii = 1;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
primaryKeyField = elem;
@@ -567,6 +581,10 @@ public class SqlWrapper {
boolean firstField = true;
Field primaryKeyField = null;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
primaryKeyField = elem;
@@ -615,6 +633,10 @@ public class SqlWrapper {
PreparedStatement ps = entry.connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);
int iii = 1;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
continue;
@@ -822,6 +844,10 @@ public class SqlWrapper {
int count = 0;
boolean hasDeleted = false;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
ModelLink linkGeneric = getLinkMode(elem);
if (linkGeneric != ModelLink.NONE) {
continue;
@@ -879,6 +905,10 @@ public class SqlWrapper {
Object data = clazz.getConstructors()[0].newInstance();
count = 1;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
ModelLink linkGeneric = getLinkMode(elem);
if (linkGeneric != ModelLink.NONE) {
continue;
@@ -913,6 +943,10 @@ public class SqlWrapper {
public static T get(Class clazz, long id) throws Exception {
Field primaryKeyField = null;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
primaryKeyField = elem;
@@ -948,13 +982,20 @@ public class SqlWrapper {
int count = 0;
StateLoad[] autoClasify = new StateLoad[clazz.getFields().length];
int indexAutoClasify = 0;
+ boolean hasDeleted = false;
for (Field elem : clazz.getFields()) {
-
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
boolean notRead = elem.getDeclaredAnnotationsByType(SQLNotRead.class).length != 0;
if (!full && notRead) {
autoClasify[indexAutoClasify++] = StateLoad.DISABLE;
continue;
}
+ if (!hasDeleted) {
+ hasDeleted = elem.getDeclaredAnnotationsByType(SQLDeleted.class).length != 0;
+ }
String name = elem.getName();
count++;
if (firstField) {
@@ -962,6 +1003,8 @@ public class SqlWrapper {
} else {
query.append(",");
}
+
+
ModelLink linkGeneric = getLinkMode(elem);
if (linkGeneric == ModelLink.EXTERNAL) {
autoClasify[indexAutoClasify++] = StateLoad.ARRAY;
@@ -1017,14 +1060,16 @@ public class SqlWrapper {
query.append(" FROM `");
query.append(tableName);
query.append("` ");
- query.append(" WHERE ");
- //query.append(tableName);
- //query.append(".");
- //query.append(primaryKeyField.getName());
- //query.append(" = ?");
- //query.append(" AND ");
- query.append(tableName);
- query.append(".deleted = false ");
+ if (hasDeleted) {
+ query.append(" WHERE ");
+ //query.append(tableName);
+ //query.append(".");
+ //query.append(primaryKeyField.getName());
+ //query.append(" = ?");
+ //query.append(" AND ");
+ query.append(tableName);
+ query.append(".deleted = false ");
+ }
firstField = true;
LOGGER.debug("generate the querry: '{}'", query.toString());
LOGGER.debug("request get {} prepare @{}", clazz.getCanonicalName(), getCurrentTimeStamp());
@@ -1041,6 +1086,9 @@ public class SqlWrapper {
Object data = clazz.getConstructors()[0].newInstance();
count = 1;
for (Field elem : clazz.getFields()) {
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
/*
boolean notRead = elem.getDeclaredAnnotationsByType(SQLNotRead.class).length != 0;
*/
@@ -1255,6 +1303,10 @@ public class SqlWrapper {
LOGGER.debug("===> TABLE `{}`", tableName);
String primaryKeyValue = null;
for (Field elem : clazz.getFields()) {
+ // static field is only for internal global declaration ==> remove it ..
+ if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
String name = elem.getName();
Integer limitSize = getLimitSize(elem);
@@ -1373,8 +1425,8 @@ public class SqlWrapper {
out.append(" ");
}
if (updateTime) {
- out.append("ON UPDATE CURRENT_TIMESTAMP");
if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ out.append("ON UPDATE CURRENT_TIMESTAMP");
out.append("(3)");
}
out.append(" ");
@@ -1388,8 +1440,8 @@ public class SqlWrapper {
}
out.append(" ");
if (updateTime) {
- out.append("ON UPDATE CURRENT_TIMESTAMP");
if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ out.append("ON UPDATE CURRENT_TIMESTAMP");
out.append("(3)");
}
out.append(" ");
diff --git a/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java b/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java
new file mode 100644
index 0000000..35ad376
--- /dev/null
+++ b/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java
@@ -0,0 +1,24 @@
+package org.kar.archidata.sqlWrapper;
+
+import java.lang.reflect.Field;
+
+public interface SqlWrapperAddOn {
+ /**
+ * Get the Class of the declaration annotation
+ * @return The annotation class
+ */
+ Class> getAnnotationClass();
+ /**
+ * Get the SQL type that is needed to declare for the specific Field Type.
+ * @param elem Field to declare.
+ * @return SQL type to create.
+ */
+ String getSQLFieldType(Field elem);
+ /**
+ * Check if the field is manage by the local add-on
+ * @param elem Field to inspect.
+ * @return True of the field is manage by the current Add-on.
+ */
+ boolean isCompatibleField(Field elem);
+
+}
diff --git a/src/org/kar/archidata/WhereCondition.java b/src/org/kar/archidata/sqlWrapper/WhereCondition.java
similarity index 69%
rename from src/org/kar/archidata/WhereCondition.java
rename to src/org/kar/archidata/sqlWrapper/WhereCondition.java
index 5c325d7..86f7f5b 100644
--- a/src/org/kar/archidata/WhereCondition.java
+++ b/src/org/kar/archidata/sqlWrapper/WhereCondition.java
@@ -1,4 +1,4 @@
-package org.kar.archidata;
+package org.kar.archidata.sqlWrapper;
public record WhereCondition(
String key,
diff --git a/src/org/kar/archidata/sqlWrapper/addOn/ExternalLink.java b/src/org/kar/archidata/sqlWrapper/addOn/ExternalLink.java
new file mode 100644
index 0000000..c040a91
--- /dev/null
+++ b/src/org/kar/archidata/sqlWrapper/addOn/ExternalLink.java
@@ -0,0 +1,21 @@
+package org.kar.archidata.sqlWrapper.addOn;
+
+import java.lang.reflect.Field;
+
+import org.kar.archidata.annotation.SQLTableLinkGeneric;
+import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
+
+public class ExternalLink implements SqlWrapperAddOn {
+
+ @Override
+ public Class> getAnnotationClass() {
+ return SQLTableLinkGeneric.class;
+ }
+ public String getSQLFieldType(Field elem) {
+ return "STRING";
+ }
+ public boolean isCompatibleField(Field elem) {
+ SQLTableLinkGeneric decorators = elem.getDeclaredAnnotation(SQLTableLinkGeneric.class);
+ return decorators != null;
+ }
+}
diff --git a/src/org/kar/archidata/util/DataTools.java b/src/org/kar/archidata/util/DataTools.java
index 9aa48b9..5954e4d 100644
--- a/src/org/kar/archidata/util/DataTools.java
+++ b/src/org/kar/archidata/util/DataTools.java
@@ -15,8 +15,8 @@ import java.sql.SQLException;
import jakarta.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
-import org.kar.archidata.SqlWrapper;
import org.kar.archidata.model.Data;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;