diff --git a/conf/core/cache.ccf b/conf/core/cache.ccf index 821e5d7862efb21e0aa13f8410886c6c14b10a7c..b4e1f93596a6170ef04ec373dc7a8d70e51fedcc 100644 --- a/conf/core/cache.ccf +++ b/conf/core/cache.ccf @@ -28,6 +28,8 @@ jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=103 jcs.region.BACKEND_SparseEntities jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1002 +jcs.region.BACKEND_RetrieveFullVersionInfo +jcs.region.BACKEND_RetrieveFullVersionInfo.cacheattributes.MaxObjects=1006 # PAM UserSource Caching: Cached Items expire after 60 seconds if they are not requested (idle) and after 600 seconds max. # PAM_UnixUserGroups diff --git a/src/main/java/caosdb/server/database/BackendTransaction.java b/src/main/java/caosdb/server/database/BackendTransaction.java index 14e65e86bd9fe05b074c731e27b601fa4ed51f68..a8f27a135094b2cab08a73bfd2e4b3f32e791399 100644 --- a/src/main/java/caosdb/server/database/BackendTransaction.java +++ b/src/main/java/caosdb/server/database/BackendTransaction.java @@ -48,6 +48,7 @@ import caosdb.server.database.backend.implementation.MySQL.MySQLRegisterSubDomai import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAll; import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAllUncheckedFiles; import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveDatatypes; +import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveFullVersion; import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveLogRecord; import caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveParents; import caosdb.server.database.backend.implementation.MySQL.MySQLRetrievePasswordValidator; @@ -103,6 +104,7 @@ import caosdb.server.database.backend.interfaces.RegisterSubDomainImpl; import caosdb.server.database.backend.interfaces.RetrieveAllImpl; import caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesImpl; import caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl; +import caosdb.server.database.backend.interfaces.RetrieveFullVersionInfoImpl; import caosdb.server.database.backend.interfaces.RetrieveLogRecordImpl; import caosdb.server.database.backend.interfaces.RetrieveParentsImpl; import caosdb.server.database.backend.interfaces.RetrievePasswordValidatorImpl; @@ -204,6 +206,7 @@ public abstract class BackendTransaction implements Undoable { setImpl( RetrieveQueryTemplateDefinitionImpl.class, MySQLRetrieveQueryTemplateDefinition.class); setImpl(InsertEntityDatatypeImpl.class, MySQLInsertEntityDatatype.class); + setImpl(RetrieveFullVersionInfoImpl.class, MySQLRetrieveFullVersion.class); } } diff --git a/src/main/java/caosdb/server/database/CacheableBackendTransaction.java b/src/main/java/caosdb/server/database/CacheableBackendTransaction.java index fc4c9659d9a8ea80393bebad945bd6badf9580c4..0883c291c43c29093f8a5b93d41631ee21284ea8 100644 --- a/src/main/java/caosdb/server/database/CacheableBackendTransaction.java +++ b/src/main/java/caosdb/server/database/CacheableBackendTransaction.java @@ -51,7 +51,7 @@ public abstract class CacheableBackendTransaction<K, V extends Serializable> private final V execute(final K key) throws TransactionException { // get from cache if possible... if (cacheIsEnabled() && key != null) { - final V cached = getCache().get(getKey()); + final V cached = getCache().get(key); if (cached != null) { this.cached = true; return cached; @@ -64,7 +64,7 @@ public abstract class CacheableBackendTransaction<K, V extends Serializable> if (notCached != null) { if (cacheIsEnabled() && key != null) { // now cache if possible - getCache().put(getKey(), notCached); + getCache().put(key, notCached); } } return notCached; diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveFullVersion.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveFullVersion.java new file mode 100644 index 0000000000000000000000000000000000000000..db28b8c21720bda2a1621eb7a7a121ba81dbcb1c --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveFullVersion.java @@ -0,0 +1,58 @@ +package caosdb.server.database.backend.implementation.MySQL; + +import caosdb.server.database.DatabaseUtils; +import caosdb.server.database.access.Access; +import caosdb.server.database.backend.interfaces.RetrieveFullVersionInfoImpl; +import caosdb.server.database.exceptions.TransactionException; +import caosdb.server.database.proto.VersionHistoryItem; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.LinkedList; + +public class MySQLRetrieveFullVersion extends MySQLTransaction + implements RetrieveFullVersionInfoImpl { + + public static final String VERSION_HISTORY_STMT = "CALL get_version_history(?)"; + + public MySQLRetrieveFullVersion(Access access) { + super(access); + } + + @Override + public HashMap<String, VersionHistoryItem> execute(Integer entityId) { + + HashMap<String, VersionHistoryItem> result = new HashMap<>(); + try { + PreparedStatement s = prepareStatement(VERSION_HISTORY_STMT); + s.setInt(1, entityId); + ResultSet rs = s.executeQuery(); + + while (rs.next()) { + String childId = DatabaseUtils.bytes2UTF8(rs.getBytes("child")); + String parentId = DatabaseUtils.bytes2UTF8(rs.getBytes("parent")); + Long childSeconds = rs.getLong("child_seconds"); + Integer childNanos = rs.getInt("child_nanos"); + VersionHistoryItem v = result.get(childId); + if (v == null) { + v = new VersionHistoryItem(); + v.id = childId; + v.seconds = childSeconds; + v.nanos = childNanos; + result.put(childId, v); + } + + if (parentId != null) { + if (v.parents == null) { + v.parents = new LinkedList<>(); + } + v.parents.add(parentId); + } + } + } catch (SQLException | ConnectionException e) { + throw new TransactionException(e); + } + return result; + } +} diff --git a/src/main/java/caosdb/server/database/backend/interfaces/RetrieveFullVersionInfoImpl.java b/src/main/java/caosdb/server/database/backend/interfaces/RetrieveFullVersionInfoImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a6201cec61c889d79f53dd23595e0d4a501bc8de --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/interfaces/RetrieveFullVersionInfoImpl.java @@ -0,0 +1,9 @@ +package caosdb.server.database.backend.interfaces; + +import caosdb.server.database.proto.VersionHistoryItem; +import java.util.HashMap; + +public interface RetrieveFullVersionInfoImpl extends BackendTransactionImpl { + + public HashMap<String, VersionHistoryItem> execute(Integer entityId); +} 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 c732d25c8384fca1768995858223a2b3e2385c80..a2e4de6482d78053ab01c70ea3634c3f8af232a3 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java +++ b/src/main/java/caosdb/server/database/backend/transaction/DeleteSparseEntity.java @@ -42,7 +42,7 @@ public class DeleteSparseEntity extends BackendTransaction { @Override protected void execute() { - RetrieveSparseEntity.removeCached(this.entity.getIdVersion()); + RetrieveSparseEntity.removeCached(this.entity); if (entity.hasFileProperties()) { GetFileRecordByPath.removeCached(this.entity.getFileProperties().getPath()); } 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 c59f912a8c7991febbe7bfcad7ae42e23efffe0a..c8e20895711e16c40c75c89c9776e8ad55851117 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java +++ b/src/main/java/caosdb/server/database/backend/transaction/InsertSparseEntity.java @@ -30,6 +30,7 @@ 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.entity.Version; import caosdb.server.utils.Undoable; public class InsertSparseEntity extends BackendTransaction { @@ -68,6 +69,6 @@ public class InsertSparseEntity extends BackendTransaction { public void cleanUp() {} }); this.entity.setId(e.id); - this.entity.setVersion(e.version); + this.entity.setVersion(new Version(e.version)); } } 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 7ac8c1592e0cb275e60008532cdabb33919369a9..8e9c0ca3034d60d710e6e1e8a051b8e36024e625 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullEntity.java @@ -60,6 +60,8 @@ public class RetrieveFullEntity extends BackendTransaction { execute(new RetrieveParents(e)); execute(new RetrieveProperties(e)); + + execute(new RetrieveVersionInfo(e)); } } } diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullVersionHistory.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullVersionHistory.java new file mode 100644 index 0000000000000000000000000000000000000000..5c61811e5fcaf5e3c9986b11cae486d71a8da8aa --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveFullVersionHistory.java @@ -0,0 +1,56 @@ +package caosdb.server.database.backend.transaction; + +import caosdb.server.database.CacheableBackendTransaction; +import caosdb.server.database.backend.interfaces.RetrieveFullVersionInfoImpl; +import caosdb.server.database.exceptions.TransactionException; +import caosdb.server.database.proto.VersionHistoryItem; +import caosdb.server.entity.EntityInterface; +import java.util.Collection; +import java.util.HashMap; + +public abstract class RetrieveFullVersionHistory + extends CacheableBackendTransaction<Integer, HashMap<String, VersionHistoryItem>> { + + // TODO + // private static final ICacheAccess<String, Version> cache = + // Cache.getCache("BACKEND_RetrieveFullVersionInfo"); + private EntityInterface entity; + private HashMap<String, VersionHistoryItem> map; + + public static void removeCached(Integer entityId) { + // TODO + } + + public RetrieveFullVersionHistory(EntityInterface e) { + super(null); // TODO + this.entity = e; + } + + @Override + public HashMap<String, VersionHistoryItem> executeNoCache() throws TransactionException { + RetrieveFullVersionInfoImpl impl = getImplementation(RetrieveFullVersionInfoImpl.class); + return impl.execute(getKey()); + } + + @Override + protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException { + this.map = map; + } + + @Override + protected Integer getKey() { + return entity.getId(); + } + + public HashMap<String, VersionHistoryItem> getMap() { + return this.map; + } + + public EntityInterface getEntity() { + return this.entity; + } + + public Collection<VersionHistoryItem> getList() { + return this.map.values(); + } +} 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 fbb257f780b0594d7859a0fc2deefc8183be30fe..9fffcae8ade2d917562edffe5675a55f50d576d0 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveParents.java @@ -61,7 +61,7 @@ public class RetrieveParents @Override public ArrayList<VerySparseEntity> executeNoCache() throws TransactionException { final RetrieveParentsImpl t = getImplementation(RetrieveParentsImpl.class); - return t.execute(this.entity.getId(), this.entity.getVersion()); + return t.execute(this.entity.getId(), this.entity.getVersion().getId()); } @Override 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 c0bcb8e8563fe276f19a668e8d1248c0dc287d23..822f57fd49e54d7517578592acf09100924fe81b 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java @@ -63,7 +63,7 @@ public class RetrieveProperties @Override public ArrayList<ProtoProperty> executeNoCache() throws TransactionException { final RetrievePropertiesImpl t = getImplementation(RetrievePropertiesImpl.class); - return t.execute(this.entity.getId(), this.entity.getVersion()); + return t.execute(this.entity.getId(), this.entity.getVersion().getId()); } @Override diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java index b3dfb14695b7a2449460d4c024448f0e30e1bad3..0c96c72cb0be41aaf368c22009526914994bc8ec 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveQueryTemplateDefinition.java @@ -40,6 +40,6 @@ public class RetrieveQueryTemplateDefinition extends BackendTransaction { final RetrieveQueryTemplateDefinitionImpl t = getImplementation(RetrieveQueryTemplateDefinitionImpl.class); this.entity.setQueryTemplateDefinition( - t.retrieve(this.entity.getId(), this.entity.getVersion())); + t.retrieve(this.entity.getId(), this.entity.getVersion().getId())); } } 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 db6b38bd197d8069e5d33804a7aaf801d0c9929b..6ad58df839e2f03101e2265c32f894992809dcee 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveSparseEntity.java @@ -42,13 +42,14 @@ public class RetrieveSparseEntity extends CacheableBackendTransaction<String, Sp Cache.getCache("BACKEND_SparseEntities"); /** - * To be called by {@link UpdateSparseEntity} and {@link DeleteEntity} on execution. + * To be called by {@link UpdateSparseEntity} and {@link DeleteSparseEntity} on execution. * - * @param idVersion + * @param entity */ - public static void removeCached(final String idVersion) { - if (idVersion != null && cache != null) { - cache.remove(idVersion); + public static void removeCached(final EntityInterface entity) { + if (entity != null && cache != null) { + cache.remove(entity.getId().toString()); + cache.remove(entity.getIdVersion()); } } @@ -64,7 +65,7 @@ public class RetrieveSparseEntity extends CacheableBackendTransaction<String, Sp @Override public SparseEntity executeNoCache() throws TransactionException { final RetrieveSparseEntityImpl t = getImplementation(RetrieveSparseEntityImpl.class); - final SparseEntity ret = t.execute(getEntity().getId(), getEntity().getVersion()); + final SparseEntity ret = t.execute(getEntity().getId(), getEntity().getVersion().getId()); if (ret == null) { this.entity.setEntityStatus(EntityStatus.NONEXISTENT); } @@ -79,6 +80,12 @@ public class RetrieveSparseEntity extends CacheableBackendTransaction<String, Sp @Override protected String getKey() { + if ("HEAD".equalsIgnoreCase(entity.getVersion().getId())) { + return this.entity.getId().toString(); + } else if (entity.hasVersion() + && entity.getVersion().getId().toUpperCase().startsWith("HEAD")) { + return null; + } return this.entity.getIdVersion(); } diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveVersionInfo.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveVersionInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..139e797968efbe3506a6945ef4ccc485b5a102ca --- /dev/null +++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveVersionInfo.java @@ -0,0 +1,60 @@ +package caosdb.server.database.backend.transaction; + +import caosdb.datetime.UTCDateTime; +import caosdb.server.database.exceptions.TransactionException; +import caosdb.server.database.proto.VersionHistoryItem; +import caosdb.server.entity.EntityInterface; +import caosdb.server.entity.Version; +import java.util.HashMap; +import java.util.LinkedList; + +public class RetrieveVersionInfo extends RetrieveFullVersionHistory { + + public RetrieveVersionInfo(EntityInterface e) { + super(e); + } + + @Override + protected void process(HashMap<String, VersionHistoryItem> map) throws TransactionException { + super.process(map); + if (!map.isEmpty()) getVersion(); + } + + public Version getVersion() { + Version v = getEntity().getVersion(); + VersionHistoryItem i = getMap().get(v.getId()); + if (i != null) v.setDate(UTCDateTime.UTCSeconds(i.seconds, i.nanos)); + + v.setPredecessors(getPredecessors(v.getId())); + v.setSuccessors(getSuccessors(v.getId())); + return v; + } + + private LinkedList<Version> getSuccessors(String id) { + LinkedList<Version> result = new LinkedList<>(); + + outer: + for (VersionHistoryItem i : getList()) { + if (i.parents != null) + for (String p : i.parents) { + if (id.equals(p)) { + Version successor = new Version(i.id, i.seconds, i.nanos); + result.add(successor); + continue outer; + } + } + } + return result; + } + + private LinkedList<Version> getPredecessors(String id) { + LinkedList<Version> result = new LinkedList<>(); + if (getMap().containsKey(id) && getMap().get(id).parents != null) + for (String p : getMap().get(id).parents) { + VersionHistoryItem i = getMap().get(p); + Version predecessor = new Version(i.id, i.seconds, i.nanos); + result.add(predecessor); + } + return result; + } +} diff --git a/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java b/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java index 6378e8bbbbd8aee87382d226df0691d004e641aa..a7c9ba43f32b1ef97a6a09544041b39a2cd5c71a 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java +++ b/src/main/java/caosdb/server/database/backend/transaction/UpdateEntity.java @@ -53,6 +53,8 @@ public class UpdateEntity extends BackendTransaction { execute(new InsertEntityValue(e)); execute(new InsertEntityProperties(e)); + + execute(new RetrieveVersionInfo(e)); } } } diff --git a/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java b/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java index c3149a765163e0ac577dd6e0a2415330cce5b58d..309ff9cbde0131f4b90cc89301a2338a8b92971f 100644 --- a/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java +++ b/src/main/java/caosdb/server/database/backend/transaction/UpdateSparseEntity.java @@ -29,6 +29,7 @@ import caosdb.server.database.backend.interfaces.UpdateSparseEntityImpl; import caosdb.server.database.exceptions.TransactionException; import caosdb.server.database.proto.SparseEntity; import caosdb.server.entity.EntityInterface; +import caosdb.server.entity.Version; public class UpdateSparseEntity extends BackendTransaction { @@ -40,7 +41,7 @@ public class UpdateSparseEntity extends BackendTransaction { @Override public void execute() throws TransactionException { - RetrieveSparseEntity.removeCached(this.entity.getIdVersion()); + RetrieveSparseEntity.removeCached(this.entity); if (entity.hasFileProperties()) { GetFileRecordByPath.removeCached(this.entity.getFileProperties().getPath()); } @@ -51,6 +52,6 @@ public class UpdateSparseEntity extends BackendTransaction { t.execute(spe); - this.entity.setVersion(spe.version); + this.entity.setVersion(new Version(spe.version)); } } diff --git a/src/main/java/caosdb/server/database/proto/VersionHistoryItem.java b/src/main/java/caosdb/server/database/proto/VersionHistoryItem.java new file mode 100644 index 0000000000000000000000000000000000000000..e671950f39f40c0b93069d031f636ad964560508 --- /dev/null +++ b/src/main/java/caosdb/server/database/proto/VersionHistoryItem.java @@ -0,0 +1,13 @@ +package caosdb.server.database.proto; + +import java.io.Serializable; +import java.util.LinkedList; + +public class VersionHistoryItem implements Serializable { + + private static final long serialVersionUID = 7855704308135158698L; + public String id = null; + public LinkedList<String> parents = null; + public Long seconds = null; + public Integer nanos = null; +} diff --git a/src/main/java/caosdb/server/entity/DeleteEntity.java b/src/main/java/caosdb/server/entity/DeleteEntity.java index f31fbb47a9e25f2d00dfa5f2874925bd504f23fe..83b7fdcf35c60358b007d1af42930bcc5c310e75 100644 --- a/src/main/java/caosdb/server/entity/DeleteEntity.java +++ b/src/main/java/caosdb/server/entity/DeleteEntity.java @@ -30,6 +30,6 @@ public class DeleteEntity extends Entity { public DeleteEntity(int id, String version) { super(id); - setVersion(version); + setVersion(new Version(version)); } } diff --git a/src/main/java/caosdb/server/entity/Entity.java b/src/main/java/caosdb/server/entity/Entity.java index c1579fb005b4a166b9347e434b8b740b221e1d56..9bd0b6ddfed6fbc42896bb19b8a15f411414a884 100644 --- a/src/main/java/caosdb/server/entity/Entity.java +++ b/src/main/java/caosdb/server/entity/Entity.java @@ -795,7 +795,9 @@ public class Entity extends AbstractObservable implements EntityInterface { final CollectionValue vals = new CollectionValue(); int pidx = 0; for (final Element pe : element.getChildren()) { - if (pe.getName().equalsIgnoreCase("EmptyString")) { + if (pe.getName().equalsIgnoreCase("Version")) { + // TODO + } else if (pe.getName().equalsIgnoreCase("EmptyString")) { // special case: empty string which cannot be distinguished from null // values otherwise. setValue(new GenericValue("")); @@ -1021,8 +1023,7 @@ public class Entity extends AbstractObservable implements EntityInterface { } private boolean datatypeOverride = false; - private String version = null; - private UTCDateTime versionDate = null; + private Version version = new Version(); @Override public EntityInterface setDatatypeOverride(final boolean b) { @@ -1067,10 +1068,11 @@ public class Entity extends AbstractObservable implements EntityInterface { setId(spe.id); this.setRole(spe.role); setEntityACL(spe.acl); - this.version = spe.version; + UTCDateTime versionDate = null; if (spe.versionSeconds != null) { - this.versionDate = UTCDateTime.UTCSeconds(spe.versionSeconds, spe.versionNanos); + versionDate = UTCDateTime.UTCSeconds(spe.versionSeconds, spe.versionNanos); } + this.version = new Version(spe.version, versionDate); if (!isNameOverride()) { setName(spe.name); @@ -1121,46 +1123,26 @@ public class Entity extends AbstractObservable implements EntityInterface { } @Override - public UTCDateTime getVersionDate() { - return this.versionDate; - } - - @Override - public String getVersion() { + public Version getVersion() { return this.version; } @Override public boolean hasVersion() { - return this.version != null; - } - - @Override - public boolean hasVersionDate() { - return this.versionDate != null; + return this.version.getId() != null; } @Override - public void setVersion(String version) { + public void setVersion(Version version) { this.version = version; } - @Override - public void setVersionDate(Long versionSeconds, Integer versionNanos) { - this.versionDate = UTCDateTime.UTCSeconds(versionSeconds, versionNanos); - } - - @Override - public void setVersionDate(UTCDateTime versionDate) { - this.versionDate = versionDate; - } - @Override public String getIdVersion() { if (!this.hasId()) { return null; } else if (this.hasVersion()) { - return new StringBuilder().append(getId()).append(getVersion()).toString(); + return new StringBuilder().append(getId()).append(getVersion().getId()).toString(); } return getId().toString(); } diff --git a/src/main/java/caosdb/server/entity/EntityInterface.java b/src/main/java/caosdb/server/entity/EntityInterface.java index a39a43d65c478c082bb215c0b8565c4890b81b6e..657727055b4289046a4ee893af0fa424a750a261 100644 --- a/src/main/java/caosdb/server/entity/EntityInterface.java +++ b/src/main/java/caosdb/server/entity/EntityInterface.java @@ -22,7 +22,6 @@ */ package caosdb.server.entity; -import caosdb.datetime.UTCDateTime; import caosdb.server.database.proto.SparseEntity; import caosdb.server.database.proto.VerySparseEntity; import caosdb.server.datatype.AbstractDatatype; @@ -186,17 +185,9 @@ public interface EntityInterface public abstract void setQueryTemplateDefinition(String query); - public abstract UTCDateTime getVersionDate(); - - public abstract String getVersion(); + public abstract Version getVersion(); public abstract boolean hasVersion(); - public abstract boolean hasVersionDate(); - - public abstract void setVersionDate(Long versionSeconds, Integer versionNanos); - - public abstract void setVersion(String version); - - public abstract void setVersionDate(UTCDateTime versionDate); + public abstract void setVersion(Version version); } diff --git a/src/main/java/caosdb/server/entity/RetrieveEntity.java b/src/main/java/caosdb/server/entity/RetrieveEntity.java index 64b99a2f66983355802b4db20300874e548e6924..57d7ae48193ff81d7be2f4dfba97166d8cd05ff7 100644 --- a/src/main/java/caosdb/server/entity/RetrieveEntity.java +++ b/src/main/java/caosdb/server/entity/RetrieveEntity.java @@ -34,11 +34,11 @@ public class RetrieveEntity extends Entity { public RetrieveEntity(int id, String version) { super(id); - this.setVersion(version); + this.setVersion(new Version(version)); } public RetrieveEntity(String name, String version) { super(name); - this.setVersion(version); + this.setVersion(new Version(version)); } } diff --git a/src/main/java/caosdb/server/entity/Version.java b/src/main/java/caosdb/server/entity/Version.java new file mode 100644 index 0000000000000000000000000000000000000000..43cdcd54ecb1dde9143f18033b9eb42575a67a0f --- /dev/null +++ b/src/main/java/caosdb/server/entity/Version.java @@ -0,0 +1,59 @@ +package caosdb.server.entity; + +import caosdb.datetime.UTCDateTime; +import java.util.LinkedList; + +public class Version { + + private String id = null; + private LinkedList<Version> predecessors = null; + private LinkedList<Version> successors = null; + private UTCDateTime date = null; + + public Version(String id, long seconds, int nanos) { + this(id, UTCDateTime.UTCSeconds(seconds, nanos)); + } + + public Version(String id, UTCDateTime date) { + this.id = id; + this.date = date; + } + + public Version(String id) { + this(id, null); + } + + public Version() {} + + public UTCDateTime getDate() { + return date; + } + + public void setDate(UTCDateTime date) { + this.date = date; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public LinkedList<Version> getSuccessors() { + return successors; + } + + public void setSuccessors(LinkedList<Version> successors) { + this.successors = successors; + } + + public LinkedList<Version> getPredecessors() { + return predecessors; + } + + public void setPredecessors(LinkedList<Version> predecessors) { + this.predecessors = predecessors; + } +} diff --git a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java index 85719dc62041a63930ab0ca711f870397fd2ce5d..71e1ad21a67f29bedbfd59fcd5bf645237023670 100644 --- a/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java +++ b/src/main/java/caosdb/server/entity/wrapper/EntityWrapper.java @@ -22,7 +22,6 @@ */ package caosdb.server.entity.wrapper; -import caosdb.datetime.UTCDateTime; import caosdb.server.database.proto.SparseEntity; import caosdb.server.database.proto.VerySparseEntity; import caosdb.server.datatype.AbstractDatatype; @@ -32,6 +31,7 @@ import caosdb.server.entity.FileProperties; import caosdb.server.entity.Message; import caosdb.server.entity.Role; import caosdb.server.entity.StatementStatus; +import caosdb.server.entity.Version; import caosdb.server.entity.container.ParentContainer; import caosdb.server.entity.container.PropertyContainer; import caosdb.server.entity.xml.ToElementStrategy; @@ -554,12 +554,7 @@ public class EntityWrapper implements EntityInterface { } @Override - public UTCDateTime getVersionDate() { - return this.entity.getVersionDate(); - } - - @Override - public String getVersion() { + public Version getVersion() { return this.entity.getVersion(); } @@ -569,25 +564,10 @@ public class EntityWrapper implements EntityInterface { } @Override - public boolean hasVersionDate() { - return this.entity.hasVersionDate(); - } - - @Override - public void setVersion(String version) { + public void setVersion(Version version) { this.entity.setVersion(version); } - @Override - public void setVersionDate(Long versionSeconds, Integer versionNanos) { - this.entity.setVersionDate(versionSeconds, versionNanos); - } - - @Override - public void setVersionDate(UTCDateTime versionDate) { - this.entity.setVersionDate(versionDate); - } - @Override public String getIdVersion() { return this.entity.getIdVersion(); diff --git a/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java b/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java index 0697c076d91b5bb9519341020f9b2698326ef6cd..bfa5e8854765f1271981f5a28b60c1aa3450b8f8 100644 --- a/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java +++ b/src/main/java/caosdb/server/entity/xml/EntityToElementStrategy.java @@ -27,7 +27,6 @@ import caosdb.server.entity.Message; import caosdb.server.utils.EntityStatus; import caosdb.server.utils.TransactionLogMessage; import java.util.Comparator; -import java.util.TimeZone; import org.apache.shiro.SecurityUtils; import org.jdom2.Content; import org.jdom2.Content.CType; @@ -52,11 +51,8 @@ public class EntityToElementStrategy implements ToElementStrategy { element.setAttribute("id", Integer.toString(entity.getId())); } if (setFieldStrategy.isToBeSet("version") && entity.hasVersion()) { - element.setAttribute("version", entity.getVersion()); - } - if (setFieldStrategy.isToBeSet("versionDate") && entity.hasVersionDate()) { - element.setAttribute( - "versionDate", entity.getVersionDate().toDateTimeString(TimeZone.getDefault())); + Element v = new VersionXMLConverter().toElement(entity.getVersion()); + element.addContent(v); } if (setFieldStrategy.isToBeSet("cuid") && entity.hasCuid()) { element.setAttribute("cuid", entity.getCuid()); diff --git a/src/main/java/caosdb/server/entity/xml/VersionXMLConverter.java b/src/main/java/caosdb/server/entity/xml/VersionXMLConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..06762c38a8c6503032b14e33f6ee5be702c91ab5 --- /dev/null +++ b/src/main/java/caosdb/server/entity/xml/VersionXMLConverter.java @@ -0,0 +1,32 @@ +package caosdb.server.entity.xml; + +import caosdb.server.entity.Version; +import java.util.TimeZone; +import org.jdom2.Element; + +class VersionXMLConverter { + public Element toElement(Version version) { + Element result = new Element("Version"); + result.setAttribute("id", version.getId()); + if (version.getDate() != null) { + result.setAttribute("date", version.getDate().toDateTimeString(TimeZone.getDefault())); + } + if (version.getPredecessors() != null) { + for (Version p : version.getPredecessors()) { + Element predecessor = new Element("Predecessor"); + predecessor.setAttribute("id", p.getId()); + predecessor.setAttribute("date", p.getDate().toDateTimeString(TimeZone.getDefault())); + result.addContent(predecessor); + } + } + if (version.getSuccessors() != null) { + for (Version s : version.getSuccessors()) { + Element successor = new Element("Successor"); + successor.setAttribute("id", s.getId()); + successor.setAttribute("date", s.getDate().toDateTimeString(TimeZone.getDefault())); + result.addContent(successor); + } + } + return result; + } +} diff --git a/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java b/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java index d647b64d2d56a8cc073467326d9ecb868b6c7d0f..280b413235198b2e778b7d0bf7d1c99ba2fef54d 100644 --- a/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java +++ b/src/main/java/caosdb/server/jobs/extension/AWIBoxLoanModel.java @@ -7,7 +7,6 @@ import caosdb.server.entity.EntityInterface; import caosdb.server.entity.Role; import caosdb.server.entity.wrapper.Property; import caosdb.server.jobs.ContainerJob; -import caosdb.server.utils.Utils; import java.util.Objects; public abstract class AWIBoxLoanModel extends ContainerJob { diff --git a/src/main/java/caosdb/server/transaction/Insert.java b/src/main/java/caosdb/server/transaction/Insert.java index 18eb5f2ca27fe7c1ddc1ca7bd08a7092baf4e4ff..c1d53f3051eb65efd9d658179e514e13863c313b 100644 --- a/src/main/java/caosdb/server/transaction/Insert.java +++ b/src/main/java/caosdb/server/transaction/Insert.java @@ -26,6 +26,7 @@ import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.InsertEntity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.FileProperties; +import caosdb.server.entity.Version; import caosdb.server.entity.container.InsertContainer; import caosdb.server.entity.container.TransactionContainer; import caosdb.server.permissions.EntityACL; @@ -102,10 +103,11 @@ public class Insert extends WriteTransaction<InsertContainer> { public void insert(final TransactionContainer container, final Access access) throws Exception { if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) { + execute(new InsertEntity(container), access); for (EntityInterface e : container) { - e.setVersionDate(this.getTimestamp()); + // TODO move to InsertEntity transaction + e.setVersion(new Version(e.getVersion().getId(), this.getTimestamp())); } - execute(new InsertEntity(container), access); } } diff --git a/src/main/java/caosdb/server/transaction/Update.java b/src/main/java/caosdb/server/transaction/Update.java index 6a48aaac361b510b1103d3a286991b45bc40d694..b9e6e8de19f137014d10d1c6516c07ca2acabf8e 100644 --- a/src/main/java/caosdb/server/transaction/Update.java +++ b/src/main/java/caosdb/server/transaction/Update.java @@ -170,9 +170,6 @@ public class Update extends WriteTransaction<UpdateContainer> { private void update(final TransactionContainer container, final Access access) throws Exception { if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) { - for (EntityInterface e : container) { - e.setVersionDate(getTimestamp()); - } execute(new UpdateEntity(container), access); } }