From 3ddfbced43b822d47109619fb75677ed888947c1 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Fri, 11 Aug 2023 16:23:56 +0200
Subject: [PATCH] WIP: generate string ids

---
 conf/core/jobs.csv                            |  1 +
 .../server/database/BackendTransaction.java   |  3 ++
 .../MySQL/MySQLInsertSparseEntity.java        | 10 ++--
 .../MySQL/MySQLRetrieveCurrentMaxId.java      | 39 ++++++++++++++
 .../interfaces/RetrieveCurrentMaxIdImpl.java  |  7 +++
 .../transaction/RetrieveCurrentMaxId.java     | 20 +++++++
 .../org/caosdb/server/entity/EntityID.java    |  1 +
 .../server/entity/EntityIdRegistry.java       | 53 +++++++++++++++++++
 .../container/TransactionContainer.java       |  3 ++
 .../server/jobs/core/EntityIdHandler.java     | 24 +++++++++
 .../caosdb/server/transaction/UpdateACL.java  |  5 ++
 .../server/transaction/WriteTransaction.java  | 11 ++++
 .../WriteTransactionInterface.java            |  2 +
 13 files changed, 174 insertions(+), 5 deletions(-)
 create mode 100644 src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java
 create mode 100644 src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveCurrentMaxIdImpl.java
 create mode 100644 src/main/java/org/caosdb/server/database/backend/transaction/RetrieveCurrentMaxId.java
 create mode 100644 src/main/java/org/caosdb/server/entity/EntityIdRegistry.java
 create mode 100644 src/main/java/org/caosdb/server/jobs/core/EntityIdHandler.java

diff --git a/conf/core/jobs.csv b/conf/core/jobs.csv
index 84795bee..38b273c4 100644
--- a/conf/core/jobs.csv
+++ b/conf/core/jobs.csv
@@ -22,6 +22,7 @@
 # DOMAIN_ID, ENTITY_ID, TRANSACTION, JOB, JOB_FAILURE_SEVERITY
 
 # general rules
+0,0,INSERT,EntityIdHandler,ERROR
 0,0,INSERT,CheckPropValid,ERROR
 0,0,INSERT,CheckParValid,ERROR
 0,0,INSERT,CheckParOblPropPresent,ERROR
diff --git a/src/main/java/org/caosdb/server/database/BackendTransaction.java b/src/main/java/org/caosdb/server/database/BackendTransaction.java
index 5addf3f3..eb888241 100644
--- a/src/main/java/org/caosdb/server/database/BackendTransaction.java
+++ b/src/main/java/org/caosdb/server/database/BackendTransaction.java
@@ -50,6 +50,7 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLLogUserVisit
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRegisterSubDomain;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAll;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAllUncheckedFiles;
+import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveCurrentMaxId;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveDatatypes;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveEntityACL;
 import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveLogRecord;
@@ -112,6 +113,7 @@ import org.caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesIm
 import org.caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl;
 import org.caosdb.server.database.backend.interfaces.RetrieveEntityACLImpl;
 import org.caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl;
+import org.caosdb.server.database.backend.interfaces.RetrieveCurrentMaxIdImpl;
 import org.caosdb.server.database.backend.interfaces.RetrieveParentsImpl;
 import org.caosdb.server.database.backend.interfaces.RetrievePasswordValidatorImpl;
 import org.caosdb.server.database.backend.interfaces.RetrievePermissionRulesImpl;
@@ -216,6 +218,7 @@ public abstract class BackendTransaction implements Undoable {
       setImpl(ListUsersImpl.class, MySQLListUsers.class);
       setImpl(LogUserVisitImpl.class, MySQLLogUserVisit.class);
       setImpl(RetrieveEntityACLImpl.class, MySQLRetrieveEntityACL.class);
+      setImpl(RetrieveCurrentMaxIdImpl.class, MySQLRetrieveCurrentMaxId.class);
     }
   }
 
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertSparseEntity.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertSparseEntity.java
index 6e429500..0a812bdf 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertSparseEntity.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertSparseEntity.java
@@ -48,14 +48,14 @@ public class MySQLInsertSparseEntity extends MySQLTransaction implements InsertS
       final PreparedStatement insertEntityStmt = prepareStatement(STMT_INSERT_SPARSE_ENTITY);
       final PreparedStatement insertFilePropsStmt = prepareStatement(STMT_INSERT_FILE_PROPERTIES);
 
