From b2283570d9e8e728de2955fb7c17b34439280f69 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Tue, 16 Aug 2022 17:27:51 +0200
Subject: [PATCH] WIP: entity-id

---
 .../MySQL/MySQLGetUpdateableChecksums.java    |  5 +++--
 .../MySQL/MySQLSetFileChecksum.java           | 14 +++++++++----
 .../exceptions/TransactionException.java      |  4 ++++
 .../java/org/caosdb/server/entity/Entity.java | 13 ++----------
 .../caosdb/server/entity/EntityInterface.java |  6 +++---
 .../container/TransactionContainer.java       | 12 +++++++++++
 .../server/entity/wrapper/EntityWrapper.java  | 20 ++++++++++++-------
 .../server/grpc/CaosDBToGrpcConverters.java   |  2 +-
 .../server/grpc/GrpcToCaosDBConverters.java   | 18 +++++++++--------
 .../resource/transaction/EntityResource.java  | 11 +++++-----
 .../server/transaction/WriteTransaction.java  | 11 ++++++----
 11 files changed, 71 insertions(+), 45 deletions(-)

diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java
index cf4e0aa7..28c55032 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java
@@ -28,6 +28,7 @@ import java.sql.SQLException;
 import org.caosdb.server.database.access.Access;
 import org.caosdb.server.database.backend.interfaces.GetUpdateableChecksumsImpl;
 import org.caosdb.server.database.exceptions.TransactionException;
+import org.caosdb.server.entity.EntityID;
 
 public class MySQLGetUpdateableChecksums extends MySQLTransaction
     implements GetUpdateableChecksumsImpl {
@@ -40,12 +41,12 @@ public class MySQLGetUpdateableChecksums extends MySQLTransaction
   }
 
   @Override
