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

---
 .../java/org/caosdb/server/entity/Entity.java | 79 ++++++++-----------
 .../org/caosdb/server/entity/EntityID.java    | 71 +++++++++++++++++
 2 files changed, 104 insertions(+), 46 deletions(-)
 create mode 100644 src/main/java/org/caosdb/server/entity/EntityID.java

diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java
index 07c451a3..9cd848d1 100644
--- a/src/main/java/org/caosdb/server/entity/Entity.java
+++ b/src/main/java/org/caosdb/server/entity/Entity.java
@@ -63,7 +63,7 @@ import org.caosdb.server.utils.TransactionLogMessage;
 import org.caosdb.unit.Unit;
 import org.jdom2.Element;
 
-public class Entity extends AbstractObservable implements EntityInterface {
+public abstract class Entity extends AbstractObservable implements EntityInterface {
 
   public static final String DATATYPE_CHANGED_EVENT = "DatatypeChangedEvent";
   public static final String ENTITY_STATUS_CHANGED_EVENT = "EntityStatusChangedEvent";
@@ -74,7 +74,8 @@ public class Entity extends AbstractObservable implements EntityInterface {
   private String name = null;
   private String description = null;
   private Value value = null;
-  private final IntegerWrapper id = new IntegerWrapper();
+  private final EntityID domain = new EntityID(0);
+  private final EntityID id = new EntityID();
   private AbstractDatatype datatype = null;
   private final ParentContainer parents = new ParentContainer(this);
   private final PropertyContainer properties = new PropertyContainer(this);
@@ -124,13 +125,13 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   @Override
-  public boolean hasPermission(Permission permission) {
+  public boolean hasPermission(final Permission permission) {
     final Subject subject = SecurityUtils.getSubject();
     return hasPermission(subject, permission);
   }
 
   @Override
-  public boolean hasPermission(Subject subject, Permission permission) {
+  public boolean hasPermission(final Subject subject, final Permission permission) {
     return this.entityACL.isPermitted(subject, permission);
   }
 
@@ -200,34 +201,9 @@ public class Entity extends AbstractObservable implements EntityInterface {
     return this.datatype != null;
   }
 
-  private class IntegerWrapper {
-    Integer i = null;
-    EntityInterface link = null;
-
-    void setId(final Integer i) {
-      this.i = i;
-    }
-
-    public Integer toInteger() {
-      if (this.link != null) {
-        return this.link.getId();
-      }
-      return this.i;
-    }
-
-    @Override
-    public String toString() {
-      return toInteger().toString();
-    }
-
-    boolean hasId() {
-      return this.i != null || (this.link != null && this.link.hasId());
-    }
-  }
-
   @Override
-  public final Integer getId() {
-    return this.id.toInteger();
+  public final EntityID getId() {
+    return this.id;
   }
 
   @Override
@@ -242,7 +218,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   @Override
   public EntityInterface linkIdToEntity(final EntityInterface link) {
-    this.id.link = link;
+    this.id.link(link);
     return this;
   }
 
@@ -379,7 +355,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
   @Override
   public SparseEntity getSparseEntity() {
     final SparseEntity ret = new SparseEntity();
-    ret.id = getId();
+    ret.id = getId().toInteger();
     ret.name = getName();
     ret.description = getDescription();
     ret.acl = getEntityACL().serialize();
@@ -406,11 +382,13 @@ public class Entity extends AbstractObservable implements EntityInterface {
     setEntityStatus(EntityStatus.QUALIFIED);
   }
 
-  public Entity(final Integer id) {
-    this();
-    setId(id);
+  @Override
+  public void setId(final EntityID id) {
+    this.id.link(id);
   }
 
+  public Entity() {}
+
   public Entity(final Element e) {
     try {
       setRole(e.getName().toUpperCase());
@@ -422,7 +400,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
     }
   }
 
-  public Entity(final Integer id, final Role role) {
+  public Entity(final EntityID id, final Role role) {
     this(id);
     if (role != null) {
       setRole(role);
@@ -447,10 +425,19 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   public Entity(final String name) {
-    this();
     setName(name);
   }
 
+  public Entity(final Element e) {
+    try {
+      setRole(e.getName().toUpperCase());
+      parseFromElement(e);
+    } catch (final NoSuchRoleException exc) {
+      parseFromElement(e);
+      addError(ServerMessages.NO_SUCH_ENTITY_ROLE(e.getName()));
+    }
+  }
+
   private StatementStatus statementStatus = null;
 
   /**
@@ -555,13 +542,13 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   @Override
-  public void addToElement(Element element, SerializeFieldStrategy strategy) {
+  public void addToElement(final Element element, final SerializeFieldStrategy strategy) {
     getToElementStrategy().addToElement(this, element, strategy);
   }
 
   @Override
-  public Integer getDomain() {
-    return 0;
+  public EntityID getDomain() {
+    return domain;
   }
 
   /** Errors, Warnings and Info messages for this entity. */
@@ -708,7 +695,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
     // Parse UNIT.
     if (element.getAttribute("unit") != null && !element.getAttributeValue("unit").equals("")) {
       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());
@@ -755,13 +742,13 @@ public class Entity extends AbstractObservable implements EntityInterface {
         // Parse sub elements which represent PROPERTIES of this
         // record.
 
-        final Property property = new Property(pe);
+        final Property property = new Property(new WritableEntity(pe, Role.Property));
         property.setPIdx(pidx++);
         addProperty(property);
       } else if (pe.getName().equalsIgnoreCase("Parent")) {
         // Parse sub elements which represent PARENTS of this
         // record.
-        final Parent parent = new Parent(pe);
+        final Parent parent = new Parent(new WritableEntity(pe, null));
         addParent(parent);
       } else if (pe.getName().equalsIgnoreCase("EntityACL")) {
         // Parse and concatenate EntityACL
@@ -861,7 +848,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   @Override
   public String toString() {
-    return (getRole().toString())
+    return getRole().toString()
         + (hasId() ? "(" + getId().toString() + ")" : "()")
         + (hasCuid() ? "[" + getCuid() + "]" : "[]")
         + (hasName() ? "(" + getName() + ")" : "()")
@@ -1047,7 +1034,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   @Override
-  public void setVersion(Version version) {
+  public void setVersion(final Version version) {
     this.version = version;
   }
 
diff --git a/src/main/java/org/caosdb/server/entity/EntityID.java b/src/main/java/org/caosdb/server/entity/EntityID.java
new file mode 100644
index 00000000..3ad769b8
--- /dev/null
+++ b/src/main/java/org/caosdb/server/entity/EntityID.java
@@ -0,0 +1,71 @@
+package org.caosdb.server.entity;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class EntityID implements Serializable {
+
+  private static final long serialVersionUID = -9092133023135548179L;
+
+  public static final EntityID DEFAULT_DOMAIN = new EntityID(0);
+  private Integer i = null;
+  private EntityID link = null;
+
+  public EntityID() {}
+
+  public EntityID(final Integer id) {
+    this.i = id;
+  }
+
+  public void setId(final Integer i) {
+    this.i = i;
+  }
+
+  public Integer toInteger() {
+    if (this.link != null) {
+      return this.link.toInteger();
+    }
+    return this.i;
+  }
+
+  @Override
+  public String toString() {
+    return toInteger().toString();
+  }
+
+  boolean hasId() {
+    return this.i != null || this.link != null && this.link.hasId();
+  }
+
+  public void link(final EntityInterface entity) {
+    this.link = entity.getId();
+  }
+
+  public void link(final EntityID entityId) {
+    this.link = entityId;
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (obj instanceof EntityID) {
+      return Objects.equals(((EntityID) obj).toInteger(), this.toInteger());
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    if (this.hasId()) {
+      return toInteger();
+    }
+    return super.hashCode();
+  }
+
+  public boolean isTemporary() {
+    return toInteger() < 0;
+  }
+
+  public static boolean isReserved(final EntityID id) {
+    return id.toInteger() < 100;
+  }
+}
-- 
GitLab