diff --git a/pom.xml b/pom.xml
index 9949de5..a799c1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -96,7 +96,7 @@
org.glassfish.jersey.test-framework.providers
jersey-test-framework-provider-grizzly2
- test
+ test
org.glassfish.jersey.media
diff --git a/src/org/kar/archidata/annotation/addOn/DataAddOnManyToManyOrdered.java b/src/org/kar/archidata/annotation/addOn/DataAddOnManyToManyOrdered.java
new file mode 100644
index 0000000..8a19385
--- /dev/null
+++ b/src/org/kar/archidata/annotation/addOn/DataAddOnManyToManyOrdered.java
@@ -0,0 +1,15 @@
+package org.kar.archidata.annotation.addOn;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.kar.archidata.annotation.DataAddOn;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@DataAddOn
+public @interface DataAddOnManyToManyOrdered {
+
+}
diff --git a/src/org/kar/archidata/migration/MigrationSqlStep.java b/src/org/kar/archidata/migration/MigrationSqlStep.java
index 2ce21d4..2eb06ae 100644
--- a/src/org/kar/archidata/migration/MigrationSqlStep.java
+++ b/src/org/kar/archidata/migration/MigrationSqlStep.java
@@ -7,12 +7,25 @@ import java.util.List;
import org.kar.archidata.db.DBEntry;
import org.kar.archidata.sqlWrapper.SqlWrapper;
+import org.kar.archidata.util.ConfigBaseVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+record Action(
+ String action,
+ List filterDB) {
+ public Action(String action) {
+ this(action, List.of());
+ }
+
+ public Action(String action, String filterDB) {
+ this(action, List.of(filterDB));
+ }
+}
+
public class MigrationSqlStep implements MigrationInterface {
final static Logger LOGGER = LoggerFactory.getLogger(MigrationSqlStep.class);
- private final List actions = new ArrayList<>();
+ private final List actions = new ArrayList<>();
@Override
public String getName() {
@@ -21,8 +34,8 @@ public class MigrationSqlStep implements MigrationInterface {
public void display() {
for (int iii = 0; iii < this.actions.size(); iii++) {
- final String action = this.actions.get(iii);
- LOGGER.info(" >>>> SQL ACTION : {}/{} ==> \n{}", iii, this.actions.size(), action);
+ final Action action = this.actions.get(iii);
+ LOGGER.info(" >>>> SQL ACTION : {}/{} ==> filter='{}'\n{}", iii, this.actions.size(), action.filterDB(), action.action());
}
}
@@ -31,11 +44,26 @@ public class MigrationSqlStep implements MigrationInterface {
for (int iii = 0; iii < this.actions.size(); iii++) {
log.append("action [" + (iii + 1) + "/" + this.actions.size() + "]\n");
LOGGER.info(" >>>> SQL ACTION : {}/{}", iii + 1, this.actions.size());
- final String action = this.actions.get(iii);
- LOGGER.info("SQL request: ```{}```", action);
- log.append("SQL: " + action + "\n");
+ final Action action = this.actions.get(iii);
+
+ LOGGER.info("SQL request: ```{}``` on '{}' current={}", action.action(), action.filterDB(), ConfigBaseVariable.getDBType());
+ log.append("SQL: " + action.action() + " on " + action.filterDB() + "\n");
+ boolean isValid = true;
+ if (action.filterDB() != null && action.filterDB().size() > 0) {
+ isValid = false;
+ for (String elem : action.filterDB()) {
+ if (ConfigBaseVariable.getDBType().equals(elem)) {
+ isValid = true;
+ }
+ }
+ }
+ if (!isValid) {
+ log.append("==> Skip (DB is not compatible: " + ConfigBaseVariable.getDBType() + ")\n");
+ LOGGER.info(" >>>> SQL ACTION : {}/{} ==> SKIP", iii + 1, this.actions.size());
+ continue;
+ }
try {
- SqlWrapper.executeQuerry(action);
+ SqlWrapper.executeQuerry(action.action());
} catch (SQLException | IOException ex) {
ex.printStackTrace();
LOGGER.info("SQL request ERROR: ", ex.getMessage());
@@ -75,12 +103,18 @@ public class MigrationSqlStep implements MigrationInterface {
}
public void addAction(final String action) {
- this.actions.add(action);
+ this.actions.add(new Action(action));
+ }
+
+ public void addAction(final String action, String filterdBType) {
+ this.actions.add(new Action(action, filterdBType));
}
public void addClass(final Class> clazz) throws Exception {
final List tmp = SqlWrapper.createTable(clazz, false);
- this.actions.addAll(tmp);
+ for (String elem : tmp) {
+ this.actions.add(new Action(elem));
+ }
}
@Override
diff --git a/src/org/kar/archidata/sqlWrapper/SqlWrapper.java b/src/org/kar/archidata/sqlWrapper/SqlWrapper.java
index 7c2ca36..6dc3fd2 100644
--- a/src/org/kar/archidata/sqlWrapper/SqlWrapper.java
+++ b/src/org/kar/archidata/sqlWrapper/SqlWrapper.java
@@ -169,6 +169,27 @@ public class SqlWrapper {
throw new InternalServerErrorException("Can Not manage the DB-access");
}
+ /**
+ * extract a list of "-" separated element from a SQL input data.
+ * @param rs Result Set of the BDD
+ * @param iii Id in the result set
+ * @return The list of Long value
+ * @throws SQLException if an error is generated in the sql request.
+ */
+ public static List getListOfIds(ResultSet rs, int iii, String separator) throws SQLException {
+ String trackString = rs.getString(iii);
+ if (rs.wasNull()) {
+ return null;
+ }
+ List out = new ArrayList<>();
+ String[] elements = trackString.split("-");
+ for (String elem : elements) {
+ Long tmp = Long.parseLong(elem);
+ out.add(tmp);
+ }
+ return out;
+ }
+
public static String convertTypeInSQL(final Class> type) throws Exception {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
if (type == Long.class || type == long.class) {
@@ -212,10 +233,10 @@ public class SqlWrapper {
return "REAL";
}
if (type == Timestamp.class) {
- return "INTEGER";
+ return "DATETIME";
}
if (type == Date.class) {
- return "NUMERIC";
+ return "DATETIME";
}
if (type == String.class) {
return "text";
@@ -369,11 +390,26 @@ public class SqlWrapper {
field.setBoolean(data, tmp);
}
} else if (type == Timestamp.class) {
- final Timestamp tmp = rs.getTimestamp(index);
- if (rs.wasNull()) {
- field.set(data, null);
- } else {
- field.set(data, tmp);
+ try {
+ final Timestamp tmp = rs.getTimestamp(index);
+ if (rs.wasNull()) {
+ field.set(data, null);
+ } else {
+ field.set(data, tmp);
+ }
+ } catch (java.sql.SQLException ex) {
+ try {
+ final Date tmp = rs.getDate(index);
+ if (rs.wasNull()) {
+
+ field.set(data, null);
+ } else {
+ field.set(data, new Timestamp(tmp.toInstant().toEpochMilli()));
+ }
+ } catch (java.sql.SQLException ex2) {
+ final String tmp = rs.getString(index);
+ LOGGER.error("plop {}", tmp);
+ }
}
} else if (type == Date.class) {
final Date tmp = rs.getDate(index);
@@ -853,7 +889,7 @@ public class SqlWrapper {
continue;
}
final SqlWrapperAddOn addOn = findAddOnforField(elem);
- if (addOn != null) {
+ if (addOn != null && addOn.isExternal()) {
continue;
}
// TODO: Manage it with AddOn
@@ -872,10 +908,13 @@ public class SqlWrapper {
querry.append(",");
}
querry.append(" ");
- querry.append(tableName);
- querry.append(".");
-
- querry.append(name);
+ if (addOn != null) {
+ addOn.generateQuerry(tableName, elem, querry, name, count, options);
+ } else {
+ querry.append(tableName);
+ querry.append(".");
+ querry.append(name);
+ }
}
querry.append(" FROM `");
querry.append(tableName);
@@ -906,7 +945,7 @@ public class SqlWrapper {
continue;
}
final SqlWrapperAddOn addOn = findAddOnforField(elem);
- if (addOn != null) {
+ if (addOn != null && addOn.isExternal()) {
continue;
}
// TODO: Manage it with AddOn
@@ -914,8 +953,13 @@ public class SqlWrapper {
if (!readAllfields && notRead) {
continue;
}
- setValueFromDb(elem.getType(), data, count, elem, rs);
- count++;
+ if (addOn != null) {
+ int nbRowRead = addOn.fillFromQuerry(rs, elem, data, count, options);
+ count += nbRowRead;
+ } else {
+ setValueFromDb(elem.getType(), data, count, elem, rs);
+ count++;
+ }
}
final T out = (T) data;
outs.add(out);
@@ -1063,8 +1107,8 @@ public class SqlWrapper {
return createTable(clazz, true);
}
- public static void createTablesSpecificType(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List ListOtherTables, final boolean createIfNotExist,
- final boolean createDrop, final int fieldId, final Class> classModel) throws Exception {
+ public static void createTablesSpecificType(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List preOtherTables, final List postOtherTables,
+ final boolean createIfNotExist, final boolean createDrop, final int fieldId, final Class> classModel) throws Exception {
final String name = AnnotationTools.getFieldName(elem);
final Integer limitSize = AnnotationTools.getLimitSize(elem);
final boolean notNull = AnnotationTools.getNotNull(elem);
@@ -1117,7 +1161,29 @@ public class SqlWrapper {
if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
mainTableBuilder.append("ON UPDATE CURRENT_TIMESTAMP");
mainTableBuilder.append("(3)");
+ } else {
+ // TODO: add trigger:
+ /*
+ CREATE TRIGGER your_table_trig AFTER UPDATE ON your_table
+ BEGIN
+ update your_table SET updated_on = datetime('now') WHERE user_id = NEW.user_id;
+ END;
+ */
+ StringBuilder triggerBuilder = new StringBuilder();
+ triggerBuilder.append("CREATE TRIGGER ");
+ triggerBuilder.append(tableName);
+ triggerBuilder.append("_update_trigger AFTER UPDATE ON ");
+ triggerBuilder.append(tableName);
+ triggerBuilder.append(" \nBEGIN \n update ");
+ triggerBuilder.append(tableName);
+ triggerBuilder.append(" SET ");
+ triggerBuilder.append(name);
+ triggerBuilder.append(" = datetime('now') WHERE id = NEW.id; \n");
+ triggerBuilder.append("END;");
+
+ postOtherTables.add(triggerBuilder.toString());
}
+
mainTableBuilder.append(" ");
}
} else {
@@ -1178,7 +1244,8 @@ public class SqlWrapper {
public static List createTable(final Class> clazz, final boolean createDrop) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz);
final boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
- final List outList = new ArrayList<>();
+ final List preActionList = new ArrayList<>();
+ final List postActionList = new ArrayList<>();
final StringBuilder out = new StringBuilder();
// Drop Table
if (createIfNotExist && createDrop) {
@@ -1186,7 +1253,7 @@ public class SqlWrapper {
tableTmp.append("DROP TABLE IF EXISTS `");
tableTmp.append(tableName);
tableTmp.append("`;");
- outList.add(tableTmp.toString());
+ postActionList.add(tableTmp.toString());
}
// create Table:
out.append("CREATE TABLE `");
@@ -1212,13 +1279,13 @@ public class SqlWrapper {
final SqlWrapperAddOn addOn = findAddOnforField(elem);
LOGGER.info("Create type for: {} ==> {} (ADD-ON)", AnnotationTools.getFieldName(elem), elem.getType());
if (addOn != null) {
- addOn.createTables(tableName, elem, out, outList, createIfNotExist, createDrop, fieldId);
+ addOn.createTables(tableName, elem, out, preActionList, postActionList, createIfNotExist, createDrop, fieldId);
} else {
throw new Exception("Element matked as add-on but add-on does not loaded: table:" + tableName + " field name=" + AnnotationTools.getFieldName(elem) + " type=" + elem.getType());
}
} else {
LOGGER.info("Create type for: {} ==> {}", AnnotationTools.getFieldName(elem), elem.getType());
- SqlWrapper.createTablesSpecificType(tableName, elem, out, outList, createIfNotExist, createDrop, fieldId, elem.getType());
+ SqlWrapper.createTablesSpecificType(tableName, elem, out, preActionList, postActionList, createIfNotExist, createDrop, fieldId, elem.getType());
}
fieldId++;
}
@@ -1237,8 +1304,9 @@ public class SqlWrapper {
out.append(" ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci");
}
out.append(";");
- outList.add(out.toString());
- return outList;
+ preActionList.add(out.toString());
+ preActionList.addAll(postActionList);
+ return preActionList;
}
}
\ No newline at end of file
diff --git a/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java b/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java
index a3803dc..b0bcf98 100644
--- a/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java
+++ b/src/org/kar/archidata/sqlWrapper/SqlWrapperAddOn.java
@@ -6,6 +6,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
+import jakarta.validation.constraints.NotNull;
+
public interface SqlWrapperAddOn {
/**
* Get the Class of the declaration annotation
@@ -27,17 +29,38 @@ public interface SqlWrapperAddOn {
*/
boolean isCompatibleField(Field elem);
+ /**
+ * Insert data in the specific field (the field must be in the current db, otherwiise it does not work at all.
+ * @param ps DB statement interface.
+ * @param data The date to inject.
+ * @param iii The index of injection
+ * @return the new index of injection in case of multiple value management
+ * @throws SQLException
+ */
int insertData(PreparedStatement ps, Object data, int iii) throws SQLException;
// External mean that the type of the object is absolutely not obvious...
boolean isExternal();
- int generateQuerry(String tableName, Field elem, StringBuilder querry, String name, List autoClasify, QuerryOptions options);
+ int generateQuerry(@NotNull String tableName, @NotNull Field elem, @NotNull StringBuilder querry, @NotNull String name, @NotNull int elemCount, QuerryOptions options);
+ // Return the number of colomn read
int fillFromQuerry(ResultSet rs, Field elem, Object data, int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException;
boolean canUpdate();
- void createTables(String tableName, Field elem, StringBuilder mainTableBuilder, List ListOtherTables, boolean createIfNotExist, boolean createDrop, int fieldId) throws Exception;
+ /**
+ * Create associated table of the specific element.
+ * @param tableName
+ * @param elem
+ * @param mainTableBuilder
+ * @param ListOtherTables
+ * @param createIfNotExist
+ * @param createDrop
+ * @param fieldId
+ * @throws Exception
+ */
+ void createTables(String tableName, Field elem, StringBuilder mainTableBuilder, List preActionList, List postActionList, boolean createIfNotExist, boolean createDrop, int fieldId)
+ throws Exception;
}
diff --git a/src/org/kar/archidata/sqlWrapper/StateLoad.java b/src/org/kar/archidata/sqlWrapper/StateLoad.java
deleted file mode 100644
index 08f6519..0000000
--- a/src/org/kar/archidata/sqlWrapper/StateLoad.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.kar.archidata.sqlWrapper;
-
-public enum StateLoad {
- DISABLE, NORMAL, ARRAY
-}
\ No newline at end of file
diff --git a/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToMany.java b/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToMany.java
index 71c861e..60b099a 100644
--- a/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToMany.java
+++ b/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToMany.java
@@ -5,10 +5,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
-import java.sql.Types;
-import java.util.ArrayList;
import java.util.List;
-import java.util.stream.Collectors;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.annotation.AnnotationTools;
@@ -17,46 +14,16 @@ import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.SqlWrapper.ExceptionDBInterface;
import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
-import org.kar.archidata.sqlWrapper.StateLoad;
import org.kar.archidata.util.ConfigBaseVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.persistence.ManyToMany;
+import jakarta.validation.constraints.NotNull;
public class AddOnManyToMany implements SqlWrapperAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
-
- /**
- * Convert the list if external id in a string '-' separated
- * @param ids List of value (null are removed)
- * @return '-' string separated
- */
- protected static String getStringOfIds(final List ids) {
- final List tmp = new ArrayList<>(ids);
- return tmp.stream().map(String::valueOf).collect(Collectors.joining("-"));
- }
-
- /**
- * extract a list of "-" separated element from a SQL input data.
- * @param rs Result Set of the BDD
- * @param iii Id in the result set
- * @return The list of Long value
- * @throws SQLException if an error is generated in the sql request.
- */
- protected static List getListOfIds(final ResultSet rs, final int iii) throws SQLException {
- final String trackString = rs.getString(iii);
- if (rs.wasNull()) {
- return null;
- }
- final List out = new ArrayList<>();
- final String[] elements = trackString.split("-");
- for (final String elem : elements) {
- final Long tmp = Long.parseLong(elem);
- out.add(tmp);
- }
- return out;
- }
+ static final String SEPARATOR = "-";
@Override
public Class> getAnnotationClass() {
@@ -76,15 +43,7 @@ public class AddOnManyToMany implements SqlWrapperAddOn {
@Override
public int insertData(final PreparedStatement ps, final Object data, int iii) throws SQLException {
- if (data == null) {
- ps.setNull(iii++, Types.BIGINT);
- } else {
- // TODO: we must check if the model of data in a list of Long ... !!!!
- @SuppressWarnings("unchecked")
- final String dataTmp = getStringOfIds((List) data);
- ps.setString(iii++, dataTmp);
- }
- return iii++;
+ return iii;
}
@Override
@@ -94,19 +53,26 @@ public class AddOnManyToMany implements SqlWrapperAddOn {
}
@Override
- public int generateQuerry(final String tableName, final Field elem, final StringBuilder querry, final String name, final List autoClasify, QuerryOptions options) {
-
- autoClasify.add(StateLoad.ARRAY);
+ public int generateQuerry(@NotNull final String tableName, @NotNull final Field elem, @NotNull final StringBuilder querry, @NotNull final String name, @NotNull final int elemCount,
+ QuerryOptions options) {
String localName = name;
if (name.endsWith("s")) {
localName = name.substring(0, name.length() - 1);
}
- final String tmpVariable = "tmp_" + Integer.toString(autoClasify.size());
+ final String tmpVariable = "tmp_" + Integer.toString(elemCount);
querry.append(" (SELECT GROUP_CONCAT(");
querry.append(tmpVariable);
querry.append(".");
querry.append(localName);
- querry.append("_id SEPARATOR '-') FROM ");
+ querry.append("_id ");
+ if (ConfigBaseVariable.getDBType().equals("sqlite")) {
+ querry.append(", ");
+ } else {
+ querry.append("SEPARATOR ");
+ }
+ querry.append("'");
+ querry.append(SEPARATOR);
+ querry.append("') FROM ");
querry.append(tableName);
querry.append("_link_");
querry.append(localName);
@@ -139,7 +105,9 @@ public class AddOnManyToMany implements SqlWrapperAddOn {
@Override
public int fillFromQuerry(final ResultSet rs, final Field elem, final Object data, final int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException {
- throw new IllegalAccessException("This Add-on has not the capability to insert data directly in DB");
+ List idList = SqlWrapper.getListOfIds(rs, count, SEPARATOR);
+ elem.set(data, idList);
+ return 1;
}
@Override
@@ -208,8 +176,8 @@ public class AddOnManyToMany implements SqlWrapperAddOn {
// TODO : refacto this table to manage a generic table with dynamic name to be serializable with the default system
@Override
- public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List ListOtherTables, final boolean createIfNotExist,
- final boolean createDrop, final int fieldId) throws Exception {
+ public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List preActionList, List postActionList,
+ final boolean createIfNotExist, final boolean createDrop, final int fieldId) throws Exception {
final String name = AnnotationTools.getFieldName(elem);
String localName = name;
if (name.endsWith("s")) {
@@ -222,7 +190,7 @@ public class AddOnManyToMany implements SqlWrapperAddOn {
tableTmp.append("_link_");
tableTmp.append(localName);
tableTmp.append("`;");
- ListOtherTables.add(tableTmp.toString());
+ postActionList.add(tableTmp.toString());
}
final StringBuilder otherTable = new StringBuilder();
otherTable.append("CREATE TABLE `");
@@ -263,6 +231,6 @@ public class AddOnManyToMany implements SqlWrapperAddOn {
otherTable.append(" ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n\n");
}
otherTable.append(";");
- ListOtherTables.add(otherTable.toString());
+ postActionList.add(otherTable.toString());
}
}
diff --git a/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToManyOrdered.java b/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToManyOrdered.java
new file mode 100644
index 0000000..14000fc
--- /dev/null
+++ b/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToManyOrdered.java
@@ -0,0 +1,235 @@
+package org.kar.archidata.sqlWrapper.addOn;
+
+import java.lang.reflect.Field;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+
+import org.kar.archidata.GlobalConfiguration;
+import org.kar.archidata.annotation.AnnotationTools;
+import org.kar.archidata.annotation.addOn.DataAddOnManyToManyOrdered;
+import org.kar.archidata.db.DBEntry;
+import org.kar.archidata.sqlWrapper.QuerryOptions;
+import org.kar.archidata.sqlWrapper.SqlWrapper;
+import org.kar.archidata.sqlWrapper.SqlWrapper.ExceptionDBInterface;
+import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
+import org.kar.archidata.util.ConfigBaseVariable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.validation.constraints.NotNull;
+
+/**
+ * Manage the decorator element @DataAddOnManyToManyOrdered to be injected in the DB.
+ * The objective of this table is to manage a link between 2 table that have a specific order (Only work in 1 direction)
+ */
+public class AddOnManyToManyOrdered implements SqlWrapperAddOn {
+ static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToManyOrdered.class);
+ static final String SEPARATOR = "-";
+
+ @Override
+ public Class> getAnnotationClass() {
+ return DataAddOnManyToManyOrdered.class;
+ }
+
+ @Override
+ public String getSQLFieldType(final Field elem) {
+ return null;
+ }
+
+ @Override
+ public boolean isCompatibleField(final Field elem) {
+ final DataAddOnManyToManyOrdered decorators = elem.getDeclaredAnnotation(DataAddOnManyToManyOrdered.class);
+ return decorators != null;
+ }
+
+ @Override
+ public int insertData(final PreparedStatement ps, final Object data, int iii) throws SQLException {
+ return iii;
+ }
+
+ @Override
+ public boolean isExternal() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int generateQuerry(@NotNull String tableName, @NotNull Field elem, @NotNull StringBuilder querry, @NotNull String name, @NotNull int elemCount, QuerryOptions options) {
+ String localName = name;
+ if (name.endsWith("s")) {
+ localName = name.substring(0, name.length() - 1);
+ }
+ final String tmpVariable = "tmp_" + Integer.toString(elemCount);
+ querry.append(" (SELECT GROUP_CONCAT(");
+ querry.append(tmpVariable);
+ querry.append(".");
+ querry.append(localName);
+ querry.append("_id ");
+ if (ConfigBaseVariable.getDBType().equals("sqlite")) {
+ querry.append(", ");
+ } else {
+ querry.append("SEPARATOR ");
+ }
+ querry.append("'");
+ querry.append(SEPARATOR);
+ querry.append("') FROM ");
+ querry.append(tableName);
+ querry.append("_link_");
+ querry.append(localName);
+ querry.append(" ");
+ querry.append(tmpVariable);
+ querry.append(" WHERE ");
+ querry.append(tmpVariable);
+ querry.append(".deleted = false AND ");
+ querry.append(tableName);
+ querry.append(".id = ");
+ querry.append(tmpVariable);
+ querry.append(".");
+ querry.append(tableName);
+ querry.append("_id ORDER BY ");
+ querry.append(tmpVariable);
+ querry.append(".order ASC");
+ querry.append(" GROUP BY ");
+ querry.append(tmpVariable);
+ querry.append(".");
+ querry.append(tableName);
+ querry.append("_id ) AS ");
+ querry.append(name);
+ querry.append(" ");
+ return 1;
+ }
+
+ @Override
+ public int fillFromQuerry(final ResultSet rs, final Field elem, final Object data, final int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException {
+ //throw new IllegalAccessException("This Add-on has not the capability to insert data directly in DB");
+ return 0;
+ }
+
+ @Override
+ public boolean canUpdate() {
+ return false;
+ }
+
+ public static void addLink(final Class> clazz, final long localKey, final String table, final long remoteKey) throws Exception {
+ final String tableName = AnnotationTools.getTableName(clazz);
+ DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
+ long uniqueSQLID = -1;
+ // real add in the BDD:
+ try {
+ // prepare the request:
+ final String querry = "INSERT INTO " + tableName + "_link_" + table + " (create_date, modify_date, " + tableName + "_id, " + table + "_id)" + " VALUES (" + SqlWrapper.getDBNow() + ", "
+ + SqlWrapper.getDBNow() + ", ?, ?)";
+ final PreparedStatement ps = entry.connection.prepareStatement(querry, Statement.RETURN_GENERATED_KEYS);
+ int iii = 1;
+ ps.setLong(iii++, localKey);
+ ps.setLong(iii++, remoteKey);
+ // execute the request
+ final int affectedRows = ps.executeUpdate();
+ if (affectedRows == 0) {
+ throw new SQLException("Creating data failed, no rows affected.");
+ }
+ // retrieve uid inserted
+ try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
+ if (generatedKeys.next()) {
+ uniqueSQLID = generatedKeys.getLong(1);
+ } else {
+ throw new SQLException("Creating user failed, no ID obtained (1).");
+ }
+ } catch (final Exception ex) {
+ LOGGER.debug("Can not get the UID key inserted ... ");
+ ex.printStackTrace();
+ throw new SQLException("Creating user failed, no ID obtained (2).");
+ }
+ } catch (final SQLException ex) {
+ ex.printStackTrace();
+ throw new ExceptionDBInterface(500, "SQL error: " + ex.getMessage());
+ } finally {
+ entry.close();
+ entry = null;
+ }
+ }
+
+ public static void removeLink(final Class> clazz, final long localKey, final String table, final long remoteKey) throws Exception {
+ final String tableName = AnnotationTools.getTableName(clazz);
+ DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig);
+ final String querry = "UPDATE `" + tableName + "_link_" + table + "` SET `modify_date`=" + SqlWrapper.getDBNow() + ", `deleted`=true WHERE `" + tableName + "_id` = ? AND `" + table
+ + "_id` = ?";
+ try {
+ final PreparedStatement ps = entry.connection.prepareStatement(querry);
+ int iii = 1;
+ ps.setLong(iii++, localKey);
+ ps.setLong(iii++, remoteKey);
+ ps.executeUpdate();
+ } catch (final SQLException ex) {
+ ex.printStackTrace();
+ throw new ExceptionDBInterface(500, "SQL error: " + ex.getMessage());
+ } finally {
+ entry.close();
+ entry = null;
+ }
+ }
+
+ // TODO : refacto this table to manage a generic table with dynamic name to be serializable with the default system
+ @Override
+ public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List preActionList, List postActionList,
+ final boolean createIfNotExist, final boolean createDrop, final int fieldId) throws Exception {
+ final String name = AnnotationTools.getFieldName(elem);
+ String localName = name;
+ if (name.endsWith("s")) {
+ localName = name.substring(0, name.length() - 1);
+ }
+ if (createIfNotExist && createDrop) {
+ final StringBuilder tableTmp = new StringBuilder();
+ tableTmp.append("DROP TABLE IF EXISTS `");
+ tableTmp.append(tableName);
+ tableTmp.append("_link_");
+ tableTmp.append(localName);
+ tableTmp.append("`;");
+ postActionList.add(tableTmp.toString());
+ }
+ final StringBuilder otherTable = new StringBuilder();
+ otherTable.append("CREATE TABLE `");
+ otherTable.append(tableName);
+ otherTable.append("_link_");
+ otherTable.append(localName);
+ otherTable.append("`(\n");
+ if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ otherTable.append("\t\t`id` bigint NOT NULL AUTO_INCREMENT,\n");
+ otherTable.append("\t\t`deleted` tinyint(1) NOT NULL DEFAULT '0',\n");
+ otherTable.append("\t\t`createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n");
+ otherTable.append("\t\t`updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n");
+ } else {
+ otherTable.append("\t\t`id` INTEGER PRIMARY KEY AUTOINCREMENT,\n");
+ otherTable.append("\t\t`deleted` INTEGER NOT NULL DEFAULT '0',\n");
+ otherTable.append("\t\t`createdAt` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,\n");
+ otherTable.append("\t\t`updatedAt` INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,\n");
+ }
+ otherTable.append("\t\t`");
+ otherTable.append(tableName);
+ if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ otherTable.append("_id` bigint NOT NULL,\n");
+ } else {
+ otherTable.append("_id` INTEGER NOT NULL,\n");
+ }
+ otherTable.append("\t\t`order` INTEGER NOT NULL DEFAULT 0,\n");
+ otherTable.append("\t\t`");
+ otherTable.append(localName);
+ if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ otherTable.append("_id` bigint NOT NULL\n");
+ } else {
+ otherTable.append("_id` INTEGER NOT NULL\n");
+ }
+ if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ otherTable.append("\t, PRIMARY KEY (`id`)\n");
+ }
+ otherTable.append("\t)");
+ if (!ConfigBaseVariable.getDBType().equals("sqlite")) {
+ otherTable.append(" ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;\n\n");
+ }
+ otherTable.append(";");
+ postActionList.add(otherTable.toString());
+ }
+}
diff --git a/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToOne.java b/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToOne.java
index 7cd57a3..76e58da 100644
--- a/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToOne.java
+++ b/src/org/kar/archidata/sqlWrapper/addOn/AddOnManyToOne.java
@@ -12,11 +12,11 @@ import java.util.stream.Collectors;
import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
-import org.kar.archidata.sqlWrapper.StateLoad;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.persistence.ManyToOne;
+import jakarta.validation.constraints.NotNull;
public class AddOnManyToOne implements SqlWrapperAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
@@ -93,8 +93,7 @@ public class AddOnManyToOne implements SqlWrapperAddOn {
}
@Override
- public int generateQuerry(final String tableName, final Field elem, final StringBuilder querry, final String name, final List autoClasify, QuerryOptions options) {
- autoClasify.add(StateLoad.NORMAL);
+ public int generateQuerry(@NotNull String tableName, @NotNull Field elem, @NotNull StringBuilder querry, @NotNull String name, @NotNull int elemCount, QuerryOptions options) {
querry.append(" ");
querry.append(tableName);
querry.append(".");
@@ -119,8 +118,8 @@ public class AddOnManyToOne implements SqlWrapperAddOn {
// TODO : refacto this table to manage a generic table with dynamic name to be serializable with the default system
@Override
- public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List ListOtherTables, final boolean createIfNotExist,
- final boolean createDrop, final int fieldId) throws Exception {
- SqlWrapper.createTablesSpecificType(tableName, elem, mainTableBuilder, ListOtherTables, createIfNotExist, createDrop, fieldId, Long.class);
+ public void createTables(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List preActionList, List postActionList,
+ final boolean createIfNotExist, final boolean createDrop, final int fieldId) throws Exception {
+ SqlWrapper.createTablesSpecificType(tableName, elem, mainTableBuilder, preActionList, postActionList, createIfNotExist, createDrop, fieldId, Long.class);
}
}
diff --git a/src/org/kar/archidata/sqlWrapper/addOn/AddOnSQLTableExternalForeinKeyAsList.java b/src/org/kar/archidata/sqlWrapper/addOn/AddOnSQLTableExternalForeinKeyAsList.java
index 0493226..f17c5da 100644
--- a/src/org/kar/archidata/sqlWrapper/addOn/AddOnSQLTableExternalForeinKeyAsList.java
+++ b/src/org/kar/archidata/sqlWrapper/addOn/AddOnSQLTableExternalForeinKeyAsList.java
@@ -13,12 +13,14 @@ import org.kar.archidata.annotation.addOn.SQLTableExternalForeinKeyAsList;
import org.kar.archidata.sqlWrapper.QuerryOptions;
import org.kar.archidata.sqlWrapper.SqlWrapper;
import org.kar.archidata.sqlWrapper.SqlWrapperAddOn;
-import org.kar.archidata.sqlWrapper.StateLoad;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import jakarta.validation.constraints.NotNull;
+
public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
+ static final String SEPARATOR = "-";
/**
* Convert the list if external id in a string '-' separated
@@ -30,28 +32,7 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
for (Long elem : ids) {
tmp.add(elem);
}
- return tmp.stream().map(x -> String.valueOf(x)).collect(Collectors.joining("-"));
- }
-
- /**
- * extract a list of "-" separated element from a SQL input data.
- * @param rs Result Set of the BDD
- * @param iii Id in the result set
- * @return The list of Long value
- * @throws SQLException if an error is generated in the sql request.
- */
- protected static List getListOfIds(ResultSet rs, int iii) throws SQLException {
- String trackString = rs.getString(iii);
- if (rs.wasNull()) {
- return null;
- }
- List out = new ArrayList<>();
- String[] elements = trackString.split("-");
- for (String elem : elements) {
- Long tmp = Long.parseLong(elem);
- out.add(tmp);
- }
- return out;
+ return tmp.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(SEPARATOR));
}
@Override
@@ -92,8 +73,7 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
}
@Override
- public int generateQuerry(String tableName, Field elem, StringBuilder querry, String name, List autoClasify, QuerryOptions options) {
- autoClasify.add(StateLoad.ARRAY);
+ public int generateQuerry(@NotNull String tableName, @NotNull Field elem, @NotNull StringBuilder querry, @NotNull String name, @NotNull int elemCount, QuerryOptions options) {
querry.append(" ");
querry.append(tableName);
querry.append(".");
@@ -103,7 +83,7 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
@Override
public int fillFromQuerry(ResultSet rs, Field elem, Object data, int count, QuerryOptions options) throws SQLException, IllegalArgumentException, IllegalAccessException {
- List idList = getListOfIds(rs, count);
+ List idList = SqlWrapper.getListOfIds(rs, count, SEPARATOR);
elem.set(data, idList);
return 1;
}
@@ -114,9 +94,10 @@ public class AddOnSQLTableExternalForeinKeyAsList implements SqlWrapperAddOn {
}
@Override
- public void createTables(String tableName, Field elem, StringBuilder mainTableBuilder, List ListOtherTables, boolean createIfNotExist, boolean createDrop, int fieldId) throws Exception {
+ public void createTables(String tableName, Field elem, StringBuilder mainTableBuilder, List preActionList, List postActionList, boolean createIfNotExist, boolean createDrop,
+ int fieldId) throws Exception {
// TODO Auto-generated method stub
- SqlWrapper.createTablesSpecificType(tableName, elem, mainTableBuilder, ListOtherTables, createIfNotExist, createDrop, fieldId, String.class);
+ SqlWrapper.createTablesSpecificType(tableName, elem, mainTableBuilder, preActionList, postActionList, createIfNotExist, createDrop, fieldId, String.class);
}
}