-  public Integer execute() throws TransactionException {
+  public EntityID execute() throws TransactionException {
     try {
       final PreparedStatement stmt = prepareStatement(this.GET_UPDATEABLE_CHECKSUMS);
       final ResultSet rs = stmt.executeQuery();
       if (rs.next()) {
-        return rs.getInt(1);
+        return new EntityID(rs.getInt(1));
       } else {
         return null;
       }
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLSetFileChecksum.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLSetFileChecksum.java
index 960457cb..fb6d4188 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLSetFileChecksum.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLSetFileChecksum.java
@@ -5,10 +5,16 @@ import java.sql.SQLException;
 import org.caosdb.server.database.access.Access;
 import org.caosdb.server.database.backend.interfaces.SetFileChecksumImpl;
 import org.caosdb.server.database.exceptions.TransactionException;
+import org.caosdb.server.entity.EntityID;
 
+/**
+ * Implements {@link SetFileChecksumImpl} for a MySQL/MariaDB back-end.
+ *
+ * @author Timm Fitschen (t.fitschen@indiscale.com)
+ */
 public class MySQLSetFileChecksum extends MySQLTransaction implements SetFileChecksumImpl {
 
-  public MySQLSetFileChecksum(Access access) {
+  public MySQLSetFileChecksum(final Access access) {
     super(access);
   }
 
@@ -16,10 +22,10 @@ public class MySQLSetFileChecksum extends MySQLTransaction implements SetFileChe
       "UPDATE files SET hash = unhex(?) WHERE file_id = ?";
 
   @Override
-  public void execute(Integer id, String checksum) {
+  public void execute(final EntityID id, final String checksum) {
     try {
-      PreparedStatement stmt = prepareStatement(STMT_SET_CHECKSUM);
-      stmt.setInt(2, id);
+      final PreparedStatement stmt = prepareStatement(STMT_SET_CHECKSUM);
+      stmt.setInt(2, id.toInteger());
       stmt.setString(1, checksum);
       stmt.execute();
     } catch (SQLException | ConnectionException e) {
diff --git a/src/main/java/org/caosdb/server/database/exceptions/TransactionException.java b/src/main/java/org/caosdb/server/database/exceptions/TransactionException.java
index ac76fe76..6564ed49 100644
--- a/src/main/java/org/caosdb/server/database/exceptions/TransactionException.java
+++ b/src/main/java/org/caosdb/server/database/exceptions/TransactionException.java
@@ -33,4 +33,8 @@ public class TransactionException extends RuntimeException {
   public TransactionException(final Throwable t) {
     super(t);
   }
+
+  public TransactionException(String message, Exception cause) {
+    super(message, cause);
+  }
 }
diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java
index 9cd848d1..b86789fb 100644
--- a/src/main/java/org/caosdb/server/entity/Entity.java
+++ b/src/main/java/org/caosdb/server/entity/Entity.java
@@ -69,7 +69,7 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa
   public static final String ENTITY_STATUS_CHANGED_EVENT = "EntityStatusChangedEvent";
   private Unit unit = null;
   private Role role = null;
-  private EntityStatus entityStatus = null;
+  private EntityStatus entityStatus = EntityStatus.QUALIFIED;
   private FileProperties fileProperties = null;
   private String name = null;
   private String description = null;
@@ -292,7 +292,7 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa
 
   @Override
   public final void setEntityStatus(final EntityStatus entityStatus) {
-    if (hasEntityStatus() && getEntityStatus() == entityStatus) {
+    if (getEntityStatus() == entityStatus) {
       return;
     }
     if (this.entityStatus == EntityStatus.UNQUALIFIED) {
@@ -303,11 +303,6 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa
     notifyObservers(ENTITY_STATUS_CHANGED_EVENT);
   }
 
-  @Override
-  public final boolean hasEntityStatus() {
-    return this.entityStatus != null;
-  }
-
   @Override
   public final Role getRole() {
     return this.role;
@@ -378,10 +373,6 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa
     return ret;
   }
 
-  public Entity() {
-    setEntityStatus(EntityStatus.QUALIFIED);
-  }
-
   @Override
   public void setId(final EntityID id) {
     this.id.link(id);
diff --git a/src/main/java/org/caosdb/server/entity/EntityInterface.java b/src/main/java/org/caosdb/server/entity/EntityInterface.java
index cfb4c280..f967b307 100644
--- a/src/main/java/org/caosdb/server/entity/EntityInterface.java
+++ b/src/main/java/org/caosdb/server/entity/EntityInterface.java
@@ -50,11 +50,11 @@ public interface EntityInterface
 
   public abstract SparseEntity getSparseEntity();
 
-  public abstract Integer getId();
+  public abstract EntityID getId();
 
   public abstract String getIdVersion();
 
-  public abstract void setId(Integer id);
+  public abstract void setId(EntityID id);
 
   public abstract boolean hasId();
 
@@ -157,7 +157,7 @@ public interface EntityInterface
 
   public abstract boolean hasUnit();
 
-  public abstract Integer getDomain();
+  public abstract EntityID getDomain();
 
   public abstract EntityInterface parseSparseEntity(SparseEntity spe);
 
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 7e9a2ba3..289287c8 100644
--- a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
@@ -30,6 +30,8 @@ import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.database.misc.TransactionBenchmark;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
+import org.caosdb.server.entity.Message;
+import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.entity.xml.ToElementable;
 import org.caosdb.server.jobs.JobTarget;
 import org.caosdb.server.utils.EntityStatus;
@@ -171,4 +173,14 @@ public class TransactionContainer extends Container<EntityInterface>
   public boolean skipJob() {
     return false;
   }
+
+  @Override
+  public void addError(Message m) {
+    setStatus(EntityStatus.UNQUALIFIED);
+    if (m.getType().equalsIgnoreCase(MessageType.Error.toString())) {
+      addMessage(m);
+    } else {
+      addMessage(new Message(MessageType.Error, m.getCode(), m.getDescription(), m.getBody()));
+    }
+  }
 }
diff --git a/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java
index 2028bee7..754c6e3f 100644
--- a/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java
+++ b/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java
@@ -33,6 +33,7 @@ import org.caosdb.server.database.proto.SparseEntity;
 import org.caosdb.server.database.proto.VerySparseEntity;
 import org.caosdb.server.datatype.AbstractDatatype;
 import org.caosdb.server.datatype.Value;
+import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.Message;
@@ -52,7 +53,7 @@ import org.caosdb.server.utils.TransactionLogMessage;
 import org.caosdb.unit.Unit;
 import org.jdom2.Element;
 
-public class EntityWrapper implements EntityInterface {
+public abstract class EntityWrapper implements EntityInterface {
 
   protected EntityInterface entity;
   private ToElementStrategy s;
@@ -96,7 +97,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public Integer getId() {
+  public EntityID getId() {
     return this.entity.getId();
   }
 
@@ -105,6 +106,11 @@ public class EntityWrapper implements EntityInterface {
     this.entity.setId(id);
   }
 
+  @Override
+  public void setId(final EntityID id) {
+    this.entity.setId(id);
+  }
+
   @Override
   public boolean hasId() {
     return this.entity.hasId();
@@ -479,7 +485,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public Integer getDomain() {
+  public EntityID getDomain() {
     return this.entity.getDomain();
   }
 
@@ -532,12 +538,12 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public boolean hasPermission(Permission permission) {
+  public boolean hasPermission(final Permission permission) {
     return this.entity.hasPermission(permission);
   }
 
   @Override
-  public boolean hasPermission(Subject subject, Permission permission) {
+  public boolean hasPermission(final Subject subject, final Permission permission) {
     return this.entity.hasPermission(subject, permission);
   }
 
@@ -552,7 +558,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public void setVersion(Version version) {
+  public void setVersion(final Version version) {
     this.entity.setVersion(version);
   }
 
@@ -562,7 +568,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public void addToElement(Element element, SerializeFieldStrategy strategy) {
+  public void addToElement(final Element element, final SerializeFieldStrategy strategy) {
     this.entity.addToElement(element, strategy);
   }
 
diff --git a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
index 40fda9d8..fc3c26f6 100644
--- a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
+++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
@@ -105,7 +105,7 @@ public class CaosDBToGrpcConverters {
     final Builder entityBuilder = Entity.newBuilder();
 
     if (from.hasId() && s.isToBeSet("id")) {
-      entityBuilder.setId(Integer.toString(from.getId()));
+      entityBuilder.setId(from.getId().toString());
     }
     if (from.getRole() != null && s.isToBeSet("role")) {
       entityBuilder.setRole(convert(from.getRole()));
diff --git a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
index d7c515a4..0430a795 100644
--- a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
+++ b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
@@ -50,9 +50,11 @@ import org.caosdb.server.datatype.ListDatatype;
 import org.caosdb.server.datatype.ReferenceDatatype;
 import org.caosdb.server.datatype.ReferenceDatatype2;
 import org.caosdb.server.datatype.Value;
+import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.MagicTypes;
+import org.caosdb.server.entity.RetrieveEntity;
 import org.caosdb.server.entity.Role;
 import org.caosdb.server.entity.StatementStatus;
 import org.caosdb.server.entity.UpdateEntity;
@@ -64,8 +66,8 @@ import org.caosdb.server.utils.ServerMessages;
 
 public class GrpcToCaosDBConverters {
 
-  public Integer getId(final String id) {
-    return Integer.parseInt(id);
+  public EntityID getId(final String id) {
+    return new EntityID(Integer.parseInt(id));
   }
 
   public Role convert(final EntityRole role) {
@@ -85,7 +87,7 @@ public class GrpcToCaosDBConverters {
 
   public Property getUnit(final String unitStr) {
     final EntityInterface magicUnit = MagicTypes.UNIT.getEntity();
-    final Property unit = new Property();
+    final Property unit = new Property(new RetrieveEntity());
     unit.setDescription(magicUnit.getDescription());
     unit.setName(magicUnit.getName());
     unit.setId(magicUnit.getId());
@@ -251,7 +253,7 @@ public class GrpcToCaosDBConverters {
 
   private Property convert(
       final org.caosdb.api.entity.v1.Property e, final StatementStatus defaultImportance) {
-    final Property result = new Property();
+    final Property result = new Property(new RetrieveEntity());
 
     try {
       result.setId(e.getId().isBlank() ? null : getId(e.getId()));
@@ -309,7 +311,7 @@ public class GrpcToCaosDBConverters {
 
   private org.caosdb.server.entity.wrapper.Parent convert(final Parent e) {
     final org.caosdb.server.entity.wrapper.Parent result =
-        new org.caosdb.server.entity.wrapper.Parent();
+        new org.caosdb.server.entity.wrapper.Parent(new RetrieveEntity());
 
     try {
       result.setId(e.getId().isBlank() ? null : getId(e.getId()));
@@ -334,12 +336,12 @@ public class GrpcToCaosDBConverters {
 
   private EntityInterface convert(EntityACL acl) {
     try {
-      Integer id = getId(acl.getId());
-      UpdateEntity result = new UpdateEntity(id, null);
+      EntityID id = getId(acl.getId());
+      UpdateEntity result = new UpdateEntity(id);
       result.setEntityACL(convertAcl(acl));
       return result;
     } catch (NumberFormatException exc) {
-      UpdateEntity result = new UpdateEntity(null, null);
+      UpdateEntity result = new UpdateEntity();
       result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
       return result;
     }
diff --git a/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java
index 7003dfc1..ee247210 100644
--- a/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java
+++ b/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java
@@ -33,6 +33,7 @@ import org.caosdb.server.FileSystem;
 import org.caosdb.server.database.backend.implementation.MySQL.ConnectionException;
 import org.caosdb.server.entity.DeleteEntity;
 import org.caosdb.server.entity.FileProperties;
+import org.caosdb.server.entity.EntityID;
 import org.caosdb.server.entity.InsertEntity;
 import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.UpdateEntity;
@@ -65,20 +66,20 @@ public class EntityResource extends RetrieveEntityResource {
     final Document doc = new Document();
 
     for (final String item : getRequestedItems()) {
-      String[] elem = item.split("@", 1);
+      final String[] elem = item.split("@", 1);
       Integer id = null;
       String version = null;
       try {
         id = Integer.parseInt(elem[0]);
-      } catch (NumberFormatException e) {
+      } catch (final NumberFormatException e) {
         // pass
       }
       if (elem.length > 1) {
         version = elem[1];
       }
 
-      if (id != null) {
-        container.add(new DeleteEntity(id, version));
+      if (id != null && id > 0) {
+        container.add(new DeleteEntity(new EntityID(id), version));
       }
     }
 
@@ -127,7 +128,7 @@ public class EntityResource extends RetrieveEntityResource {
    * Parse the body of requests with content type "multipart/form-data". This is specific for
    * requests which also contain file blobs.
    */
-  private Element parseMultipartEntity(WritableContainer container)
+  private Element parseMultipartEntity(final WritableContainer container)
       throws FileUploadException, IOException, Message, xmlNotWellFormedException,
           NoSuchAlgorithmException, CaosDBException {
     final DiskFileItemFactory factory = new DiskFileItemFactory();
diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
index 3497f912..67a461aa 100644
--- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
@@ -39,6 +39,7 @@ import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransact
 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.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.InsertEntity;
@@ -49,6 +50,7 @@ import org.caosdb.server.entity.container.TransactionContainer;
 import org.caosdb.server.entity.container.WritableContainer;
 import org.caosdb.server.entity.wrapper.Parent;
 import org.caosdb.server.entity.wrapper.Property;
+import org.caosdb.server.jobs.Job;
 import org.caosdb.server.jobs.Schedule;
 import org.caosdb.server.permissions.EntityACL;
 import org.caosdb.server.permissions.EntityPermission;
@@ -56,6 +58,7 @@ import org.caosdb.server.permissions.Permission;
 import org.caosdb.server.query.Query;
 import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
+import org.caosdb.server.utils.Undoable;
 
 /**
  * This class is responsible for inserting, updating and deleting entities which are held in the
@@ -242,7 +245,7 @@ public class WriteTransaction extends Transaction<WritableContainer>
         }
 
         // no standard entities are to be deleted.
-        if (entity.hasId() && entity.getId() < 100) {
+        if (entity.hasId() && EntityID.isReserved(entity.getId())) {
           entity.setEntityStatus(EntityStatus.UNQUALIFIED);
           entity.addInfo("This entity cannot be deleted");
         }
@@ -309,9 +312,6 @@ public class WriteTransaction extends Transaction<WritableContainer>
     }
   }
 
-  @Override
-  protected void postCheck() {}
-
   @Override
   protected void transaction() throws Exception {
     if (getContainer().getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) {
@@ -341,6 +341,9 @@ public class WriteTransaction extends Transaction<WritableContainer>
     }
   }
 
+  @Override
+  protected void postCheck() {}
+
   @Override
   protected void postTransaction() throws Exception {
     // set entityStatus to DELETED and add deletion info message for deleted entities.
-- 
GitLab