-      insertEntityStmt.setString(1, entity.name);
-      insertEntityStmt.setString(2, entity.description);
-      insertEntityStmt.setString(3, entity.role);
-      insertEntityStmt.setString(4, entity.acl);
+      insertEntityStmt.setInt(1, entity.id);
+      insertEntityStmt.setString(2, entity.name);
+      insertEntityStmt.setString(3, entity.description);
+      insertEntityStmt.setString(4, entity.role);
+      insertEntityStmt.setString(5, entity.acl);
 
       try (final ResultSet rs = insertEntityStmt.executeQuery()) {
         if (rs.next()) {
-          entity.id = rs.getInt("EntityID");
           entity.versionId = DatabaseUtils.bytes2UTF8(rs.getBytes("Version"));
         } else {
           throw new TransactionException("Didn't get new EntityID back.");
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java
new file mode 100644
index 00000000..ff4e9175
--- /dev/null
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java
@@ -0,0 +1,39 @@
+package org.caosdb.server.database.backend.implementation.MySQL;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.caosdb.server.database.access.Access;
+import org.caosdb.server.database.backend.interfaces.RetrieveCurrentMaxIdImpl;
+import org.caosdb.server.database.exceptions.TransactionException;
+
+public class MySQLRetrieveCurrentMaxId extends MySQLTransaction implements RetrieveCurrentMaxIdImpl {
+
+	public MySQLRetrieveCurrentMaxId(Access access) {
+		super(access);
+	}
+	
+	public static final String STMT = "SELECT max(entity_id) AS max_id FROM transaction_log";
+
+	@Override
+	public Integer execute() {
+try {
+	try (
+			PreparedStatement stmt = prepareStatement(STMT)
+			) {		
+	
+	try (ResultSet rs = stmt.executeQuery()) {
+		if(rs.next()) {
+			return rs.getInt("max_id");
+		} else {
+			return 100;
+		}
+	}
+	}
+} catch (SQLException | ConnectionException e) {
+throw new TransactionException(e);
+}
+	}
+
+}
diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveCurrentMaxIdImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveCurrentMaxIdImpl.java
new file mode 100644
index 00000000..6d7b2d3f
--- /dev/null
+++ b/src/main/java/org/caosdb/server/database/backend/interfaces/RetrieveCurrentMaxIdImpl.java
@@ -0,0 +1,7 @@
+package org.caosdb.server.database.backend.interfaces;
+
+public interface RetrieveCurrentMaxIdImpl extends BackendTransactionImpl {
+
+	public Integer execute();
+
+}
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveCurrentMaxId.java b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveCurrentMaxId.java
new file mode 100644
index 00000000..0efc4f8c
--- /dev/null
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveCurrentMaxId.java
@@ -0,0 +1,20 @@
+package org.caosdb.server.database.backend.transaction;
+
+import org.caosdb.server.database.BackendTransaction;
+import org.caosdb.server.database.backend.interfaces.RetrieveCurrentMaxIdImpl;
+
+public class RetrieveCurrentMaxId extends BackendTransaction {
+
+	private Integer maxId;
+
+	@Override
+	protected void execute() {
+		RetrieveCurrentMaxIdImpl t = getImplementation(RetrieveCurrentMaxIdImpl.class);
+		this.maxId = t.execute();
+	}
+
+	public Integer getCurrentMaxId() {
+		return this.maxId;
+	}
+
+}
diff --git a/src/main/java/org/caosdb/server/entity/EntityID.java b/src/main/java/org/caosdb/server/entity/EntityID.java
index 6a2d2ca3..a8867152 100644
--- a/src/main/java/org/caosdb/server/entity/EntityID.java
+++ b/src/main/java/org/caosdb/server/entity/EntityID.java
@@ -77,4 +77,5 @@ public class EntityID implements Serializable {
   public static boolean isReserved(final EntityID id) {
     return id.toInteger() < 100;
   }
+
 }
diff --git a/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java b/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java
new file mode 100644
index 00000000..b3b99498
--- /dev/null
+++ b/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java
@@ -0,0 +1,53 @@
+
+package org.caosdb.server.entity;
+
+import org.caosdb.server.database.backend.transaction.RetrieveCurrentMaxId;
+import org.caosdb.server.transaction.Transaction;
+
+/**
+ * <p>
+ * Aufgaben:
+ *
+ * <ul>
+ * <li>Ids generieren
+ * <ul>
+ * <li>Pattern (positive Integer, uuid)
+ * </ul>
+ * <li>
+ * </ul>
+ *
+ * @author tf
+ */
+
+public class EntityIdRegistry {
+	
+	private boolean isInit;
+	private Integer currentMaxId;
+	private Transaction<?> transaction;
+
+	public EntityIdRegistry(Transaction<?> t) {
+		this.transaction = t;
+		this.isInit = false;
+	}
+	
+	public void init() {
+		isInit = true;
+		initCurrentMaxId();
+	}
+
+	private void initCurrentMaxId() {
+		this.currentMaxId = transaction.execute(new RetrieveCurrentMaxId(), transaction.getAccess()).getCurrentMaxId();
+	}
+
+	public Integer generate() {
+		if(!isInit) {
+			init();
+		}
+		return ++currentMaxId;
+	}
+
+
+	public boolean isUnused(Integer i) { 
+		return i>currentMaxId;
+ }
+}
diff --git a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
index d3963455..47a0452b 100644
--- a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
@@ -122,6 +122,7 @@ public class TransactionContainer extends Container<EntityInterface>
 
   private TransactionBenchmark benchmark;
   private Query query;
+private Integer currentMaxId =null;
 
   public void setFiles(final HashMap<String, FileProperties> files) {
     this.files = files;
@@ -193,4 +194,6 @@ public class TransactionContainer extends Container<EntityInterface>
   public Query getQuery() {
     return query;
   }
+
+
 }
diff --git a/src/main/java/org/caosdb/server/jobs/core/EntityIdHandler.java b/src/main/java/org/caosdb/server/jobs/core/EntityIdHandler.java
new file mode 100644
index 00000000..e8740107
--- /dev/null
+++ b/src/main/java/org/caosdb/server/jobs/core/EntityIdHandler.java
@@ -0,0 +1,24 @@
+
+package org.caosdb.server.jobs.core;
+
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.InsertEntity;
+import org.caosdb.server.entity.Message;
+import org.caosdb.server.jobs.EntityJob;
+import org.caosdb.server.jobs.JobAnnotation;
+import org.caosdb.server.jobs.TransactionStage;
+import org.caosdb.server.transaction.WriteTransactionInterface;
+
+@JobAnnotation(stage = TransactionStage.PRE_TRANSACTION)
+public class EntityIdHandler extends EntityJob {
+
+	@Override
+	protected void run() throws Message {
+		EntityInterface entity = getEntity();
+		if(entity instanceof InsertEntity && getTransaction() instanceof WriteTransactionInterface) {
+			Integer id = ((WriteTransactionInterface) getTransaction()).generateId();
+			entity.getId().setId(id);
+		}
+	}
+}
+
diff --git a/src/main/java/org/caosdb/server/transaction/UpdateACL.java b/src/main/java/org/caosdb/server/transaction/UpdateACL.java
index 84c73080..89640add 100644
--- a/src/main/java/org/caosdb/server/transaction/UpdateACL.java
+++ b/src/main/java/org/caosdb/server/transaction/UpdateACL.java
@@ -143,4 +143,9 @@ public class UpdateACL extends Transaction<TransactionContainer>
   public String getSRID() {
     return getContainer().getRequestId();
   }
+  
+  @Override
+	public Integer generateId() {
+		throw new UnsupportedOperationException("This is not implemented on purpose. This exception indicates a usage error of this UpdateACL class.");
+	}
 }
diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
index 47b7a53c..b1b1153a 100644
--- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
@@ -40,6 +40,7 @@ import org.caosdb.server.database.backend.transaction.UpdateEntityTransaction;
 import org.caosdb.server.database.misc.RollBackHandler;
 import org.caosdb.server.entity.DeleteEntity;
 import org.caosdb.server.entity.EntityID;
+import org.caosdb.server.entity.EntityIdRegistry;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.InsertEntity;
@@ -73,6 +74,7 @@ public class WriteTransaction extends Transaction<WritableContainer>
     implements WriteTransactionInterface {
 
   private boolean noIdIsError = true;
+private EntityIdRegistry idRegistry;
 
   public WriteTransaction(final WritableContainer container) {
     super(container);
@@ -593,4 +595,13 @@ public class WriteTransaction extends Transaction<WritableContainer>
   public String getSRID() {
     return getContainer().getRequestId();
   }
+
+@Override
+public Integer generateId() {
+	if (this.idRegistry == null) {
+		this.idRegistry = new EntityIdRegistry(getAccess());
+	}
+
+	return this.idRegistry.generate();
+}
 }
diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransactionInterface.java b/src/main/java/org/caosdb/server/transaction/WriteTransactionInterface.java
index 4e2938e1..ccc6a83b 100644
--- a/src/main/java/org/caosdb/server/transaction/WriteTransactionInterface.java
+++ b/src/main/java/org/caosdb/server/transaction/WriteTransactionInterface.java
@@ -10,4 +10,6 @@ public interface WriteTransactionInterface extends TransactionInterface {
   public Subject getTransactor();
 
   public String getSRID();
+
+public Integer generateId();
 }
-- 
GitLab