From 19124d74d592e7f96e35e0583203246ad782ff42 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <timm.fitschen@ds.mpg.de>
Date: Mon, 10 Dec 2018 14:58:58 +0100
Subject: [PATCH] MAINT: Refactoring

---
 .../server/accessControl/UserSources.java     |   3 +-
 .../transaction/DeleteEntityProperties.java   |   5 +-
 .../backend/transaction/DeleteFile.java       |   2 +-
 .../transaction/DeleteSparseEntity.java       |   5 +-
 .../backend/transaction/GetChildren.java      |   2 +-
 .../transaction/GetDependentEntities.java     |   2 +-
 .../backend/transaction/GetFileIterator.java  |   2 +-
 .../backend/transaction/GetIDByName.java      |   2 +-
 .../transaction/InsertEntityDatatype.java     |   3 -
 .../transaction/InsertEntityProperties.java   |   6 +-
 .../backend/transaction/InsertFile.java       |   5 +-
 .../backend/transaction/InsertLogRecord.java  |   4 +-
 .../transaction/InsertSparseEntity.java       |   3 -
 .../transaction/RegisterSubDomain.java        |   2 +-
 .../backend/transaction/RetrieveAll.java      |   2 +-
 .../RetrieveAllUncheckedFiles.java            |   2 +-
 .../transaction/RetrieveDatatypes.java        |   2 +-
 .../transaction/RetrieveFullEntity.java       |  14 +-
 .../transaction/RetrieveLogRecord.java        |   6 +-
 .../backend/transaction/RetrieveParents.java  |   4 +-
 .../transaction/RetrievePermissionRules.java  |   4 +-
 .../transaction/RetrieveProperties.java       |   4 +-
 .../backend/transaction/RetrieveRole.java     |   2 +-
 .../transaction/RetrieveSparseEntity.java     |   2 +-
 .../RetrieveTransactionHistory.java           |   4 +-
 .../backend/transaction/RetrieveUser.java     |   2 +-
 .../backend/transaction/RuleLoader.java       |   9 +-
 .../transaction/SetPermissionRules.java       |   2 +-
 .../backend/transaction/UpdateUserRoles.java  |   2 +-
 .../java/caosdb/server/entity/Entity.java     |  49 +++---
 .../caosdb/server/entity/EntityInterface.java |   9 +-
 .../server/entity/TransactionEntity.java      |  18 +--
 .../entity/container/ParentContainer.java     |   1 -
 .../entity/container/PropertyContainer.java   |   1 -
 .../container/TransactionContainer.java       |   8 +-
 .../server/entity/wrapper/EntityWrapper.java  |  25 ++-
 .../java/caosdb/server/jobs/ContainerJob.java |  12 +-
 src/main/java/caosdb/server/jobs/Job.java     | 143 ++++++++++--------
 .../caosdb/server/jobs/JobAnnotation.java     |   7 +
 .../java/caosdb/server/jobs/Schedule.java     |   8 +-
 .../java/caosdb/server/jobs/core/Atomic.java  |  14 +-
 .../jobs/core/CheckDatatypePresent.java       |  22 +--
 .../CheckNoAdditionalPropertiesPresent.java   |  56 +++++++
 .../jobs/core/CheckNoOverridesPresent.java    |  36 +++++
 .../jobs/core/CheckParOblPropPresent.java     |   6 +-
 .../jobs/core/CheckRefidIsaParRefid.java      |   4 +-
 .../server/jobs/core/CheckRefidValid.java     |   1 -
 .../server/jobs/core/CheckUnitPresent.java    |   2 +-
 .../caosdb/server/jobs/core/Inheritance.java  |   4 +-
 .../server/jobs/core/InsertFilesInDir.java    |   3 +-
 .../jobs/core/LoadContainerFlagJobs.java      |   2 +-
 .../java/caosdb/server/jobs/core/PickUp.java  |   5 +-
 .../jobs/extension/SQLiteTransaction.java     |  14 +-
 src/main/java/caosdb/server/query/Query.java  |   4 +-
 .../caosdb/server/transaction/Retrieve.java   |   5 +-
 .../server/transaction/Transaction.java       |  28 ++--
 .../caosdb/server/utils/EntityStatus.java     |   1 -
 .../caosdb/server/utils/ServerMessages.java   |   8 +
 58 files changed, 357 insertions(+), 246 deletions(-)
 create mode 100644 src/main/java/caosdb/server/jobs/core/CheckNoAdditionalPropertiesPresent.java
 create mode 100644 src/main/java/caosdb/server/jobs/core/CheckNoOverridesPresent.java

diff --git a/src/main/java/caosdb/server/accessControl/UserSources.java b/src/main/java/caosdb/server/accessControl/UserSources.java
index 32b851e8..d96fdf14 100644
--- a/src/main/java/caosdb/server/accessControl/UserSources.java
+++ b/src/main/java/caosdb/server/accessControl/UserSources.java
@@ -44,6 +44,7 @@ import org.apache.shiro.subject.PrincipalCollection;
 
 public class UserSources extends HashMap<String, UserSource> {
 
+  public static final String ANONYMOUS_ROLE = "anonymous";
   private static final Logger logger =
       LogManager.getLogManager().getLogger(UserSources.class.getName());
   public static final String KEY_DEAULT_REALM = "defaultRealm";
@@ -171,7 +172,7 @@ public class UserSources extends HashMap<String, UserSource> {
     if (principals.getPrimaryPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal()) {
       // anymous has one role
       Set<String> roles = new HashSet<>();
-      roles.add("anonymous");
+      roles.add(ANONYMOUS_ROLE);
       return roles;
     }
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/DeleteEntityProperties.java b/src/main/java/caosdb/server/database/backend/transaction/DeleteEntityProperties.java
index ff306830..addcb4e7 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/DeleteEntityProperties.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/DeleteEntityProperties.java
@@ -23,11 +23,9 @@
 package caosdb.server.database.backend.transaction;
 
 import static caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.DeleteEntityPropertiesImpl;
 import caosdb.server.database.exceptions.IntegrityException;
-import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.utils.EntityStatus;
 
@@ -40,7 +38,7 @@ public class DeleteEntityProperties extends BackendTransaction {
   }
 
   @Override
-  public void execute() throws TransactionException {
+  public void execute() {
     RetrieveProperties.removeCached(this.entity.getId());
     RetrieveParents.removeCached(this.entity.getId());
 
@@ -52,7 +50,6 @@ public class DeleteEntityProperties extends BackendTransaction {
         ret.execute(this.entity.getId());
       } catch (final IntegrityException exc) {
         this.entity.addError(ERROR_INTEGRITY_VIOLATION);
-        this.entity.setEntityStatus(EntityStatus.CORRUPT);
         throw exc;
       }
     }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/DeleteFile.java b/src/main/java/caosdb/server/database/backend/transaction/DeleteFile.java
index 82c022be..11235995 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/DeleteFile.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/DeleteFile.java
@@ -22,12 +22,12 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.io.IOException;
 import caosdb.server.CaosDBException;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.Message;
-import java.io.IOException;
 
 public class DeleteFile extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
index dd563882..f777a124 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
@@ -23,11 +23,9 @@
 package caosdb.server.database.backend.transaction;
 
 import static caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.DeleteSparseEntityImpl;
 import caosdb.server.database.exceptions.IntegrityException;
-import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.utils.EntityStatus;
 
@@ -40,7 +38,7 @@ public class DeleteSparseEntity extends BackendTransaction {
   }
 
   @Override
-  protected void execute() throws TransactionException {
+  protected void execute()  {
     RetrieveSparseEntity.removeCached(this.entity.getId());
 
     final DeleteSparseEntityImpl ret = getImplementation(DeleteSparseEntityImpl.class);
@@ -51,7 +49,6 @@ public class DeleteSparseEntity extends BackendTransaction {
       }
     } catch (final IntegrityException exc) {
       this.entity.addError(ERROR_INTEGRITY_VIOLATION);
-      this.entity.setEntityStatus(EntityStatus.CORRUPT);
       throw exc;
     }
   }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/GetChildren.java b/src/main/java/caosdb/server/database/backend/transaction/GetChildren.java
index d476345c..2952b985 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/GetChildren.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/GetChildren.java
@@ -22,10 +22,10 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.List;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.GetChildrenImpl;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.List;
 
 public class GetChildren extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/GetDependentEntities.java b/src/main/java/caosdb/server/database/backend/transaction/GetDependentEntities.java
index e4e6e96f..60143ec8 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/GetDependentEntities.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/GetDependentEntities.java
@@ -22,10 +22,10 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.List;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.GetDependentEntitiesImpl;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.List;
 
 public class GetDependentEntities extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/GetFileIterator.java b/src/main/java/caosdb/server/database/backend/transaction/GetFileIterator.java
index 7e28ff24..d8f47b18 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/GetFileIterator.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/GetFileIterator.java
@@ -22,10 +22,10 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.Iterator;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.GetFileIteratorImpl;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.Iterator;
 
 public class GetFileIterator extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/GetIDByName.java b/src/main/java/caosdb/server/database/backend/transaction/GetIDByName.java
index 895cd707..1adda922 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/GetIDByName.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/GetIDByName.java
@@ -22,12 +22,12 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.List;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.GetIDByNameImpl;
 import caosdb.server.database.exceptions.EntityDoesNotExistException;
 import caosdb.server.database.exceptions.EntityWasNotUniqueException;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.List;
 
 public class GetIDByName extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/InsertEntityDatatype.java b/src/main/java/caosdb/server/database/backend/transaction/InsertEntityDatatype.java
index 39c46583..f0f7dbe2 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/InsertEntityDatatype.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/InsertEntityDatatype.java
@@ -1,13 +1,11 @@
 package caosdb.server.database.backend.transaction;
 
 import static caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.InsertEntityDatatypeImpl;
 import caosdb.server.database.exceptions.IntegrityException;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.entity.EntityInterface;
-import caosdb.server.utils.EntityStatus;
 
 public class InsertEntityDatatype extends BackendTransaction {
 
@@ -27,7 +25,6 @@ public class InsertEntityDatatype extends BackendTransaction {
       t.execute(e);
     } catch (final IntegrityException exc) {
       this.entity.addError(ERROR_INTEGRITY_VIOLATION);
-      this.entity.setEntityStatus(EntityStatus.CORRUPT);
       throw exc;
     }
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/InsertEntityProperties.java b/src/main/java/caosdb/server/database/backend/transaction/InsertEntityProperties.java
index 05e4dbce..d5e32df1 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/InsertEntityProperties.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/InsertEntityProperties.java
@@ -22,6 +22,9 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.DatabaseUtils;
 import caosdb.server.database.backend.interfaces.InsertEntityPropertiesImpl;
@@ -35,9 +38,6 @@ import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.Role;
 import caosdb.server.entity.StatementStatus;
 import caosdb.server.entity.wrapper.Property;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.List;
 
 public class InsertEntityProperties extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/InsertFile.java b/src/main/java/caosdb/server/database/backend/transaction/InsertFile.java
index 7fa04fbb..fe479b20 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/InsertFile.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/InsertFile.java
@@ -22,12 +22,12 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.io.IOException;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.Message;
 import caosdb.server.utils.EntityStatus;
-import java.io.IOException;
 
 public class InsertFile extends BackendTransaction {
 
@@ -38,7 +38,7 @@ public class InsertFile extends BackendTransaction {
   }
 
   @Override
-  public void execute() throws TransactionException {
+  public void execute(){
     try {
       if (this.entity.getEntityStatus() == EntityStatus.QUALIFIED) {
 
@@ -46,7 +46,6 @@ public class InsertFile extends BackendTransaction {
           getUndoHandler().append(this.entity.getFileProperties().storeFile());
         } catch (final Message m) {
           this.entity.addMessage(m);
-          this.entity.setEntityStatus(EntityStatus.CORRUPT);
           throw new TransactionException(m);
         }
       }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/InsertLogRecord.java b/src/main/java/caosdb/server/database/backend/transaction/InsertLogRecord.java
index 43a21d48..c951712a 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/InsertLogRecord.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/InsertLogRecord.java
@@ -22,11 +22,11 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.List;
+import java.util.logging.LogRecord;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.InsertLogRecordImpl;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.List;
-import java.util.logging.LogRecord;
 
 public class InsertLogRecord extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java
index f6294483..1d11d85c 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java
@@ -23,14 +23,12 @@
 package caosdb.server.database.backend.transaction;
 
 import static caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.InsertSparseEntityImpl;
 import caosdb.server.database.exceptions.IntegrityException;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.entity.EntityInterface;
-import caosdb.server.utils.EntityStatus;
 import caosdb.server.utils.Undoable;
 
 public class InsertSparseEntity extends BackendTransaction {
@@ -53,7 +51,6 @@ public class InsertSparseEntity extends BackendTransaction {
       t.execute(e);
     } catch (final IntegrityException exc) {
       this.entity.addError(ERROR_INTEGRITY_VIOLATION);
-      this.entity.setEntityStatus(EntityStatus.CORRUPT);
       throw exc;
     }
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RegisterSubDomain.java b/src/main/java/caosdb/server/database/backend/transaction/RegisterSubDomain.java
index 08b999d0..f5cd5604 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RegisterSubDomain.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RegisterSubDomain.java
@@ -22,10 +22,10 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.Deque;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.RegisterSubDomainImpl;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.Deque;
 
 public class RegisterSubDomain extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveAll.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveAll.java
index 5820547c..28f8e344 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveAll.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveAll.java
@@ -22,12 +22,12 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.List;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.RetrieveAllImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.RetrieveEntity;
 import caosdb.server.entity.container.TransactionContainer;
-import java.util.List;
 
 public class RetrieveAll extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveAllUncheckedFiles.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveAllUncheckedFiles.java
index b9969424..192428e7 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveAllUncheckedFiles.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveAllUncheckedFiles.java
@@ -22,11 +22,11 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.Iterator;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.proto.SparseEntity;
-import java.util.Iterator;
 
 public class RetrieveAllUncheckedFiles extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveDatatypes.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveDatatypes.java
index 44f8427a..08eac872 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveDatatypes.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveDatatypes.java
@@ -22,6 +22,7 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.ArrayList;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl;
 import caosdb.server.database.exceptions.TransactionException;
@@ -30,7 +31,6 @@ import caosdb.server.entity.Entity;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.RetrieveEntity;
 import caosdb.server.entity.container.Container;
-import java.util.ArrayList;
 
 public class RetrieveDatatypes extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java
index 59836abc..62edee0d 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java
@@ -23,8 +23,8 @@
 package caosdb.server.database.backend.transaction;
 
 import caosdb.server.database.BackendTransaction;
-import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.EntityInterface;
+import caosdb.server.entity.RetrieveEntity;
 import caosdb.server.entity.Role;
 import caosdb.server.entity.container.Container;
 import caosdb.server.utils.EntityStatus;
@@ -34,7 +34,7 @@ public class RetrieveFullEntity extends BackendTransaction {
   private final Container<? extends EntityInterface> container;
 
   public RetrieveFullEntity(final EntityInterface entity) {
-    final Container<EntityInterface> c = new Container<EntityInterface>();
+    final Container<EntityInterface> c = new Container<>();
     c.add(entity);
     this.container = c;
   }
@@ -43,8 +43,12 @@ public class RetrieveFullEntity extends BackendTransaction {
     this.container = container;
   }
 
+  public RetrieveFullEntity(Integer id) {
+    this(new RetrieveEntity(id));
+  }
+
   @Override
-  public void execute() throws TransactionException {
+  public void execute() {
     for (final EntityInterface e : this.container) {
       if (e.hasId() && e.getId() > 0 && e.getEntityStatus() == EntityStatus.QUALIFIED) {
 
@@ -60,4 +64,8 @@ public class RetrieveFullEntity extends BackendTransaction {
       }
     }
   }
+  
+  public Container<? extends EntityInterface> getContainer() {
+    return container;
+  }
 }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveLogRecord.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveLogRecord.java
index 42211d43..a08d737f 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveLogRecord.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveLogRecord.java
@@ -22,12 +22,12 @@
  */
 package caosdb.server.database.backend.transaction;
 
-import caosdb.server.database.BackendTransaction;
-import caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl;
-import caosdb.server.database.exceptions.TransactionException;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
+import caosdb.server.database.BackendTransaction;
+import caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl;
+import caosdb.server.database.exceptions.TransactionException;
 
 public class RetrieveLogRecord extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java
index 5d1545d2..0169b087 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java
@@ -22,6 +22,8 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.ArrayList;
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.database.CacheableBackendTransaction;
@@ -31,8 +33,6 @@ import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.misc.Cache;
 import caosdb.server.database.proto.VerySparseEntity;
 import caosdb.server.entity.EntityInterface;
-import java.util.ArrayList;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrieveParents
     extends CacheableBackendTransaction<Integer, ArrayList<VerySparseEntity>> {
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrievePermissionRules.java b/src/main/java/caosdb/server/database/backend/transaction/RetrievePermissionRules.java
index c0daecbc..ef99a55b 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrievePermissionRules.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrievePermissionRules.java
@@ -22,6 +22,8 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.HashSet;
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.database.CacheableBackendTransaction;
@@ -29,8 +31,6 @@ import caosdb.server.database.backend.interfaces.RetrievePermissionRulesImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.misc.Cache;
 import caosdb.server.permissions.PermissionRule;
-import java.util.HashSet;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrievePermissionRules
     extends CacheableBackendTransaction<String, HashSet<PermissionRule>> {
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
index b75d91ac..98f7994c 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
@@ -22,6 +22,8 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.ArrayList;
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.database.CacheableBackendTransaction;
@@ -33,8 +35,6 @@ import caosdb.server.database.proto.ProtoProperty;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.Role;
 import caosdb.server.entity.wrapper.Property;
-import java.util.ArrayList;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrieveProperties
     extends CacheableBackendTransaction<Integer, ArrayList<ProtoProperty>> {
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveRole.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveRole.java
index e4587996..ef5a5ec6 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveRole.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveRole.java
@@ -22,6 +22,7 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.accessControl.Role;
@@ -29,7 +30,6 @@ import caosdb.server.database.CacheableBackendTransaction;
 import caosdb.server.database.backend.interfaces.RetrieveRoleImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.misc.Cache;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrieveRole extends CacheableBackendTransaction<String, Role> {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java
index df9f5867..4d533068 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java
@@ -22,6 +22,7 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.database.CacheableBackendTransaction;
@@ -33,7 +34,6 @@ import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.entity.Entity;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.utils.EntityStatus;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrieveSparseEntity extends CacheableBackendTransaction<Integer, SparseEntity> {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveTransactionHistory.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveTransactionHistory.java
index cb9cdd9e..795e1691 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveTransactionHistory.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveTransactionHistory.java
@@ -22,6 +22,8 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.ArrayList;
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.datetime.UTCDateTime;
 import caosdb.server.database.CacheableBackendTransaction;
 import caosdb.server.database.backend.interfaces.RetrieveTransactionHistoryImpl;
@@ -29,8 +31,6 @@ import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.proto.ProtoTransactionLogMessage;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.utils.TransactionLogMessage;
-import java.util.ArrayList;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrieveTransactionHistory
     extends CacheableBackendTransaction<Integer, ArrayList<ProtoTransactionLogMessage>> {
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveUser.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveUser.java
index 7492df38..9ccc4582 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveUser.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveUser.java
@@ -22,6 +22,7 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.accessControl.Principal;
@@ -30,7 +31,6 @@ import caosdb.server.database.backend.interfaces.RetrieveUserImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.database.misc.Cache;
 import caosdb.server.database.proto.ProtoUser;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RetrieveUser extends CacheableBackendTransaction<Principal, ProtoUser> {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RuleLoader.java b/src/main/java/caosdb/server/database/backend/transaction/RuleLoader.java
index 781c2ce4..888cefc5 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RuleLoader.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RuleLoader.java
@@ -22,6 +22,8 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.ArrayList;
+import org.apache.commons.jcs.access.CacheAccess;
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
 import caosdb.server.database.CacheableBackendTransaction;
@@ -33,13 +35,10 @@ import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.container.TransactionContainer;
 import caosdb.server.jobs.Job;
 import caosdb.server.transaction.Transaction;
-import java.util.ArrayList;
-import org.apache.commons.jcs.access.CacheAccess;
 
 public class RuleLoader extends CacheableBackendTransaction<String, ArrayList<Rule>> {
 
   private final Transaction<? extends TransactionContainer> transaction;
-  private final TransactionContainer container;
   private final EntityInterface e;
   private final Integer entity;
   private final Integer domain;
@@ -49,12 +48,10 @@ public class RuleLoader extends CacheableBackendTransaction<String, ArrayList<Ru
       final Integer domain,
       final Integer entity,
       final EntityInterface e,
-      final TransactionContainer container,
       final Transaction<? extends TransactionContainer> transaction) {
     this.domain = domain;
     this.entity = entity;
     this.e = e;
-    this.container = container;
     this.transaction = transaction;
   }
 
@@ -94,7 +91,7 @@ public class RuleLoader extends CacheableBackendTransaction<String, ArrayList<Ru
   protected void process(final ArrayList<Rule> t) throws TransactionException {
     this.jobs = new ArrayList<Job>();
     for (final Rule r : t) {
-      this.jobs.add(Job.getJob(r.job, r.mode, this.e, this.container, this.transaction));
+      this.jobs.add(Job.getJob(r.job, r.mode, this.e, this.transaction));
     }
   }
 }
diff --git a/src/main/java/caosdb/server/database/backend/transaction/SetPermissionRules.java b/src/main/java/caosdb/server/database/backend/transaction/SetPermissionRules.java
index a632f299..4cb7e852 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/SetPermissionRules.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/SetPermissionRules.java
@@ -22,11 +22,11 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.Set;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.SetPermissionRulesImpl;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.permissions.PermissionRule;
-import java.util.Set;
 
 public class SetPermissionRules extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/database/backend/transaction/UpdateUserRoles.java b/src/main/java/caosdb/server/database/backend/transaction/UpdateUserRoles.java
index 359bbb3a..fc6abf16 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/UpdateUserRoles.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/UpdateUserRoles.java
@@ -22,11 +22,11 @@
  */
 package caosdb.server.database.backend.transaction;
 
+import java.util.HashSet;
 import caosdb.server.accessControl.Principal;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.interfaces.UpdateUserRolesImpl;
 import caosdb.server.database.exceptions.TransactionException;
-import java.util.HashSet;
 
 public class UpdateUserRoles extends BackendTransaction {
 
diff --git a/src/main/java/caosdb/server/entity/Entity.java b/src/main/java/caosdb/server/entity/Entity.java
index ff2f95de..c18d79ec 100644
--- a/src/main/java/caosdb/server/entity/Entity.java
+++ b/src/main/java/caosdb/server/entity/Entity.java
@@ -52,6 +52,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.AuthorizationException;
 import org.apache.shiro.authz.Permission;
@@ -73,7 +74,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
   private AbstractDatatype datatype = null;
   private final ParentContainer parents = new ParentContainer(this);
   private final PropertyContainer properties = new PropertyContainer(this);
-  private final ArrayList<TransactionLogMessage> history = new ArrayList<TransactionLogMessage>();
+  private final List<TransactionLogMessage> history = new ArrayList<>();
   private List<Selection> selections = null;
   private EntityACL entityACL = null;
 
@@ -118,7 +119,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   @Override
   public final boolean hasProperties() {
-    return this.properties != null && !this.properties.isEmpty();
+    return !this.properties.isEmpty();
   }
 
   @Override
@@ -255,10 +256,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   @Override
   public final boolean hasDescription() {
-    if (this.description == null || this.description.isEmpty() || this.description.equals("")) {
-      return false;
-    }
-    return true;
+    return  !(this.description == null || this.description.isEmpty() || this.description.equals(""));
   }
 
   @Override
@@ -304,6 +302,9 @@ public class Entity extends AbstractObservable implements EntityInterface {
     if (hasEntityStatus() && getEntityStatus() == entityStatus) {
       return;
     }
+    if(this.entityStatus == EntityStatus.UNQUALIFIED ) {
+      throw new CaosDBException("It is not allowed to change the state again, once an UNQUALIFIED state has been reached.");
+    }
     this.entityStatus = entityStatus;
     notifyObservers(ENTITY_STATUS_CHANGED_EVENT);
   }
@@ -599,10 +600,10 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   /** Errors, Warnings and Info messages for this entity. */
-  private final HashSet<ToElementable> messages = new HashSet<ToElementable>();
+  private final Set<ToElementable> messages = new HashSet<>();
 
   @Override
-  public final HashSet<ToElementable> getMessages() {
+  public final Set<ToElementable> getMessages() {
     return this.messages;
   }
 
@@ -614,11 +615,9 @@ public class Entity extends AbstractObservable implements EntityInterface {
   @Override
   public final boolean hasMessage(final String type) {
     for (final ToElementable m : this.messages) {
-      if (m instanceof Message) {
-        if (((Message) m).getType().equalsIgnoreCase(type)) {
+      if (m instanceof Message && ((Message) m).getType().equalsIgnoreCase(type)) {
           return true;
         }
-      }
     }
     return false;
   }
@@ -629,29 +628,22 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   @Override
-  public final LinkedList<Message> getMessages(final String type) {
-    final LinkedList<Message> ret = new LinkedList<Message>();
+  public final List<Message> getMessages(final String type) {
+    final LinkedList<Message> ret = new LinkedList<>();
     for (final ToElementable m : this.messages) {
-      if (m instanceof Message) {
-        if (((Message) m).getType().equalsIgnoreCase(type)) {
+      if (m instanceof Message && ((Message) m).getType().equalsIgnoreCase(type)) {
           ret.add((Message) m);
-        }
       }
     }
-    if (ret.isEmpty()) {
-      return null;
-    }
     return ret;
   }
 
   @Override
   public final Message getMessage(final String type, final Integer code) {
     for (final ToElementable m : this.messages) {
-      if (m instanceof Message) {
-        if (((Message) m).getType().equalsIgnoreCase(type) && ((Message) m).getCode() == code) {
+      if (m instanceof Message&& ((Message) m).getType().equalsIgnoreCase(type) && ((Message) m).getCode() == code) {
           return (Message) m;
         }
-      }
     }
     return null;
   }
@@ -663,6 +655,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   @Override
   public final void addError(final Message m) {
+    setEntityStatus(EntityStatus.UNQUALIFIED);
     if (m.getType().equalsIgnoreCase(MessageType.Error.toString())) {
       addMessage(m);
     } else {
@@ -755,7 +748,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
         this.setDatatype(element.getAttributeValue("datatype"));
       } catch (final IllegalArgumentException e) {
         addError(ServerMessages.UNKNOWN_DATATYPE);
-        setEntityStatus(EntityStatus.UNQUALIFIED);
+        
       }
     }
 
@@ -826,7 +819,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
       } else {
         final String type = pe.getName();
         Integer code = null;
-        String description = null;
+        String localDescription = null;
         String body = null;
 
         // Parse MESSAGE CODE.
@@ -843,7 +836,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
         // Parse MESSAGE DESCRIPTION.
         if (pe.getAttribute("description") != null
             && !pe.getAttributeValue("description").equals("")) {
-          description = pe.getAttributeValue("description");
+          localDescription = pe.getAttributeValue("description");
         }
 
         // Parse MESSAGE BODY.
@@ -851,7 +844,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
           body = pe.getTextTrim();
         }
 
-        addMessage(new Message(type, code, description, body));
+        addMessage(new Message(type, code, localDescription, body));
       }
     }
 
@@ -1027,7 +1020,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
   }
 
   @Override
-  public ArrayList<TransactionLogMessage> getTransactionLogMessages() {
+  public List<TransactionLogMessage> getTransactionLogMessages() {
     return this.history;
   }
 
@@ -1086,7 +1079,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   public EntityInterface addSelections(final List<Selection> selections) {
     if (this.selections == null) {
-      this.selections = new LinkedList<Selection>();
+      this.selections = new LinkedList<>();
     }
     this.selections.addAll(selections);
     return this;
diff --git a/src/main/java/caosdb/server/entity/EntityInterface.java b/src/main/java/caosdb/server/entity/EntityInterface.java
index 315a80e8..2bfe32a4 100644
--- a/src/main/java/caosdb/server/entity/EntityInterface.java
+++ b/src/main/java/caosdb/server/entity/EntityInterface.java
@@ -22,6 +22,9 @@
  */
 package caosdb.server.entity;
 
+import java.util.List;
+import org.apache.shiro.authz.Permission;
+import org.apache.shiro.subject.Subject;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.database.proto.VerySparseEntity;
 import caosdb.server.datatype.AbstractDatatype;
@@ -37,10 +40,6 @@ import caosdb.server.permissions.EntityACL;
 import caosdb.server.utils.Observable;
 import caosdb.server.utils.TransactionLogMessage;
 import caosdb.unit.Unit;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.shiro.authz.Permission;
-import org.apache.shiro.subject.Subject;
 
 public interface EntityInterface
     extends JobTarget, Observable, ToElementable, WriteEntity, TransactionEntity {
@@ -148,7 +147,7 @@ public interface EntityInterface
 
   public abstract void addTransactionLog(TransactionLogMessage transactionLogMessage);
 
-  public abstract ArrayList<TransactionLogMessage> getTransactionLogMessages();
+  public abstract List<TransactionLogMessage> getTransactionLogMessages();
 
   public abstract boolean hasTransactionLogMessages();
 
diff --git a/src/main/java/caosdb/server/entity/TransactionEntity.java b/src/main/java/caosdb/server/entity/TransactionEntity.java
index cb0782d0..36c581b5 100644
--- a/src/main/java/caosdb/server/entity/TransactionEntity.java
+++ b/src/main/java/caosdb/server/entity/TransactionEntity.java
@@ -22,16 +22,14 @@
  */
 package caosdb.server.entity;
 
-import caosdb.server.CaosDBException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.jdom2.Element;
 import caosdb.server.entity.xml.ToElementStrategy;
 import caosdb.server.entity.xml.ToElementable;
 import caosdb.server.query.Query.Selection;
 import caosdb.server.utils.EntityStatus;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import org.jdom2.Element;
 
 public interface TransactionEntity {
 
@@ -45,13 +43,13 @@ public interface TransactionEntity {
 
   public abstract String getCuid();
 
-  public abstract void setCuid(String cuid) throws CaosDBException;
+  public abstract void setCuid(String cuid);
 
   public abstract void setToElementStragegy(ToElementStrategy s);
 
   public abstract Element toElement();
 
-  public abstract HashSet<ToElementable> getMessages();
+  public abstract Set<ToElementable> getMessages();
 
   public abstract boolean hasMessages();
 
@@ -59,7 +57,7 @@ public interface TransactionEntity {
 
   public abstract void removeMessage(Message m);
 
-  public abstract LinkedList<Message> getMessages(String type);
+  public abstract List<Message> getMessages(String type);
 
   public abstract Message getMessage(String type, Integer code);
 
@@ -75,7 +73,7 @@ public interface TransactionEntity {
 
   public abstract ToElementStrategy getToElementStrategy();
 
-  public abstract HashMap<String, String> getFlags();
+  public abstract Map<String, String> getFlags();
 
   public abstract void setFlag(String key, String value);
 
diff --git a/src/main/java/caosdb/server/entity/container/ParentContainer.java b/src/main/java/caosdb/server/entity/container/ParentContainer.java
index 64bbb6ff..461760b8 100644
--- a/src/main/java/caosdb/server/entity/container/ParentContainer.java
+++ b/src/main/java/caosdb/server/entity/container/ParentContainer.java
@@ -78,7 +78,6 @@ public class ParentContainer extends Container<Parent> {
 
     switch (parent.getEntityStatus()) {
       case UNQUALIFIED:
-      case CORRUPT:
       case DELETED:
       case NONEXISTENT:
         entity.addError(ServerMessages.ENTITY_HAS_UNQUALIFIED_PARENTS);
diff --git a/src/main/java/caosdb/server/entity/container/PropertyContainer.java b/src/main/java/caosdb/server/entity/container/PropertyContainer.java
index 8667901e..a80e2bfc 100644
--- a/src/main/java/caosdb/server/entity/container/PropertyContainer.java
+++ b/src/main/java/caosdb/server/entity/container/PropertyContainer.java
@@ -96,7 +96,6 @@ public class PropertyContainer extends Container<Property> {
     }
     switch (prop.getEntityStatus()) {
       case UNQUALIFIED:
-      case CORRUPT:
       case DELETED:
       case NONEXISTENT:
         entity.addError(ServerMessages.ENTITY_HAS_UNQUALIFIED_PROPERTIES);
diff --git a/src/main/java/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/caosdb/server/entity/container/TransactionContainer.java
index 763e1cd3..20668f54 100644
--- a/src/main/java/caosdb/server/entity/container/TransactionContainer.java
+++ b/src/main/java/caosdb/server/entity/container/TransactionContainer.java
@@ -32,6 +32,7 @@ import caosdb.server.jobs.JobTarget;
 import caosdb.server.utils.EntityStatus;
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.List;
 import org.apache.shiro.subject.Subject;
 import org.jdom2.Element;
 
@@ -77,7 +78,11 @@ public class TransactionContainer extends Container<Entity> implements ToElement
     this.status = status;
   }
 
-  private final LinkedList<ToElementable> messages = new LinkedList<ToElementable>();
+  private final LinkedList<ToElementable> messages = new LinkedList<>();
+
+  public List<ToElementable> getMessages() {
+    return messages;
+  }
 
   public void addMessage(final ToElementable m) {
     this.messages.add(m);
@@ -177,4 +182,5 @@ public class TransactionContainer extends Container<Entity> implements ToElement
   public boolean skipJob() {
     return false;
   }
+
 }
diff --git a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java
index 7ae648cc..8b6ec031 100644
--- a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java
+++ b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java
@@ -22,7 +22,12 @@
  */
 package caosdb.server.entity.wrapper;
 
-import caosdb.server.CaosDBException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.shiro.authz.Permission;
+import org.apache.shiro.subject.Subject;
+import org.jdom2.Element;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.database.proto.VerySparseEntity;
 import caosdb.server.datatype.AbstractDatatype;
@@ -42,14 +47,6 @@ import caosdb.server.utils.EntityStatus;
 import caosdb.server.utils.Observer;
 import caosdb.server.utils.TransactionLogMessage;
 import caosdb.unit.Unit;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import org.apache.shiro.authz.Permission;
-import org.apache.shiro.subject.Subject;
-import org.jdom2.Element;
 
 public class EntityWrapper implements EntityInterface {
 
@@ -155,7 +152,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public void setCuid(final String cuid) throws CaosDBException {
+  public void setCuid(final String cuid) {
     this.entity.setCuid(cuid);
   }
 
@@ -315,7 +312,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public HashSet<ToElementable> getMessages() {
+  public Set<ToElementable> getMessages() {
     return this.entity.getMessages();
   }
 
@@ -335,7 +332,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public LinkedList<Message> getMessages(final String type) {
+  public List<Message> getMessages(final String type) {
     return this.entity.getMessages(type);
   }
 
@@ -405,7 +402,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public HashMap<String, String> getFlags() {
+  public Map<String, String> getFlags() {
     return this.entity.getFlags();
   }
 
@@ -450,7 +447,7 @@ public class EntityWrapper implements EntityInterface {
   }
 
   @Override
-  public ArrayList<TransactionLogMessage> getTransactionLogMessages() {
+  public List<TransactionLogMessage> getTransactionLogMessages() {
     return this.entity.getTransactionLogMessages();
   }
 
diff --git a/src/main/java/caosdb/server/jobs/ContainerJob.java b/src/main/java/caosdb/server/jobs/ContainerJob.java
index 4b4a80e2..6cef06e3 100644
--- a/src/main/java/caosdb/server/jobs/ContainerJob.java
+++ b/src/main/java/caosdb/server/jobs/ContainerJob.java
@@ -22,17 +22,25 @@
  */
 package caosdb.server.jobs;
 
+import caosdb.server.entity.Message;
 import caosdb.server.entity.container.TransactionContainer;
+import caosdb.server.utils.EntityStatus;
 
 public abstract class ContainerJob extends Job {
 
   @Override
-  protected final TransactionContainer getContainer() {
+  public
+  final TransactionContainer getContainer() {
     return super.getContainer();
   }
 
   @Override
   public JobTarget getTarget() {
     return getContainer();
-  };
+  }
+
+  public void addError(Message error) {
+    getContainer().addMessage(error);
+    getContainer().setStatus(EntityStatus.UNQUALIFIED);
+  }
 }
diff --git a/src/main/java/caosdb/server/jobs/Job.java b/src/main/java/caosdb/server/jobs/Job.java
index 48a4ed75..13209335 100644
--- a/src/main/java/caosdb/server/jobs/Job.java
+++ b/src/main/java/caosdb/server/jobs/Job.java
@@ -22,9 +22,20 @@
  */
 package caosdb.server.jobs;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.Permission;
+import org.apache.shiro.subject.Subject;
+import org.reflections.Reflections;
+import caosdb.server.CaosDBException;
 import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.GetIDByName;
 import caosdb.server.database.backend.transaction.IsSubType;
+import caosdb.server.database.backend.transaction.RetrieveFullEntity;
 import caosdb.server.database.backend.transaction.RetrieveParents;
 import caosdb.server.database.backend.transaction.RetrieveSparseEntity;
 import caosdb.server.database.backend.transaction.RuleLoader;
@@ -42,13 +53,6 @@ import caosdb.server.utils.EntityStatus;
 import caosdb.server.utils.Observable;
 import caosdb.server.utils.Observer;
 import caosdb.server.utils.ServerMessages;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Set;
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authz.Permission;
-import org.reflections.Reflections;
 
 public abstract class Job extends AbstractObservable implements Observer {
   private Transaction<? extends TransactionContainer> transaction = null;
@@ -57,7 +61,6 @@ public abstract class Job extends AbstractObservable implements Observer {
   public abstract JobTarget getTarget();
 
   private EntityInterface entity = null;
-  private final boolean isDone = false;
 
   protected <S, T> HashMap<S, T> getCache(final String name) {
     return getTransaction().getCache(name);
@@ -70,14 +73,18 @@ public abstract class Job extends AbstractObservable implements Observer {
   protected String getRequestId() {
     return getContainer().getRequestId();
   }
+  
+  protected Subject getUser(){
+    return getTransaction().getTransactor();
+  }
 
-  protected void appendJob(final EntityInterface entity, final Class<? extends Job> clazz) {
+  protected ScheduledJob appendJob(final EntityInterface entity, final Class<? extends Job> clazz) {
     try {
       final Job job = clazz.newInstance();
-      job.init(getMode(), entity, getContainer(), getTransaction());
-      getTransaction().getSchedule().add(job);
+      job.init(getMode(), entity, getTransaction());
+      return getTransaction().getSchedule().add(job);
     } catch (InstantiationException | IllegalAccessException e) {
-      throw new RuntimeException(e);
+      throw new CaosDBException(e);
     }
   }
 
@@ -100,7 +107,6 @@ public abstract class Job extends AbstractObservable implements Observer {
   public final Job init(
       final Mode mode,
       final EntityInterface entity,
-      final TransactionContainer entities,
       final Transaction<? extends TransactionContainer> transaction) {
     this.mode = mode;
     this.entity = entity;
@@ -108,19 +114,19 @@ public abstract class Job extends AbstractObservable implements Observer {
     return this;
   }
 
-  public final boolean isDone() {
-    return this.isDone;
-  }
-
   /** to be overridden */
   protected abstract void run();
 
-  protected void getJobFromSchedule(
+  protected void runJobFromSchedule(
       final EntityInterface entity, final Class<? extends Job> jobclass) {
     getTransaction().getSchedule().runJob(entity, jobclass);
   }
+  
+  protected void runJobFromSchedule(ScheduledJob job){
+    getTransaction().getSchedule().runJob(job); 
+  }
 
-  EntityInterface getEntity() {
+  public EntityInterface getEntity() {
     return this.entity;
   }
 
@@ -150,11 +156,11 @@ public abstract class Job extends AbstractObservable implements Observer {
   }
 
   protected final boolean isValidSubTypeNoCache(final int child, final int parent) {
-    return Database.execute(new IsSubType(child, parent), getTransaction().getAccess()).isSubType();
+    return child==parent || Database.execute(new IsSubType(child, parent), getTransaction().getAccess()).isSubType();
   }
 
   protected final EntityInterface retrieveValidSparseEntityByName(final String name)
-      throws TransactionException, Message {
+      throws Message {
     return retrieveValidSparseEntityById(retrieveValidIDByName(name));
   }
 
@@ -167,6 +173,9 @@ public abstract class Job extends AbstractObservable implements Observer {
     return ret;
   }
 
+  protected final EntityInterface retrieveValidEntity(Integer id){
+    return Database.execute(new RetrieveFullEntity(id), getTransaction().getAccess()).getContainer().get(0);
+  }
   protected final Integer retrieveValidIDByName(final String name) {
     return Database.execute(new GetIDByName(name), getTransaction().getAccess()).getId();
   }
@@ -192,34 +201,24 @@ public abstract class Job extends AbstractObservable implements Observer {
   }
 
   static HashMap<String, Class<? extends Job>> allClasses = null;
+  private static List<Class<? extends Job>> loadAlways;
 
   public static Job getJob(
       final String job,
       final Mode mode,
       final EntityInterface entity,
-      final TransactionContainer entities,
       final Transaction<? extends TransactionContainer> transaction) {
     scanJobClasspath();
 
     final Class<? extends Job> jobClass = allClasses.get(job.toLowerCase());
-    Job ret;
-    try {
-      if (jobClass != null) {
-        ret = jobClass.newInstance();
-        ret.init(mode, entity, entities, transaction);
-        return ret;
-      }
-      return null;
-    } catch (final InstantiationException e) {
-      throw new TransactionException(e);
-    } catch (final IllegalAccessException e) {
-      throw new TransactionException(e);
-    }
+    return getJob(jobClass, mode, entity, transaction);
   }
 
   private static void scanJobClasspath() {
-    if (allClasses == null) {
-      allClasses = new HashMap<String, Class<? extends Job>>();
+    
+    if (allClasses == null || loadAlways == null) {
+      allClasses = new HashMap<>();
+      loadAlways = new ArrayList<>();
       Reflections jobPackage = new Reflections("caosdb.server.jobs.core");
       Set<Class<? extends Job>> allClassesSet = jobPackage.getSubTypesOf(Job.class);
       allClassesSet.addAll(jobPackage.getSubTypesOf(FlagJob.class));
@@ -241,83 +240,105 @@ public abstract class Job extends AbstractObservable implements Observer {
           if (flagName.length() > 0) {
             allClasses.put(flagName.toLowerCase(), c);
           }
+          if (c.getAnnotation(JobAnnotation.class).loadAlways()){
+            loadAlways.add(c);
+          }
         }
       }
     }
   }
 
-  protected ArrayList<Job> loadDataTypeSpecificJobs() {
-    return Job.loadDataTypeSpecificJobs(getEntity(), getContainer(), getTransaction());
+  protected List<Job> loadDataTypeSpecificJobs() {
+    return Job.loadDataTypeSpecificJobs(getEntity(), getTransaction());
   }
 
-  public static ArrayList<Job> loadDataTypeSpecificJobs(
+  public static List<Job> loadDataTypeSpecificJobs(
       final EntityInterface entity,
-      final TransactionContainer entities,
       final Transaction<? extends TransactionContainer> transaction) {
 
-    return loadDataTypeSpecificJobs(entity.getDatatype(), entity, entities, transaction);
+    return loadDataTypeSpecificJobs(entity.getDatatype(), entity, transaction);
   }
 
-  private static ArrayList<Job> loadDataTypeSpecificJobs(
+  private static List<Job> loadDataTypeSpecificJobs(
       final AbstractDatatype dt,
       final EntityInterface entity,
-      final TransactionContainer entities,
       final Transaction<? extends TransactionContainer> transaction) {
     if (dt == null) {
       return new ArrayList<Job>();
     }
     if (dt instanceof ReferenceDatatype2) {
-      final RuleLoader t = new RuleLoader(0, 17, entity, entities, transaction);
+      final RuleLoader t = new RuleLoader(0, 17, entity, transaction);
       return Database.execute(t, transaction.getAccess()).getJobs();
     } else if (dt instanceof AbstractCollectionDatatype) {
       final AbstractDatatype datatype = ((AbstractCollectionDatatype) dt).getDatatype();
-      return loadDataTypeSpecificJobs(datatype, entity, entities, transaction);
+      return loadDataTypeSpecificJobs(datatype, entity, transaction);
     } else if (dt.getId() != null) {
-      final RuleLoader t = new RuleLoader(0, dt.getId(), entity, entities, transaction);
+      final RuleLoader t = new RuleLoader(0, dt.getId(), entity, transaction);
       return Database.execute(t, transaction.getAccess()).getJobs();
     } else {
       return null;
     }
   }
 
-  public static ArrayList<Job> loadStandardJobs(
+  public static List<Job> loadStandardJobs(
       final EntityInterface entity,
-      final TransactionContainer entities,
       final Transaction<? extends TransactionContainer> transaction) {
 
-    final ArrayList<Job> jobs = new ArrayList<Job>();
+    final ArrayList<Job> jobs = new ArrayList<>();    
+    // load permanent jobs
+    for (Class<? extends Job> j : loadAlways) {
+      if(j.getAnnotation(JobAnnotation.class).transaction().isInstance(transaction)){
+        jobs.add(getJob(j, Mode.MUST, entity, transaction));
+      }
+    }
+    
     // load general rules
     {
-      final RuleLoader t = new RuleLoader(0, 0, entity, entities, transaction);
+      final RuleLoader t = new RuleLoader(0, 0, entity, transaction);
       jobs.addAll(Database.execute(t, transaction.getAccess()).getJobs());
     }
 
     // load Role specific rules
     if (entity.hasRole()) {
       final RuleLoader t =
-          new RuleLoader(0, entity.getRole().getId(), entity, entities, transaction);
+          new RuleLoader(0, entity.getRole().getId(), entity, transaction);
       jobs.addAll(Database.execute(t, transaction.getAccess()).getJobs());
     }
 
     // load data type specific rules
-    jobs.addAll(loadDataTypeSpecificJobs(entity, entities, transaction));
+    jobs.addAll(loadDataTypeSpecificJobs(entity, transaction));
 
     return jobs;
   }
 
-  public static LinkedList<Job> loadJobs(
+  private static Job getJob(Class<? extends Job> jobClass, Mode mode, EntityInterface entity,
+      Transaction<? extends TransactionContainer> transaction) {
+    Job ret;
+    try {
+      
+      if (jobClass != null) {
+        ret = jobClass.newInstance();
+        ret.init(mode, entity, transaction);
+        return ret;
+      }
+      return null;
+    } catch (final InstantiationException | IllegalAccessException e) {
+      throw new TransactionException(e);
+    }
+  }
+
+  public static List<Job> loadJobs(
       final EntityInterface entity,
-      final TransactionContainer entities,
       final Transaction<? extends TransactionContainer> transaction) {
-    final LinkedList<Job> jobs = new LinkedList<Job>();
+    final LinkedList<Job> jobs = new LinkedList<>();
 
     // general rules, role rules, data type rules
-    jobs.addAll(loadStandardJobs(entity, entities, transaction));
+    jobs.addAll(loadStandardJobs(entity, transaction));
 
     // load flag jobs
     if (!entity.getFlags().isEmpty()) {
       for (final String key : entity.getFlags().keySet()) {
-        final Job j = getJob(key, Mode.MUST, entity, entities, transaction);
+        final Job j = getJob(key, Mode.MUST, entity, transaction);
         if (j != null) {
           if (j instanceof FlagJob) {
             ((FlagJob) j).setValue(entity.getFlag(key));
@@ -332,7 +353,7 @@ public abstract class Job extends AbstractObservable implements Observer {
       for (final EntityInterface p : entity.getParents()) {
         if (!p.getFlags().isEmpty()) {
           for (final String key : p.getFlags().keySet()) {
-            final Job j = getJob(key, Mode.MUST, entity, entities, transaction);
+            final Job j = getJob(key, Mode.MUST, entity, transaction);
             if (j != null) {
               if (j instanceof FlagJob) {
                 ((FlagJob) j).setValue(p.getFlag(key));
@@ -351,7 +372,7 @@ public abstract class Job extends AbstractObservable implements Observer {
       for (final EntityInterface p : entity.getProperties()) {
         if (!p.getFlags().isEmpty()) {
           for (final String key : p.getFlags().keySet()) {
-            final Job j = getJob(key, Mode.MUST, entity, entities, transaction);
+            final Job j = getJob(key, Mode.MUST, entity, transaction);
             if (j != null) {
               if (j instanceof FlagJob) {
                 ((FlagJob) j).setValue(p.getFlag(key));
@@ -366,7 +387,7 @@ public abstract class Job extends AbstractObservable implements Observer {
     // load jobs for the properties
     if (entity.hasProperties()) {
       for (final EntityInterface p : entity.getProperties()) {
-        jobs.addAll(loadJobs(p, entities, transaction));
+        jobs.addAll(loadJobs(p, transaction));
       }
     }
 
diff --git a/src/main/java/caosdb/server/jobs/JobAnnotation.java b/src/main/java/caosdb/server/jobs/JobAnnotation.java
index 48f5d91c..97263aeb 100644
--- a/src/main/java/caosdb/server/jobs/JobAnnotation.java
+++ b/src/main/java/caosdb/server/jobs/JobAnnotation.java
@@ -47,4 +47,11 @@ public @interface JobAnnotation {
    * @return true per default.
    */
   boolean loadOnDefault() default true;
+
+  /**
+   * Load for every transaction that is a subclass of 'transaction'.
+   * 
+   * @return false per default.
+   */
+  boolean loadAlways() default false;
 }
diff --git a/src/main/java/caosdb/server/jobs/Schedule.java b/src/main/java/caosdb/server/jobs/Schedule.java
index 12c3f8e1..367fdcbd 100644
--- a/src/main/java/caosdb/server/jobs/Schedule.java
+++ b/src/main/java/caosdb/server/jobs/Schedule.java
@@ -90,8 +90,10 @@ public class Schedule {
     }
   }
 
-  public void add(final Job j) {
-    this.jobs.add(new ScheduledJob(j));
+  public ScheduledJob add(final Job j) {
+    ScheduledJob ret = new ScheduledJob(j);
+    this.jobs.add(ret);
+    return ret;
   }
 
   public void runJobs(final JobExecutionTime time) {
@@ -104,7 +106,7 @@ public class Schedule {
     }
   }
 
-  private void runJob(final ScheduledJob scheduledJob) {
+  protected void runJob(final ScheduledJob scheduledJob) {
     if (!this.jobs.contains(scheduledJob)) {
       throw new RuntimeException("Job was not in schedule.");
     }
diff --git a/src/main/java/caosdb/server/jobs/core/Atomic.java b/src/main/java/caosdb/server/jobs/core/Atomic.java
index d8e1a6b6..cf6d99a0 100644
--- a/src/main/java/caosdb/server/jobs/core/Atomic.java
+++ b/src/main/java/caosdb/server/jobs/core/Atomic.java
@@ -37,15 +37,11 @@ public class Atomic extends ContainerJob {
   private boolean doCheck() {
     if (getContainer().getStatus() == EntityStatus.QUALIFIED) {
       for (final EntityInterface entity : getContainer()) {
-        switch (entity.getEntityStatus()) {
-          case CORRUPT:
-          case UNQUALIFIED:
-            getContainer().setStatus(EntityStatus.UNQUALIFIED);
-            getContainer().addMessage(ServerMessages.ATOMICITY_ERROR);
-            // job done. remove observer.
-            return false;
-          default:
-            break;
+        if(entity.getEntityStatus() == EntityStatus.UNQUALIFIED) {
+          getContainer().setStatus(EntityStatus.UNQUALIFIED);
+          getContainer().addMessage(ServerMessages.ATOMICITY_ERROR);
+          // job done. remove observer.
+          return false;
         }
       }
       // keep observer
diff --git a/src/main/java/caosdb/server/jobs/core/CheckDatatypePresent.java b/src/main/java/caosdb/server/jobs/core/CheckDatatypePresent.java
index 73297223..ca6ced6e 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckDatatypePresent.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckDatatypePresent.java
@@ -22,9 +22,9 @@
  */
 package caosdb.server.jobs.core;
 
+import java.util.List;
 import caosdb.server.database.exceptions.EntityDoesNotExistException;
 import caosdb.server.database.exceptions.EntityWasNotUniqueException;
-import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.datatype.AbstractCollectionDatatype;
 import caosdb.server.datatype.AbstractDatatype;
 import caosdb.server.datatype.ReferenceDatatype2;
@@ -36,7 +36,6 @@ import caosdb.server.jobs.Job;
 import caosdb.server.permissions.EntityPermission;
 import caosdb.server.utils.EntityStatus;
 import caosdb.server.utils.ServerMessages;
-import java.util.ArrayList;
 
 /**
  * Check whether the entity has a data type. Assign the data type of the abstract property if
@@ -80,7 +79,7 @@ public final class CheckDatatypePresent extends EntityJob {
         }
 
         // run jobsreturn this.entities;
-        final ArrayList<Job> datatypeJobs = loadDataTypeSpecificJobs();
+        final List<Job> datatypeJobs = loadDataTypeSpecificJobs();
         getTransaction().getSchedule().addAll(datatypeJobs);
         for (final Job job : datatypeJobs) {
           getTransaction().getSchedule().runJob(job);
@@ -97,15 +96,11 @@ public final class CheckDatatypePresent extends EntityJob {
       } else {
         getEntity().addError(m);
       }
-      getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
     } catch (final EntityDoesNotExistException exc) {
       getEntity().addError(ServerMessages.UNKNOWN_DATATYPE);
-      getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
     } catch (final EntityWasNotUniqueException exc) {
       getEntity().addError(ServerMessages.DATA_TYPE_NAME_DUPLICATES);
-      getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
     }
-    return;
   }
 
   private void checkReference2(final ReferenceDatatype2 datatype) throws Message {
@@ -152,7 +147,7 @@ public final class CheckDatatypePresent extends EntityJob {
     checkPermission(datatype, EntityPermission.USE_AS_DATA_TYPE);
   }
 
-  private void checkIfOverride() throws TransactionException, Message {
+  private void checkIfOverride() throws Message {
     if (getEntity().hasId() && getEntity().getId() > 0) {
       // get data type from database
       final EntityInterface foreign = retrieveValidSparseEntityById(getEntity().getId());
@@ -178,7 +173,7 @@ public final class CheckDatatypePresent extends EntityJob {
     }
   }
 
-  private void inheritDatatypeFromAbstractEntity() throws TransactionException, Message {
+  private void inheritDatatypeFromAbstractEntity() throws Message {
     // if this is a record type property or a concrete property, assign
     // the data type of the corresponding abstract property.
     if (getEntity().hasId() && getEntity().getId() > 0) {
@@ -207,16 +202,14 @@ public final class CheckDatatypePresent extends EntityJob {
         entity.setEntityStatus(EntityStatus.VALID);
       } catch (final EntityDoesNotExistException exc) {
         entity.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
-        entity.setEntityStatus(EntityStatus.UNQUALIFIED);
       } catch (final EntityWasNotUniqueException exc) {
         entity.addError(ServerMessages.CANNOT_IDENTIFY_ENTITY_UNIQUELY);
-        entity.setEntityStatus(EntityStatus.UNQUALIFIED);
       }
     }
   }
 
   private void getDataTypeFromParent() throws Message {
-    getJobFromSchedule(getEntity(), CheckParValid.class);
+    runJobFromSchedule(getEntity(), CheckParValid.class);
 
     AbstractDatatype datatype = null;
     for (final EntityInterface parent : getEntity().getParents()) {
@@ -225,12 +218,11 @@ public final class CheckDatatypePresent extends EntityJob {
         parentEntity = retrieveValidSparseEntityById(parent.getId());
       } else {
         parentEntity = getEntityById(parent.getId());
-        getJobFromSchedule(parentEntity, CheckDatatypePresent.class);
+        runJobFromSchedule(parentEntity, CheckDatatypePresent.class);
       }
       if (parentEntity.hasDatatype()) {
         if (datatype != null && !parentEntity.getDatatype().equals(datatype)) {
-          getEntity().addMessage(ServerMessages.DATATYPE_INHERITANCE_AMBIGUOUS);
-          getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
+          getEntity().addError(ServerMessages.DATATYPE_INHERITANCE_AMBIGUOUS);
           return;
         } else {
           datatype = parentEntity.getDatatype();
diff --git a/src/main/java/caosdb/server/jobs/core/CheckNoAdditionalPropertiesPresent.java b/src/main/java/caosdb/server/jobs/core/CheckNoAdditionalPropertiesPresent.java
new file mode 100644
index 00000000..1557401d
--- /dev/null
+++ b/src/main/java/caosdb/server/jobs/core/CheckNoAdditionalPropertiesPresent.java
@@ -0,0 +1,56 @@
+package caosdb.server.jobs.core;
+
+import java.util.HashSet;
+import java.util.Set;
+import caosdb.server.entity.EntityInterface;
+import caosdb.server.entity.Message;
+import caosdb.server.jobs.EntityJob;
+import caosdb.server.jobs.JobAnnotation;
+import caosdb.server.utils.EntityStatus;
+import caosdb.server.utils.ServerMessages;
+
+@JobAnnotation(flag="noAdditionalProperties", description="Fail if this entity has any property which has not been defined by the parents of this entity.")
+public class CheckNoAdditionalPropertiesPresent extends EntityJob {
+
+  private Set<EntityInterface> used = new HashSet<>();
+
+  @Override
+  protected void run() {
+    
+    // validate all parents and properties
+    runJobFromSchedule(getEntity(), CheckParOblPropPresent.class);
+    
+    
+    if(getEntity().getEntityStatus() == EntityStatus.QUALIFIED && getEntity().hasProperties()){
+      for(EntityInterface property : getEntity().getProperties()){
+        checkProperty(property);
+      }
+    }
+    
+  }
+  
+  public void checkProperty(EntityInterface property){
+    for(EntityInterface parent : getEntity().getParents()){
+      for(EntityInterface parentProperty : parent.getProperties()){
+        if(sameProperty(property, parentProperty) && !used.contains(parentProperty)){
+          used .add(parentProperty);
+        }
+      }
+      // not found!
+      addMessage(property,ServerMessages.ADDITIONAL_PROPERTY);
+    }
+  }
+
+  private void addMessage(EntityInterface property, Message message) {
+    if(getMode()==Mode.MUST) {
+      property.addError(message);
+    } else {
+      property.addWarning(message);
+    }
+  }
+
+  private boolean sameProperty(EntityInterface property, EntityInterface parentProperty) {
+    return property.getId() == parentProperty.getId();
+  }
+
+}
diff --git a/src/main/java/caosdb/server/jobs/core/CheckNoOverridesPresent.java b/src/main/java/caosdb/server/jobs/core/CheckNoOverridesPresent.java
new file mode 100644
index 00000000..d640f19f
--- /dev/null
+++ b/src/main/java/caosdb/server/jobs/core/CheckNoOverridesPresent.java
@@ -0,0 +1,36 @@
+package caosdb.server.jobs.core;
+
+import caosdb.server.entity.Message;
+import caosdb.server.entity.wrapper.Property;
+import caosdb.server.jobs.EntityJob;
+import caosdb.server.jobs.JobAnnotation;
+import caosdb.server.utils.ServerMessages;
+
+@JobAnnotation(flag="noOverrides", description="Fail if this entity has any properties with overrides.")
+public class CheckNoOverridesPresent extends EntityJob {
+
+  @Override
+  protected void run() {
+    runJobFromSchedule(this.getEntity(), CheckPropValid.class);
+    for(Property p : getEntity().getProperties()){
+      if(p.isDatatypeOverride()){
+        addMessage(p, ServerMessages.PROPERTY_WITH_DATATYPE_OVERRIDE);
+      }
+      if(p.isNameOverride()){
+        addMessage(p, ServerMessages.PROPERTY_WITH_NAME_OVERRIDE);
+      }
+      if(p.isDescOverride()){
+        addMessage(p, ServerMessages.PROPERTY_WITH_DESC_OVERRIDE);
+      }
+    }
+  }
+
+  private void addMessage(Property p, Message message) {
+    if(getMode()==Mode.MUST){
+      p.addError(message);
+    } else {
+      p.addWarning(message);
+    }
+  }
+
+}
diff --git a/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java b/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java
index 7ee0d218..ead4248f 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java
@@ -41,12 +41,12 @@ public class CheckParOblPropPresent extends EntityJob {
 
     // This test needs the valid/qualified ids of all properties.
     // Thus, run a CheckPropValid first.
-    getJobFromSchedule(getEntity(), CheckPropValid.class);
+    runJobFromSchedule(getEntity(), CheckPropValid.class);
 
     // This test needs the valid/qualified parents. If a parent is only
     // referenced by name it has to be translated into a (hopefully) unique
     // id.
-    getJobFromSchedule(getEntity(), CheckParValid.class);
+    runJobFromSchedule(getEntity(), CheckParValid.class);
 
     if (getEntity().hasParents()) {
       Database.execute(
@@ -54,7 +54,7 @@ public class CheckParOblPropPresent extends EntityJob {
     }
 
     // inherit properties
-    getJobFromSchedule(getEntity(), Inheritance.class);
+    runJobFromSchedule(getEntity(), Inheritance.class);
 
     // loop over all parents
     if (getEntity().hasParents()) {
diff --git a/src/main/java/caosdb/server/jobs/core/CheckRefidIsaParRefid.java b/src/main/java/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
index 7c36b1cd..fa2b21cc 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
@@ -114,7 +114,7 @@ public class CheckRefidIsaParRefid extends EntityJob {
       final ReferenceValue value, final ReferenceDatatype2 dt, final EntityInterface entity)
       throws Message {
 
-    getJobFromSchedule(entity, CheckRefidValid.class);
+    runJobFromSchedule(entity, CheckRefidValid.class);
     if (entity.getEntityStatus() == EntityStatus.UNQUALIFIED) {
       return;
     }
@@ -135,7 +135,7 @@ public class CheckRefidIsaParRefid extends EntityJob {
       final EntityInterface refEntity = getEntityById(child);
       for (final Parent par : refEntity.getParents()) {
         if (par.getId() == null) {
-          getJobFromSchedule(refEntity, CheckParValid.class);
+          runJobFromSchedule(refEntity, CheckParValid.class);
         }
         if (par.getId() == null) {
           getEntity()
diff --git a/src/main/java/caosdb/server/jobs/core/CheckRefidValid.java b/src/main/java/caosdb/server/jobs/core/CheckRefidValid.java
index 7dccec03..14d98962 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckRefidValid.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckRefidValid.java
@@ -149,7 +149,6 @@ public class CheckRefidValid extends EntityJob {
     if (ref.getEntity().hasEntityStatus()) {
       switch (ref.getEntity().getEntityStatus()) {
         case UNQUALIFIED:
-        case CORRUPT:
           getEntity().addError(ServerMessages.ENTITY_HAS_INVALID_REFERENCE);
           getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
           return false;
diff --git a/src/main/java/caosdb/server/jobs/core/CheckUnitPresent.java b/src/main/java/caosdb/server/jobs/core/CheckUnitPresent.java
index 0b31806f..5b923769 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckUnitPresent.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckUnitPresent.java
@@ -37,7 +37,7 @@ public class CheckUnitPresent extends EntityJob {
 
   @Override
   protected void run() {
-    getJobFromSchedule(getEntity(), Inheritance.class);
+    runJobFromSchedule(getEntity(), Inheritance.class);
 
     if (!hasUnit(getEntity())) {
       switch (getMode()) {
diff --git a/src/main/java/caosdb/server/jobs/core/Inheritance.java b/src/main/java/caosdb/server/jobs/core/Inheritance.java
index 1290f8a1..ed25c64c 100644
--- a/src/main/java/caosdb/server/jobs/core/Inheritance.java
+++ b/src/main/java/caosdb/server/jobs/core/Inheritance.java
@@ -72,7 +72,7 @@ public class Inheritance extends EntityJob {
               break parentLoop;
             }
 
-            getJobFromSchedule(getEntity(), CheckParValid.class);
+            runJobFromSchedule(getEntity(), CheckParValid.class);
 
             Database.execute(new RetrieveFullEntity(parent), getTransaction().getAccess());
 
@@ -149,7 +149,7 @@ public class Inheritance extends EntityJob {
               break propertyLoop;
             }
 
-            getJobFromSchedule(getEntity(), CheckPropValid.class);
+            runJobFromSchedule(getEntity(), CheckPropValid.class);
 
             EntityInterface validProperty = new Entity(property.getId());
             if (getEntity().hasParents()) {
diff --git a/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java b/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java
index 86730b59..773ac275 100644
--- a/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java
+++ b/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java
@@ -44,6 +44,7 @@ import caosdb.server.utils.Utils;
 import java.io.File;
 import java.io.IOException;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -299,7 +300,7 @@ public class InsertFilesInDir extends FlagJob {
   }
 
   private void loadJobs(final Entity e) {
-    final LinkedList<Job> loadJobs = Job.loadJobs(e, getContainer(), getTransaction());
+    final List<Job> loadJobs = Job.loadJobs(e, getTransaction());
     getTransaction().getSchedule().addAll(loadJobs);
   }
 
diff --git a/src/main/java/caosdb/server/jobs/core/LoadContainerFlagJobs.java b/src/main/java/caosdb/server/jobs/core/LoadContainerFlagJobs.java
index f00c44cd..9df5e601 100644
--- a/src/main/java/caosdb/server/jobs/core/LoadContainerFlagJobs.java
+++ b/src/main/java/caosdb/server/jobs/core/LoadContainerFlagJobs.java
@@ -36,7 +36,7 @@ public class LoadContainerFlagJobs extends ContainerJob {
   protected void run() {
     if (getContainer().getFlags() != null) {
       for (final Entry<String, String> flag : getContainer().getFlags().entrySet()) {
-        final Job j = Job.getJob(flag.getKey(), Mode.MUST, null, getContainer(), getTransaction());
+        final Job j = Job.getJob(flag.getKey(), Mode.MUST, null, getTransaction());
         if (j != null) {
           if (j instanceof FlagJob) {
             ((FlagJob) j).setValue(flag.getValue());
diff --git a/src/main/java/caosdb/server/jobs/core/PickUp.java b/src/main/java/caosdb/server/jobs/core/PickUp.java
index 2d44f590..8d200ac5 100644
--- a/src/main/java/caosdb/server/jobs/core/PickUp.java
+++ b/src/main/java/caosdb/server/jobs/core/PickUp.java
@@ -70,14 +70,11 @@ public class PickUp extends EntityJob {
 
   @Override
   public boolean notifyObserver(final String e, final Observable o) {
-    if (e == Entity.ENTITY_STATUS_CHANGED_EVENT && o == getEntity()) {
-      if (this.rollBack && getEntity().getEntityStatus() == EntityStatus.UNQUALIFIED
-          || getEntity().getEntityStatus() == EntityStatus.CORRUPT) {
+    if (e == Entity.ENTITY_STATUS_CHANGED_EVENT && o == getEntity() && this.rollBack && getEntity().getEntityStatus() == EntityStatus.UNQUALIFIED) {
         final File target = new File(FileSystem.getDropOffBox() + this.dropOffBoxPath);
         getEntity().getFileProperties().getFile().renameTo(target);
         this.rollBack = false;
         return false;
-      }
     }
     return true;
   }
diff --git a/src/main/java/caosdb/server/jobs/extension/SQLiteTransaction.java b/src/main/java/caosdb/server/jobs/extension/SQLiteTransaction.java
index af364e4e..17125669 100644
--- a/src/main/java/caosdb/server/jobs/extension/SQLiteTransaction.java
+++ b/src/main/java/caosdb/server/jobs/extension/SQLiteTransaction.java
@@ -22,11 +22,6 @@
  */
 package caosdb.server.jobs.extension;
 
-import caosdb.server.CaosDBException;
-import caosdb.server.entity.FileProperties;
-import caosdb.server.entity.Message;
-import caosdb.server.jobs.EntityJob;
-import caosdb.server.utils.FileUtils;
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 import java.sql.Connection;
@@ -37,8 +32,13 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.List;
 import java.util.concurrent.locks.ReentrantLock;
+import caosdb.server.CaosDBException;
+import caosdb.server.entity.FileProperties;
+import caosdb.server.entity.Message;
+import caosdb.server.jobs.EntityJob;
+import caosdb.server.utils.FileUtils;
 
 public class SQLiteTransaction extends EntityJob {
   private static HashMap<String, ReentrantLock> lockedTables = new HashMap<String, ReentrantLock>();
@@ -72,7 +72,7 @@ public class SQLiteTransaction extends EntityJob {
                 final Statement stmt = con.createStatement();
 
                 //
-                final LinkedList<Message> msgs = getEntity().getMessages("execute");
+                final List<Message> msgs = getEntity().getMessages("execute");
                 Collections.sort(msgs);
                 for (final Message m : msgs) {
                   getEntity().removeMessage(m);
diff --git a/src/main/java/caosdb/server/query/Query.java b/src/main/java/caosdb/server/query/Query.java
index 9018ee0f..c9bff5a5 100644
--- a/src/main/java/caosdb/server/query/Query.java
+++ b/src/main/java/caosdb/server/query/Query.java
@@ -173,7 +173,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
               ServerProperties.KEY_QUERY_FILTER_ENTITIES_WITHOUT_RETRIEVE_PERMISSIONS)
           .equalsIgnoreCase("FALSE");
 
-  private LinkedList<Integer> resultSet = null;
+  List<Integer> resultSet = null;
   private final String query;
   private Pattern entity = null;
   private Role role = null;
@@ -600,7 +600,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     return this.query;
   }
 
-  public LinkedList<Integer> getResultSet() {
+  public List<Integer> getResultSet() {
     return this.resultSet;
   }
 
diff --git a/src/main/java/caosdb/server/transaction/Retrieve.java b/src/main/java/caosdb/server/transaction/Retrieve.java
index 07af1e6c..3110ee97 100644
--- a/src/main/java/caosdb/server/transaction/Retrieve.java
+++ b/src/main/java/caosdb/server/transaction/Retrieve.java
@@ -53,12 +53,12 @@ public class Retrieve extends Transaction<RetrieveContainer> {
 
     // resolve names
     final ResolveNames r = new ResolveNames();
-    r.init(Mode.SHOULD, null, getContainer(), this);
+    r.init(Mode.SHOULD, null, this);
     getSchedule().add(r);
     getSchedule().runJob(r);
 
     final RemoveDuplicates job = new RemoveDuplicates();
-    job.init(Mode.MUST, null, getContainer(), this);
+    job.init(Mode.MUST, null, this);
     getSchedule().add(job);
     getSchedule().runJob(job);
 
@@ -134,7 +134,6 @@ public class Retrieve extends Transaction<RetrieveContainer> {
   @Override
   protected void transaction() throws Exception {
     // retrieve entities from mysql database
-    // retrieveFullEntities(getContainer(), getConnection());
     retrieveFullEntities(getContainer(), getAccess());
   }
 
diff --git a/src/main/java/caosdb/server/transaction/Transaction.java b/src/main/java/caosdb/server/transaction/Transaction.java
index 347e806e..396cf061 100644
--- a/src/main/java/caosdb/server/transaction/Transaction.java
+++ b/src/main/java/caosdb/server/transaction/Transaction.java
@@ -22,6 +22,9 @@
  */
 package caosdb.server.transaction;
 
+import java.util.HashMap;
+import java.util.List;
+import org.apache.shiro.subject.Subject;
 import caosdb.datetime.UTCDateTime;
 import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.Principal;
@@ -45,9 +48,7 @@ import caosdb.server.jobs.core.Mode;
 import caosdb.server.jobs.core.PickUp;
 import caosdb.server.utils.AbstractObservable;
 import caosdb.server.utils.Info;
-import java.util.HashMap;
-import java.util.LinkedList;
-import org.apache.shiro.subject.Subject;
+import caosdb.server.utils.Observer;
 
 public abstract class Transaction<C extends TransactionContainer> extends AbstractObservable
     implements TransactionInterface {
@@ -63,8 +64,13 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
   private final Schedule schedule = new Schedule();
 
   protected Transaction(final C container) {
-    acceptObserver(Info.getInstance());
+    this(container, Info.getInstance());
+  }
+  
+  protected Transaction(C container, Observer o){    
     this.container = container;
+    if(o!=null)
+    acceptObserver(o);
   }
 
   public static DatabaseMonitor getMonitor() {
@@ -78,23 +84,23 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
   protected void makeSchedule() throws Exception {
     // load flag jobs
     final Job loadContainerFlags =
-        Job.getJob("LoadContainerFlagJobs", Mode.MUST, null, getContainer(), this);
+        Job.getJob("LoadContainerFlagJobs", Mode.MUST, null, this);
     this.schedule.add(loadContainerFlags);
     this.schedule.runJob(loadContainerFlags);
 
     // all transactions are atomic
     this.schedule.add(
-        Job.getJob(Atomic.class.getSimpleName(), Mode.MUST, null, getContainer(), this));
+        Job.getJob(Atomic.class.getSimpleName(), Mode.MUST, null, this));
 
     // AccessControl
     this.schedule.add(
-        Job.getJob(AccessControl.class.getSimpleName(), Mode.MUST, null, getContainer(), this));
+        Job.getJob(AccessControl.class.getSimpleName(), Mode.MUST, null, this));
     this.schedule.add(
         Job.getJob(
-            CheckEntityACLRoles.class.getSimpleName(), Mode.MUST, null, getContainer(), this));
+            CheckEntityACLRoles.class.getSimpleName(), Mode.MUST, null,  this));
 
     for (final EntityInterface e : getContainer()) {
-      final LinkedList<Job> loadJobs = Job.loadJobs(e, getContainer(), this);
+      final List<Job> loadJobs = Job.loadJobs(e, this);
       this.schedule.addAll(loadJobs);
 
       // additionally load datatype job
@@ -108,13 +114,13 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
           }
         }
         if (!found) {
-          this.schedule.add(new CheckDatatypePresent().init(Mode.MUST, e, getContainer(), this));
+          this.schedule.add(new CheckDatatypePresent().init(Mode.MUST, e, this));
         }
       }
 
       // load pickup job if necessary
       if (e.hasFileProperties() && e.getFileProperties().isPickupable()) {
-        this.schedule.add(new PickUp().init(Mode.MUST, e, getContainer(), this));
+        this.schedule.add(new PickUp().init(Mode.MUST, e, this));
       }
     }
   }
diff --git a/src/main/java/caosdb/server/utils/EntityStatus.java b/src/main/java/caosdb/server/utils/EntityStatus.java
index f7e9f002..3e906302 100644
--- a/src/main/java/caosdb/server/utils/EntityStatus.java
+++ b/src/main/java/caosdb/server/utils/EntityStatus.java
@@ -38,7 +38,6 @@ package caosdb.server.utils;
 public enum EntityStatus {
   IGNORE,
   UNQUALIFIED,
-  CORRUPT,
   DELETED,
   NONEXISTENT,
   QUALIFIED,
diff --git a/src/main/java/caosdb/server/utils/ServerMessages.java b/src/main/java/caosdb/server/utils/ServerMessages.java
index 5d4a3c3a..d4a0f713 100644
--- a/src/main/java/caosdb/server/utils/ServerMessages.java
+++ b/src/main/java/caosdb/server/utils/ServerMessages.java
@@ -418,4 +418,12 @@ public class ServerMessages {
 
   public static final Message SERVER_SIDE_SCRIPT_MISSING_CALL =
       new Message(MessageType.Error, 400, "You must specify the `call` field.");
+
+  public static final Message ADDITIONAL_PROPERTY = new Message(MessageType.Warning,0,"This property is an additional property which has no corresponding properties among the properties of the parents.");
+
+  public static final Message PROPERTY_WITH_DATATYPE_OVERRIDE = new Message(MessageType.Warning,0,"This property overrides the datatype.");
+  
+  public static final Message PROPERTY_WITH_DESC_OVERRIDE = new Message(MessageType.Warning,0,"This property overrides the description.");
+  
+  public static final Message PROPERTY_WITH_NAME_OVERRIDE = new Message(MessageType.Warning,0,"This property overrides the name.");
 }
-- 
GitLab