diff --git a/src/main/java/org/caosdb/server/CaosDBServer.java b/src/main/java/org/caosdb/server/CaosDBServer.java index 2a115c5cfa06ed0e3db85847c27fb4c8424eadaf..e843645cd5570e528f37f601c87e9f48b6299c65 100644 --- a/src/main/java/org/caosdb/server/CaosDBServer.java +++ b/src/main/java/org/caosdb/server/CaosDBServer.java @@ -129,6 +129,7 @@ public class CaosDBServer extends Application { private static boolean NO_TLS = false; public static final String REQUEST_TIME_LOGGER = "REQUEST_TIME_LOGGER"; public static final String REQUEST_ERRORS_LOGGER = "REQUEST_ERRORS_LOGGER"; + private static boolean USE_CACHE = false; private static Scheduler SCHEDULER; public static String getServerProperty(final String key) { @@ -196,6 +197,8 @@ public class CaosDBServer extends Application { public static void initServerProperties() throws IOException { SERVER_PROPERTIES = ServerProperties.initServerProperties(); + USE_CACHE = + !Boolean.parseBoolean(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_DISABLE)); } /** @@ -886,6 +889,10 @@ public class CaosDBServer extends Application { throws SchedulerException { SCHEDULER.scheduleJob(job, trigger); } + + public static boolean useCache() { + return USE_CACHE; + } } class CaosDBComponent extends Component { diff --git a/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java b/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java index 1613b8be8194425ab14e5e68b9215a0ba92be8d3..f294e4bb029b7e03d2864ae832b3044685536404 100644 --- a/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java +++ b/src/main/java/org/caosdb/server/caching/JCSCacheHelper.java @@ -62,8 +62,7 @@ public class JCSCacheHelper implements CacheHelper { } public static void init() { - final boolean disabled = - Boolean.parseBoolean(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_DISABLE)); + final boolean disabled = !CaosDBServer.useCache(); init(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_CONF_LOC), disabled); } diff --git a/src/main/java/org/caosdb/server/database/access/AbstractAccess.java b/src/main/java/org/caosdb/server/database/access/AbstractAccess.java index 1d30bd3fee7187b9c44378e5b94c1c6d97287f00..680b18275a27d9d55ffecffa8b66e65eb87237bb 100644 --- a/src/main/java/org/caosdb/server/database/access/AbstractAccess.java +++ b/src/main/java/org/caosdb/server/database/access/AbstractAccess.java @@ -1,5 +1,4 @@ /* - * ** header v3.0 * This file is a part of the CaosDB Project. * * Copyright (C) 2018 Research Group Biomedical Physics, @@ -17,8 +16,6 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header */ package org.caosdb.server.database.access; @@ -26,11 +23,12 @@ import java.util.HashMap; import org.caosdb.server.database.misc.DBHelper; import org.caosdb.server.database.misc.RollBackHandler; import org.caosdb.server.transaction.TransactionInterface; +import org.caosdb.server.utils.UseCacheResourceDelegate; -public abstract class AbstractAccess<T extends TransactionInterface> implements Access { +public abstract class AbstractAccess<T extends TransactionInterface> + extends UseCacheResourceDelegate implements Access { private HashMap<String, DBHelper> helpers = new HashMap<String, DBHelper>(); - private Boolean useCache = true; private final T transaction; private boolean released = false; @@ -73,22 +71,6 @@ public abstract class AbstractAccess<T extends TransactionInterface> implements } } - @Override - public void setUseCache(final Boolean useCache) { - this.useCache = useCache; - } - /** - * Whether the transaction allows to use the query cache or other caches. This is controlled by - * the "cache" flag. - * - * @see {@link NoCache} - * @return true if caching is encouraged. - */ - @Override - public boolean useCache() { - return this.useCache; - } - @Override public void commit() throws Exception { synchronized (this.helpers) { diff --git a/src/main/java/org/caosdb/server/database/access/Access.java b/src/main/java/org/caosdb/server/database/access/Access.java index 228e8e004aea7454a287bccd898794c2bb4f1b9c..a98afa2737656a9f5bdd0e3d720354b742030584 100644 --- a/src/main/java/org/caosdb/server/database/access/Access.java +++ b/src/main/java/org/caosdb/server/database/access/Access.java @@ -1,5 +1,4 @@ /* - * ** header v3.0 * This file is a part of the CaosDB Project. * * Copyright (C) 2018 Research Group Biomedical Physics, @@ -17,14 +16,13 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header */ package org.caosdb.server.database.access; import org.caosdb.server.database.misc.DBHelper; +import org.caosdb.server.utils.UseCacheResource; -public interface Access { +public interface Access extends UseCacheResource { public abstract void setHelper(String name, DBHelper helper); @@ -33,8 +31,4 @@ public interface Access { public abstract void release(); public abstract void commit() throws Exception; - - public abstract void setUseCache(Boolean useCache); - - public boolean useCache(); } diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java index fabe5233d48cbda8b57fe4af10797aa0bd8ad8c5..bb33b4df1adcf38466bcaeaa72923ddc7fe30b65 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetDependentEntities.java @@ -51,7 +51,7 @@ public class MySQLGetDependentEntities extends MySQLTransaction try { final List<EntityID> ret = new LinkedList<>(); while (rs.next()) { - ret.add(new EntityID(rs.getInt(1))); + ret.add(new EntityID(rs.getString(1))); } return ret; } finally { diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java index 611535a946eaaef79c898911b5b5cd67278ca7b0..4837fc591df2ba6a61f28b6608b469ab0fb0f5cb 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetIDByName.java @@ -65,7 +65,7 @@ public class MySQLGetIDByName extends MySQLTransaction implements GetIDByNameImp try (ResultSet rs = stmt.executeQuery()) { final List<EntityID> ret = new LinkedList<>(); while (rs.next()) { - ret.add(new EntityID(rs.getInt("id"))); + ret.add(new EntityID(rs.getString("id"))); } return ret; diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java index dd6c87760c18702b4e69dd5ec46996f0dbd15a63..2081b026903026a0aa704290d6fa16d8d5e64800 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetUpdateableChecksums.java @@ -46,7 +46,7 @@ public class MySQLGetUpdateableChecksums extends MySQLTransaction final PreparedStatement stmt = prepareStatement(this.GET_UPDATEABLE_CHECKSUMS); final ResultSet rs = stmt.executeQuery(); if (rs.next()) { - return new EntityID(rs.getInt(1)); + return new EntityID(rs.getString(1)); } else { return null; } diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java index 8d70660486b571f7f81e125df200b2be0fce89e0..2fb7c95f766748571009177fa38bf99405637101 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java @@ -224,7 +224,7 @@ public class MySQLInsertEntityProperties extends MySQLTransaction try (final ResultSet rs = stmt.executeQuery()) { final Deque<EntityID> ret = new ArrayDeque<>(); while (rs.next()) { - ret.add(new EntityID(rs.getInt(1))); + ret.add(new EntityID(rs.getString(1))); } return ret; } diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java index 83ebffe679e6625da720fd2933a5d8defb7264c3..3b68c45d0ff60473ae837f3c9ebc17ae82e68c2d 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLListUsers.java @@ -53,8 +53,8 @@ public class MySQLListUsers extends MySQLTransaction implements ListUsersImpl { user.name = rs.getString("name"); user.realm = rs.getString("realm"); user.email = rs.getString("email"); - user.entity = rs.getInt("entity"); - if (user.entity == 0) { + user.entity = rs.getString("entity"); + if (user.entity.isBlank() || user.entity.equals("0")) { user.entity = null; } user.status = UserStatus.valueOf(rs.getString("status")); diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java index 9a2ea81629853e3baf9de7757e1abe6c8f01fe28..55b8f194ea0be90b5a77fa0c50930c836c48b3f7 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveAll.java @@ -75,7 +75,7 @@ public class MySQLRetrieveAll extends MySQLTransaction implements RetrieveAllImp final String acl = DatabaseUtils.bytes2UTF8(rs.getBytes("ACL")); if (EntityACL.deserialize(acl) .isPermitted(SecurityUtils.getSubject(), EntityPermission.RETRIEVE_ENTITY)) { - ret.add(new EntityID(rs.getInt("ID"))); + ret.add(new EntityID(rs.getString("ID"))); } } return ret; diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java index 18cf01f159d10aac470bdeb919df185b09d6c7fa..1bc9a89dd119a66eecc33799849977019422fde1 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveCurrentMaxId.java @@ -14,7 +14,8 @@ public class MySQLRetrieveCurrentMaxId extends MySQLTransaction super(access); } - public static final String STMT = "SELECT max(entity_id) AS max_id FROM transaction_log"; + public static final String STMT = + "SELECT max(CAST(entity_id AS UNSIGNED INT)) AS max_id FROM transaction_log WHERE transaction='Insert'"; @Override public Integer execute() { diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java index 546b5675cb5e1b0d51398230155f61b1e11f2ebb..30a0f530bb77458f95d21278f0474e2cdc89a457 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java @@ -22,6 +22,7 @@ */ package org.caosdb.server.database.backend.implementation.MySQL; +import com.mysql.cj.jdbc.exceptions.MysqlDataTruncation; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -92,6 +93,8 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev } return properties; + } catch (MysqlDataTruncation e) { + throw e; } } diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java index 40f036f1d63753c0be9e6153f741db7d4f9d04ad..b149fae264549f88c21d996f854662401d744beb 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveUser.java @@ -66,7 +66,7 @@ public class MySQLRetrieveUser extends MySQLTransaction implements RetrieveUserI if (rs.getString("entity") == null) { ret.entity = null; } else { - ret.entity = rs.getInt("entity"); + ret.entity = rs.getString("entity"); } } } finally { diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java index bd368698956163a8473ead7507aac0ba2b83d552..43f71e386fcad42b4a3e39e14eeedf7cb924a535 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLUpdateUser.java @@ -49,7 +49,7 @@ public class MySQLUpdateUser extends MySQLTransaction implements UpdateUserImpl stmt.setString(3, user.status.toString()); stmt.setString(4, user.email); if (user.entity != null) { - stmt.setInt(5, user.entity); + stmt.setString(5, user.entity); } else { stmt.setNull(5, Types.INTEGER); } @@ -57,7 +57,7 @@ public class MySQLUpdateUser extends MySQLTransaction implements UpdateUserImpl stmt.setString(6, user.status.toString()); stmt.setString(7, user.email); if (user.entity != null) { - stmt.setInt(8, user.entity); + stmt.setString(8, user.entity); } else { stmt.setNull(8, Types.INTEGER); } diff --git a/src/main/java/org/caosdb/server/database/proto/ProtoUser.java b/src/main/java/org/caosdb/server/database/proto/ProtoUser.java index 643f4250216c7829c8218113a8842ff139b313ec..8b2d97a85044881d61fa6ea795443ae13f3cabc2 100644 --- a/src/main/java/org/caosdb/server/database/proto/ProtoUser.java +++ b/src/main/java/org/caosdb/server/database/proto/ProtoUser.java @@ -36,7 +36,7 @@ public class ProtoUser implements Serializable { public UserStatus status = null; public String name = null; public String email = null; - public Integer entity = null; + public String entity = null; public String realm = null; public HashSet<String> roles = null; } diff --git a/src/main/java/org/caosdb/server/datatype/ReferenceValue.java b/src/main/java/org/caosdb/server/datatype/ReferenceValue.java index a24e2ddfda7faf333fd7d7f64420d4a6c7fdc290..20620a4327ddbc46fb5f5f29abad4ef93e4fee88 100644 --- a/src/main/java/org/caosdb/server/datatype/ReferenceValue.java +++ b/src/main/java/org/caosdb/server/datatype/ReferenceValue.java @@ -66,7 +66,7 @@ public class ReferenceValue implements SingleValue { throw ServerMessages.DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES; } else { try { - return new ReferenceValue(Integer.parseInt(reference.toString())); + return new ReferenceValue(reference.toString()); } catch (final NumberFormatException e) { return new ReferenceValue(reference.toString()); } @@ -81,9 +81,9 @@ public class ReferenceValue implements SingleValue { public static ReferenceValue parseIdVersion(final String str) { final String[] split = str.split("@", 2); if (split.length == 2) { - return new ReferenceValue(Integer.parseInt(split[0]), split[1]); + return new ReferenceValue(split[0], split[1]); } else { - return new ReferenceValue(Integer.parseInt(str)); + return new ReferenceValue(str); } } @@ -150,14 +150,13 @@ public class ReferenceValue implements SingleValue { /** If the reference is given by name, versioning is not possible (at the moment). */ public ReferenceValue(final String name) { this.name = name; + this.id = new EntityID(name); } - public ReferenceValue(final int id, final String name) { - this(new EntityID(id), name); - } - - public ReferenceValue(final int id) { - this(new EntityID(id)); + public ReferenceValue(String name, String version) { + this.name = name; + this.id = new EntityID(name); + this.version = version; } public final EntityInterface getEntity() { diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java index 19934568c93a421af5dab35635686de61052bc93..9c75e91d50e84bd06356c7f85eb1a1018232638b 100644 --- a/src/main/java/org/caosdb/server/entity/Entity.java +++ b/src/main/java/org/caosdb/server/entity/Entity.java @@ -73,7 +73,7 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa private String name = null; private String description = null; private Value value = null; - private final EntityID domain = new EntityID(0); + private final EntityID domain = new EntityID("0"); private final EntityID id = new EntityID(); private AbstractDatatype datatype = null; private final ParentContainer parents = new ParentContainer(this); diff --git a/src/main/java/org/caosdb/server/entity/EntityID.java b/src/main/java/org/caosdb/server/entity/EntityID.java index f1a13769140e856d62e197108c9cc8e1c298de11..469b2e50ef124061eb400878d59b98de1ebbe840 100644 --- a/src/main/java/org/caosdb/server/entity/EntityID.java +++ b/src/main/java/org/caosdb/server/entity/EntityID.java @@ -22,12 +22,8 @@ public class EntityID implements Serializable { public EntityID() {} - public EntityID(final int id) { - this(Integer.toString(id)); - } - public EntityID(final String id) { - this.id = id.toString(); + this.id = id; } public void setId(final String id) { diff --git a/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java b/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java index 6ab18d156225fc683e73128c1d92381cfe87892d..c6010eda5e1b8b590fae2afbf5f5964021ef8a99 100644 --- a/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java +++ b/src/main/java/org/caosdb/server/entity/EntityIdRegistry.java @@ -1,51 +1,46 @@ package org.caosdb.server.entity; -import org.caosdb.server.database.backend.transaction.RetrieveCurrentMaxId; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.transaction.Transaction; -/** - * Aufgaben: - * - * <ul> - * <li>Ids generieren - * <ul> - * <li>Pattern (positive Integer, uuid) - * </ul> - * <li> - * </ul> - * - * @author tf - */ public class EntityIdRegistry { - private boolean isInit; - private Integer currentMaxId; - private Transaction<?> transaction; + private EntityIdRegistryStrategy strategy; public EntityIdRegistry(Transaction<?> t) { - this.transaction = t; - this.isInit = false; + // this("org.caosdb.server.entity.StringIds", t); + this("org.caosdb.server.entity.LegacyIds", t); } - public void init() { - isInit = true; - initCurrentMaxId(); + public EntityIdRegistry(EntityIdRegistryStrategy strategy) { + this.strategy = strategy; } - private void initCurrentMaxId() { - this.currentMaxId = - Math.max( - 101, - transaction - .execute(new RetrieveCurrentMaxId(), transaction.getAccess()) - .getCurrentMaxId()); + public String generate() { + return this.strategy.generate(); } - public String generate() { - if (!isInit) { - init(); + public EntityIdRegistry(String strategy, Transaction<?> t) { + try { + @SuppressWarnings("unchecked") + Class<? extends EntityIdRegistry> clazz = + (Class<? extends EntityIdRegistry>) Class.forName(strategy); + Constructor<?> constructor = clazz.getConstructor(Transaction.class); + this.strategy = (EntityIdRegistryStrategy) constructor.newInstance(t); + } catch (ClassNotFoundException + | NoSuchMethodException + | SecurityException + | InstantiationException + | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException e) { + throw new TransactionException(e); } - ++currentMaxId; - return Integer.toString(++currentMaxId); + } + + public boolean matchIdPattern(String id) { + return this.strategy.matchIdPattern(id); } } diff --git a/src/main/java/org/caosdb/server/entity/EntityIdRegistryStrategy.java b/src/main/java/org/caosdb/server/entity/EntityIdRegistryStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..66235e980d1c82ecf6a7d3ef5b5fd30b702b41dd --- /dev/null +++ b/src/main/java/org/caosdb/server/entity/EntityIdRegistryStrategy.java @@ -0,0 +1,20 @@ +package org.caosdb.server.entity; + +import org.caosdb.server.transaction.Transaction; + +public abstract class EntityIdRegistryStrategy { + + private Transaction<?> transaction; + + public EntityIdRegistryStrategy(Transaction<?> transaction) { + this.transaction = transaction; + } + + public abstract String generate(); + + public Transaction<?> getTransaction() { + return transaction; + } + + public abstract boolean matchIdPattern(String id); +} diff --git a/src/main/java/org/caosdb/server/entity/LegacyIds.java b/src/main/java/org/caosdb/server/entity/LegacyIds.java new file mode 100644 index 0000000000000000000000000000000000000000..38f5bfefdc8f3028585881c489f3ff143498acfc --- /dev/null +++ b/src/main/java/org/caosdb/server/entity/LegacyIds.java @@ -0,0 +1,48 @@ +package org.caosdb.server.entity; + +import org.caosdb.server.database.backend.transaction.RetrieveCurrentMaxId; +import org.caosdb.server.transaction.Transaction; + +public class LegacyIds extends EntityIdRegistryStrategy { + + private boolean isInit; + private Integer currentMaxId; + + public LegacyIds(Transaction<?> t) { + super(t); + this.isInit = false; + } + + private void init() { + isInit = true; + initCurrentMaxId(); + } + + private void initCurrentMaxId() { + this.currentMaxId = + Math.max( + 101, + getTransaction() + .execute(new RetrieveCurrentMaxId(), getTransaction().getAccess()) + .getCurrentMaxId()); + } + + @Override + public String generate() { + if (!isInit) { + init(); + } + ++currentMaxId; + return Integer.toString(++currentMaxId); + } + + @Override + public boolean matchIdPattern(String id) { + try { + Integer.parseInt(id); + return true; + } catch (NumberFormatException e) { + return false; + } + } +} diff --git a/src/main/java/org/caosdb/server/entity/MagicTypes.java b/src/main/java/org/caosdb/server/entity/MagicTypes.java index e132ddc00c2aeac2630c0aabfc5a93a07ce504dc..6e987af95c0188fa21a50f19d11a493d97bbe8d8 100644 --- a/src/main/java/org/caosdb/server/entity/MagicTypes.java +++ b/src/main/java/org/caosdb/server/entity/MagicTypes.java @@ -33,9 +33,9 @@ public enum MagicTypes { NAME, DESCRIPTION; - private static final EntityID UNIT_ID = new EntityID(21); - private static final EntityID DESCRIPTION_ID = new EntityID(24); - private static final EntityID NAME_ID = new EntityID(20); + private static final EntityID UNIT_ID = new EntityID("21"); + private static final EntityID DESCRIPTION_ID = new EntityID("24"); + private static final EntityID NAME_ID = new EntityID("20"); public EntityID getId() { switch (this) { @@ -82,7 +82,7 @@ public enum MagicTypes { final RetrieveContainer container = new RetrieveContainer(null, System.currentTimeMillis(), null, null); for (final MagicTypes mt : MagicTypes.values()) { - container.add(mt.getId()); + container.add(mt.getId(), null); } final Retrieve retrieve = new Retrieve(container); retrieve.execute(); diff --git a/src/main/java/org/caosdb/server/entity/RetrieveEntity.java b/src/main/java/org/caosdb/server/entity/RetrieveEntity.java index 2d1ca6f2175ca2377b7f1a73f847a48377cc4694..00a120fbf023024eae8acc5788a9260d020a956d 100644 --- a/src/main/java/org/caosdb/server/entity/RetrieveEntity.java +++ b/src/main/java/org/caosdb/server/entity/RetrieveEntity.java @@ -47,6 +47,11 @@ public class RetrieveEntity extends Entity { this.setVersion(new Version(version)); } + public RetrieveEntity(final EntityID id, String name, final String version) { + this(id, version); + this.setName(name); + } + public RetrieveEntity(final String name, final String version) { super(name); this.setVersion(new Version(version)); diff --git a/src/main/java/org/caosdb/server/entity/StringIds.java b/src/main/java/org/caosdb/server/entity/StringIds.java new file mode 100644 index 0000000000000000000000000000000000000000..ca60730a0efac6b24060077dbbbb0185cfb1763c --- /dev/null +++ b/src/main/java/org/caosdb/server/entity/StringIds.java @@ -0,0 +1,26 @@ +package org.caosdb.server.entity; + +import java.util.UUID; +import org.caosdb.server.transaction.Transaction; + +public class StringIds extends EntityIdRegistryStrategy { + + public StringIds(Transaction<?> t) { + super(t); + } + + @Override + public String generate() { + return UUID.randomUUID().toString(); + } + + @Override + public boolean matchIdPattern(String id) { + try { + UUID.fromString(id); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } +} diff --git a/src/main/java/org/caosdb/server/entity/container/Container.java b/src/main/java/org/caosdb/server/entity/container/Container.java index 1618fbed6a1594891ea3ddc615f48869227f2c92..fdbcbf0de68d77c3eef026ef68d559a69f2f0956 100644 --- a/src/main/java/org/caosdb/server/entity/container/Container.java +++ b/src/main/java/org/caosdb/server/entity/container/Container.java @@ -36,9 +36,11 @@ public class Container<T extends EntityInterface> extends ArrayList<T> { * Return the entity with the matching id, if it can be found inside this Container, else null. */ public T getEntityById(final EntityID id) { - for (final T e : this) { - if (e.hasId() && e.getId().equals(id)) { - return e; + if (id != null) { + for (final T e : this) { + if (e.hasId() && e.getId().equals(id)) { + return e; + } } } return null; diff --git a/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java b/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java index a8c3e6a832848903884edda270e003a0c0dd6feb..1e756e3313fc4a816c096351527df7022a79f47b 100644 --- a/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java @@ -37,7 +37,5 @@ public abstract class EntityByIdContainer extends TransactionContainer { super(user, timestamp, srid, flags); } - public abstract void add(EntityID id); - public abstract void add(EntityID id, String version); } diff --git a/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java b/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java index bc0da7c1de2bb876551d29ad7daffb50494f9720..d58d85dc1d6a627757a9e0c8fd851aef899901bd 100644 --- a/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java @@ -27,7 +27,7 @@ import org.apache.shiro.subject.Subject; import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.RetrieveEntity; -public class RetrieveContainer extends EntityByIdContainer { +public class RetrieveContainer extends TransactionContainer { private static final long serialVersionUID = 4816050921531043503L; @@ -39,21 +39,11 @@ public class RetrieveContainer extends EntityByIdContainer { super(user, timestamp, srid, flags); } - @Override - public void add(final EntityID id) { - add(new RetrieveEntity(id)); - } - - public void add(final String name) { - add(new RetrieveEntity(name)); - } - - public void add(final String name, final String version) { - add(new RetrieveEntity(name, version)); - } - - @Override public void add(final EntityID id, final String version) { add(new RetrieveEntity(id, version)); } + + public void add(final EntityID id, final String name, final String version) { + add(new RetrieveEntity(id, name, version)); + } } diff --git a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java index 3e5ec4d55f086061e2d0766c9f700ef61fbe809f..f2f2c0254a2b9092e8c33c00a4b60f35d88fdeee 100644 --- a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java @@ -153,9 +153,11 @@ public class TransactionContainer extends Container<EntityInterface> * @param name */ public EntityInterface getEntityByName(final String name) { - for (final EntityInterface e : this) { - if (e.hasName() && e.getName().equals(name)) { - return e; + if (name != null) { + for (final EntityInterface e : this) { + if (e.hasName() && e.getName().equals(name)) { + return e; + } } } return null; diff --git a/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java b/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java index 88429828f27ac843903cfcfc801847c35eedb607..00a433d72c0a00e8e8ef796777bfa016679cbfe6 100644 --- a/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java +++ b/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java @@ -129,8 +129,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS result.setEmailSetting(EmailSetting.newBuilder().setEmail(user.email)); } if (user.entity != null) { - result.setEntitySetting( - EntitySetting.newBuilder().setEntityId(Integer.toString(user.entity))); + result.setEntitySetting(EntitySetting.newBuilder().setEntityId(user.entity)); } if (user.roles != null && !user.roles.isEmpty()) { result.addAllRoles(user.roles); diff --git a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java index 030b52544fec858ef3c62c531e9627baf5500551..61724779d7d9ae466a5acc3eb8116a309db5a5f6 100644 --- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java +++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java @@ -47,11 +47,11 @@ import org.caosdb.api.entity.v1.RetrieveResponse; import org.caosdb.api.entity.v1.SelectQueryResult; import org.caosdb.api.entity.v1.TransactionRequest; import org.caosdb.api.entity.v1.TransactionRequest.WrappedRequestsCase; -import org.caosdb.api.entity.v1.TransactionResponse; import org.caosdb.api.entity.v1.UpdateRequest; import org.caosdb.api.entity.v1.UpdateResponse; import org.caosdb.server.CaosDBException; import org.caosdb.server.entity.DeleteEntity; +import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.FileProperties; import org.caosdb.server.entity.InsertEntity; @@ -135,15 +135,19 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa } else { // or ID retrieves. final String id = sub_request.getRetrieveRequest().getId(); if (!id.isBlank()) { + /* try { - final RetrieveEntity entity = new RetrieveEntity(grpcToCaosdb.getId(id)); - if (isFileDownload) { - entity.setFlag("download_files", "true"); - } - container.add(entity); + */ + final RetrieveEntity entity = new RetrieveEntity(new EntityID(id)); + if (isFileDownload) { + entity.setFlag("download_files", "true"); + } + container.add(entity); + /* } catch (final NumberFormatException e) { // We handle this after the retrieval } + */ } } } @@ -194,7 +198,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa } // Add those entities which have not been retrieved because they have a string id - for (final TransactionRequest sub_request : request.getRequestsList()) { + /*for (final TransactionRequest sub_request : request.getRequestsList()) { final String id = sub_request.getRetrieveRequest().getId(); if (!id.isBlank()) { try { @@ -208,16 +212,18 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa RetrieveResponse.newBuilder().setEntityResponse(entityDoesNotExist(id)))); } } - } + }*/ return builder.build(); } + /* private EntityResponse entityDoesNotExist(final String id) { return EntityResponse.newBuilder() .addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST)) .setEntity(Entity.newBuilder().setId(id)) .build(); } + */ private String getSRID() { return UUID.randomUUID().toString(); @@ -298,7 +304,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa try { final UpdateEntity entity = new UpdateEntity( - grpcToCaosdb.getId(updateEntity.getId()), // ID is not handled by grpc convert + new EntityID(updateEntity.getId()), // ID is not handled by grpc convert grpcToCaosdb.convert(updateEntity.getRole())); grpcToCaosdb.convert(updateEntity, entity); addFileUpload(container, entity, updateRequest.getEntityRequest()); @@ -311,7 +317,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa case DELETE_REQUEST: final DeleteRequest deleteRequest = subRequest.getDeleteRequest(); try { - final DeleteEntity entity = new DeleteEntity(grpcToCaosdb.getId(deleteRequest.getId())); + final DeleteEntity entity = new DeleteEntity(new EntityID(deleteRequest.getId())); container.add(entity); } catch (final NumberFormatException e) { @@ -383,12 +389,14 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa final Entity updateEntity = updateRequest.getEntityRequest().getEntity(); idResponse.setId(updateEntity.getId()); + /* try { grpcToCaosdb.getId(updateEntity.getId()); } catch (final NumberFormatException e) { // ID wasn't an integer idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST)); } + */ builder .addResponsesBuilder() .setUpdateResponse(UpdateResponse.newBuilder().setIdResponse(idResponse)); @@ -396,12 +404,14 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa case DELETE_REQUEST: final DeleteRequest deleteRequest = subRequest.getDeleteRequest(); idResponse.setId(deleteRequest.getId()); + /* try { grpcToCaosdb.getId(deleteRequest.getId()); } catch (final NumberFormatException e) { // ID wasn't an integer idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST)); } + */ builder .addResponsesBuilder() .setDeleteResponse(DeleteResponse.newBuilder().setIdResponse(idResponse)); diff --git a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java index 0430a795457152141473c2819997ebd1597028fd..1c0b0f429d1702c9e952e3aeda95bcd13355b4df 100644 --- a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java +++ b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java @@ -66,9 +66,11 @@ import org.caosdb.server.utils.ServerMessages; public class GrpcToCaosDBConverters { + /* public EntityID getId(final String id) { return new EntityID(Integer.parseInt(id)); } + */ public Role convert(final EntityRole role) { switch (role) { @@ -256,7 +258,7 @@ public class GrpcToCaosDBConverters { final Property result = new Property(new RetrieveEntity()); try { - result.setId(e.getId().isBlank() ? null : getId(e.getId())); + result.setId(e.getId().isBlank() ? null : new EntityID(e.getId())); } catch (final NumberFormatException exc) { result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); } @@ -314,7 +316,7 @@ public class GrpcToCaosDBConverters { new org.caosdb.server.entity.wrapper.Parent(new RetrieveEntity()); try { - result.setId(e.getId().isBlank() ? null : getId(e.getId())); + result.setId(e.getId().isBlank() ? null : new EntityID(e.getId())); } catch (final NumberFormatException exc) { result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); } @@ -336,7 +338,7 @@ public class GrpcToCaosDBConverters { private EntityInterface convert(EntityACL acl) { try { - EntityID id = getId(acl.getId()); + EntityID id = new EntityID(acl.getId()); UpdateEntity result = new UpdateEntity(id); result.setEntityACL(convertAcl(acl)); return result; diff --git a/src/main/java/org/caosdb/server/jobs/Job.java b/src/main/java/org/caosdb/server/jobs/Job.java index 9f6103a9bea047fb11b1b25d6ecc9cfa67988ab8..5134de6ccd796aa7a1ca6111af0c56447ad9925e 100644 --- a/src/main/java/org/caosdb/server/jobs/Job.java +++ b/src/main/java/org/caosdb/server/jobs/Job.java @@ -3,8 +3,8 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * Copyright (C) 2020-2021 IndiScale GmbH <info@indiscale.com> - * Copyright (C) 2020-2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2020-2023 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020-2023 Timm Fitschen <t.fitschen@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -25,6 +25,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import org.apache.shiro.subject.Subject; @@ -32,9 +33,8 @@ import org.caosdb.server.CaosDBException; import org.caosdb.server.database.BackendTransaction; import org.caosdb.server.database.backend.transaction.GetIDByName; import org.caosdb.server.database.backend.transaction.IsSubType; -import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransaction; -import org.caosdb.server.database.backend.transaction.RetrieveParents; import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity; +import org.caosdb.server.database.exceptions.EntityDoesNotExistException; import org.caosdb.server.database.exceptions.EntityWasNotUniqueException; import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.datatype.AbstractCollectionDatatype; @@ -43,13 +43,12 @@ import org.caosdb.server.datatype.ReferenceDatatype2; import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.Message; -import org.caosdb.server.entity.container.ParentContainer; +import org.caosdb.server.entity.Version; import org.caosdb.server.entity.container.TransactionContainer; import org.caosdb.server.entity.wrapper.Parent; import org.caosdb.server.jobs.core.JobFailureSeverity; import org.caosdb.server.transaction.Transaction; import org.caosdb.server.utils.EntityStatus; -import org.caosdb.server.utils.ServerMessages; import org.reflections.Reflections; /** @@ -72,7 +71,7 @@ public abstract class Job { public abstract JobTarget getTarget(); - protected <S, T> HashMap<S, T> getCache(final String name) { + protected <S, T> Map<S, T> getCache(final String name) { return getTransaction().getCache(name); } @@ -88,7 +87,7 @@ public abstract class Job { return getTransaction().getTransactor(); } - public <K extends BackendTransaction> K execute(final K t) { + protected <K extends BackendTransaction> K execute(final K t) { return getTransaction().execute(t, getTransaction().getAccess()); } @@ -184,8 +183,8 @@ public abstract class Job { if (targetParent.getId().equals(child.getId())) { return true; } - - } else if (targetParent.hasName()) { + } + if (targetParent.hasName()) { if (targetParent.getName().equals(child.getName())) { return true; } else { @@ -194,13 +193,7 @@ public abstract class Job { } // check direct parents of child - ParentContainer directParents; - if (child.hasParents()) { - directParents = child.getParents(); - } else { - directParents = resolve(child).getParents(); - } - for (final Parent directParent : directParents) { + for (final Parent directParent : child.getParents()) { EntityInterface resolvedDirectParent = null; if (directParent.hasId() && targetParent.hasId()) { if (directParent.getId().equals(targetParent.getId())) { @@ -230,78 +223,73 @@ public abstract class Job { } protected final boolean isValidSubType(final EntityID child, final EntityID parent) { - if (!"false".equals(getContainer().getFlags().get("cache"))) { - final HashMap<String, Boolean> isSubTypeCache = getCache("isSubType"); - final String key = child + "->" + parent; - final Boolean cached = isSubTypeCache.get(key); - if (cached == null) { - final Boolean toCache = isValidSubTypeNoCache(child, parent); - isSubTypeCache.put(key, toCache); - return toCache; - } else { - return cached; - } - } else { - return isValidSubTypeNoCache(child, parent); + Boolean result = null; + final Map<String, Boolean> isSubTypeCache = getCache("isSubType"); + + final String key = child + "->" + parent; + result = isSubTypeCache.get(key); + + if (result == null) { + result = isValidSubTypeNoCache(child, parent); + isSubTypeCache.put(key, result); } + + return result; } - protected final boolean isValidSubTypeNoCache(final EntityID child, final EntityID parent) { + private final boolean isValidSubTypeNoCache(final EntityID child, final EntityID parent) { return Objects.equals(child, parent) || execute(new IsSubType(child, parent)).isSubType(); } - protected final EntityInterface retrieveValidSparseEntityByName(final String name) - throws Message { - return retrieveValidSparseEntityById(retrieveValidIDByName(name), null); + private final EntityInterface retrieveValidLazyEntityByName(final String name, String version) { + EntityID id = null; + + final Map<String, EntityID> cache = getCache("validEntityByName"); + String key = name; + if (version != null && !version.equals("HEAD")) { + key += version; + } + + id = cache.get(key); + if (id == null) { + id = retrieveValidIDByName(name, version); + cache.put(key, id); + } + + return retrieveValidLazyEntityById(id, version); } - protected final EntityInterface retrieveValidSparseEntityById( - final EntityID id, final String version) throws Message { + private final EntityInterface retrieveValidLazyEntityById( + final EntityID id, final String version) { + EntityInterface result = null; - String resulting_version = version; - if (version == null || version.equals("HEAD")) { - // the targeted entity version is the entity after the transaction or the - // entity without a specific version. Thus we have to fetch the entity - // from the container if possible. - final EntityInterface ret = getEntityById(id); - if (ret != null) { - return ret; - } - } else if (version.startsWith("HEAD~")) { - final EntityInterface entById = getEntityById(id); - if (entById != null && entById.getEntityStatus() != EntityStatus.VALID) { - // if version is HEAD~{OFFSET} with {OFFSET} > 0 and the targeted entity is is to be - // updated, the actual offset has to be reduced by 1. HEAD always denotes the entity@HEAD - // *after* the successful transaction, so that it is consistent with subsequent retrieves. - final int offset = Integer.parseInt(version.substring(5)) - 1; - if (offset == 0) { - // special case HEAD~1 - resulting_version = "HEAD"; - } else { - resulting_version = new StringBuilder().append("HEAD~").append(offset).toString(); - } - } + final Map<String, EntityInterface> cache = getCache("validEntityById"); + String key = id.toString(); + if (version != null && !version.equals("HEAD")) { + key += version; } - final EntityInterface ret = - execute(new RetrieveSparseEntity(id, resulting_version)).getEntity(); - if (ret.getEntityStatus() == EntityStatus.NONEXISTENT) { - throw ServerMessages.ENTITY_DOES_NOT_EXIST; + result = cache.get(key); + if (result == null) { + result = retrieveValidLazyEntityByIdNoCache(id, version); + cache.put(key, result); } - return ret; - } - protected final EntityInterface retrieveValidEntity(final EntityID id) { - return execute(new RetrieveFullEntityTransaction(id)).getContainer().get(0); + return result; } - protected final EntityID retrieveValidIDByName(final String name) { - return execute(new GetIDByName(name)).getId(); + private final EntityInterface retrieveValidLazyEntityByIdNoCache( + final EntityID id, final String version) { + + final EntityInterface ret = execute(new RetrieveSparseEntity(id, version)).getEntity(); + if (ret.getEntityStatus() == EntityStatus.NONEXISTENT) { + throw new EntityDoesNotExistException(); + } + return new LazyEntityResolver(ret, getTransaction()); } - protected EntityInterface retrieveParentsOfValidEntity(final EntityInterface entity) { - execute(new RetrieveParents(entity)); - return entity; + protected final EntityID retrieveValidIDByName(final String name, String version) { + return execute(new GetIDByName(name, version)).getId(); } /** @@ -386,7 +374,7 @@ public abstract class Job { } if (dt instanceof ReferenceDatatype2) { return jobConfig.getConfiguredJobs( - EntityID.DEFAULT_DOMAIN, new EntityID(17), entity, transaction); + EntityID.DEFAULT_DOMAIN, new EntityID("17"), entity, transaction); } else if (dt instanceof AbstractCollectionDatatype) { final AbstractDatatype datatype = ((AbstractCollectionDatatype) dt).getDatatype(); return loadDataTypeSpecificJobs(datatype, entity, transaction); @@ -414,7 +402,8 @@ public abstract class Job { // load general rules final List<Job> generalRules = - jobConfig.getConfiguredJobs(EntityID.DEFAULT_DOMAIN, new EntityID(0), entity, transaction); + jobConfig.getConfiguredJobs( + EntityID.DEFAULT_DOMAIN, new EntityID("0"), entity, transaction); if (generalRules != null) { jobs.addAll(generalRules); } @@ -544,10 +533,6 @@ public abstract class Job { + "]"; } - public void print() { - System.out.println(toString()); - } - public TransactionStage getTransactionStage() { return this.stage; } @@ -562,26 +547,72 @@ public abstract class Job { */ protected EntityInterface resolve(final EntityInterface entity) throws EntityWasNotUniqueException { - EntityInterface resolvedEntity = null; - if (!entity.hasId() && entity.hasName()) { - resolvedEntity = getEntityByName(entity.getName()); + return resolve(entity.getId(), entity.getName(), entity.getVersion()); + } + + protected EntityInterface resolve(EntityID id) { + return resolve(id, null, (String) null); + } + + protected EntityInterface resolve(EntityID id, String name, String versionId) + throws EntityDoesNotExistException, EntityWasNotUniqueException { + EntityInterface resolvedEntity = getEntityById(id); + + String resulting_version = versionId; + if (versionId == null || versionId.equals("HEAD")) { + resulting_version = null; + versionId = null; + } else if (versionId.startsWith("HEAD~")) { if (resolvedEntity == null) { - final EntityID eid = retrieveValidIDByName(entity.getName()); - entity.setId(eid); + resolvedEntity = getEntityByName(name); + } + if (resolvedEntity != null && resolvedEntity.getEntityStatus() == EntityStatus.QUALIFIED) { + // if versionId is HEAD~{OFFSET} with {OFFSET} > 0 and the targeted entity is is to be + // updated, the actual offset has to be reduced by 1. HEAD always denotes the entity@HEAD + // *after* the successful transaction, so that it is consistent with subsequent retrieves. + final int offset = Integer.parseInt(versionId.substring(5)) - 1; + if (offset == 0) { + // special case HEAD~1 + resulting_version = "HEAD"; + } else { + resulting_version = new StringBuilder().append("HEAD~").append(offset).toString(); + } } + resolvedEntity = null; + } else { + resolvedEntity = null; } - if (entity.hasId()) { - // get entity from container - resolvedEntity = getEntityById(entity.getId()); - if (resolvedEntity == null && !entity.getId().isTemporary()) { - resolvedEntity = retrieveValidEntity(entity.getId()); + if (resolvedEntity == null && id != null) { + try { + resolvedEntity = retrieveValidLazyEntityById(id, resulting_version); + } catch (EntityDoesNotExistException e) { + // ignore here, try to find by name. } } + // find by name in the container... + if (resolvedEntity == null && versionId == null) { + // from current transaction's container + resolvedEntity = getEntityByName(name); + } + + if (resolvedEntity == null && name != null) { + // from database + resolvedEntity = retrieveValidLazyEntityByName(name, resulting_version); + } + + if (resolvedEntity == null) { + throw new EntityDoesNotExistException(); + } return resolvedEntity; } + protected EntityInterface resolve(EntityID id, String name, Version version) { + String versionId = version != null ? version.getId() : null; + return resolve(id, name, versionId); + } + /** * Return those matching jobs which are annotated with the "loadAlways" attribute. * @@ -598,4 +629,22 @@ public abstract class Job { } return jobs; } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof Job) { + Job other = (Job) obj; + return other.getClass().equals(this.getClass()) + && Objects.equals(other.getEntity(), this.getEntity()) + && other.getFailureSeverity().equals(this.getFailureSeverity()); + } + return false; + } + + @Override + public int hashCode() { + return getClass().hashCode() + + (getEntity() == null ? 0 : getEntity().hashCode()) + + getFailureSeverity().hashCode(); + } } diff --git a/src/main/java/org/caosdb/server/jobs/JobConfig.java b/src/main/java/org/caosdb/server/jobs/JobConfig.java index ac53b605f5a0d9a5514403a1976b3e42650a75f2..ab6cd819fd338931aa32c41e2d9923ca716c9bf0 100644 --- a/src/main/java/org/caosdb/server/jobs/JobConfig.java +++ b/src/main/java/org/caosdb/server/jobs/JobConfig.java @@ -141,8 +141,8 @@ public class JobConfig { "Could not parse the job rules. Lines of five comma-separated values expected"); } try { - final Integer domain = Integer.parseInt(row[0]); - final Integer entity = Integer.parseInt(row[1]); + final String domain = row[0]; + final String entity = row[1]; final String transaction = row[2]; final String job = row[3]; final JobFailureSeverity severity = JobFailureSeverity.valueOf(row[4]); diff --git a/src/main/java/org/caosdb/server/jobs/LazyEntityResolver.java b/src/main/java/org/caosdb/server/jobs/LazyEntityResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..285378e16329d0a171eb55e550d916ac2a209a28 --- /dev/null +++ b/src/main/java/org/caosdb/server/jobs/LazyEntityResolver.java @@ -0,0 +1,62 @@ +package org.caosdb.server.jobs; + +import org.caosdb.server.database.backend.transaction.RetrieveParents; +import org.caosdb.server.database.backend.transaction.RetrieveProperties; +import org.caosdb.server.entity.EntityInterface; +import org.caosdb.server.entity.container.ParentContainer; +import org.caosdb.server.entity.container.PropertyContainer; +import org.caosdb.server.entity.wrapper.EntityWrapper; +import org.caosdb.server.transaction.Transaction; + +public class LazyEntityResolver extends EntityWrapper { + + private Transaction<?> transaction; + private boolean propertiesResolved = false; + private boolean parentsResolved = false; + + public LazyEntityResolver(EntityInterface entity, Transaction<?> transaction) { + super(entity); + this.transaction = transaction; + } + + public void resolveParents() { + if (parentsResolved) return; + parentsResolved = true; + transaction.execute(new RetrieveParents(getWrapped()), transaction.getAccess()); + } + + private void resolveProperties() { + if (propertiesResolved) return; + propertiesResolved = true; + transaction.execute(new RetrieveProperties(getWrapped()), transaction.getAccess()); + } + + public void resolveAll() { + resolveParents(); + resolveProperties(); + } + + @Override + public ParentContainer getParents() { + resolveParents(); + return super.getParents(); + } + + @Override + public boolean hasParents() { + resolveParents(); + return super.hasParents(); + } + + @Override + public PropertyContainer getProperties() { + resolveProperties(); + return super.getProperties(); + } + + @Override + public boolean hasProperties() { + resolveProperties(); + return super.hasProperties(); + } +} diff --git a/src/main/java/org/caosdb/server/jobs/Schedule.java b/src/main/java/org/caosdb/server/jobs/Schedule.java index 57474da515418745ed0457962596dfce233bff48..ab0f63a2105dacfea0fce0a7c5d553799b0ae222 100644 --- a/src/main/java/org/caosdb/server/jobs/Schedule.java +++ b/src/main/java/org/caosdb/server/jobs/Schedule.java @@ -44,7 +44,10 @@ public class Schedule { public List<ScheduledJob> addAll(final Collection<Job> jobs) { final List<ScheduledJob> result = new ArrayList<ScheduledJob>(jobs.size()); for (final Job j : jobs) { - result.add(add(j)); + ScheduledJob scheduledJob = add(j); + if (scheduledJob != null) { + result.add(scheduledJob); + } } return result; } @@ -56,8 +59,11 @@ public class Schedule { jobs = new CopyOnWriteArrayList<ScheduledJob>(); jobLists.put(ret.getTransactionStage().ordinal(), jobs); } - jobs.add(ret); - return ret; + if (!jobs.contains(ret)) { + jobs.add(ret); + return ret; + } + return null; } /** Run all Jobs from the specified {@link TransactionStage}. */ @@ -71,7 +77,7 @@ public class Schedule { } public void runJob(final ScheduledJob scheduledJob) { - if (scheduledJob.skip()) { + if (scheduledJob == null || scheduledJob.skip()) { return; } final ScheduledJob parent = this.running; diff --git a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java index 2122b34de5f0b60db4c2b6d4c1c2358d3df02851..f729e0047c2f2ccc9b924b6650cbb64c7ec3749a 100644 --- a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java +++ b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java @@ -102,4 +102,18 @@ public class ScheduledJob { public Job getJob() { return job; } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ScheduledJob) { + ScheduledJob other = (ScheduledJob) obj; + return this.job.equals(other.job); + } + return false; + } + + @Override + public int hashCode() { + return job.hashCode(); + } } diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java index 40e01d2636509774555f1514c75bb0bf16870539..adc02cafb3c27162d00c8aded5db2eea9a2aa240 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java @@ -115,44 +115,15 @@ public final class CheckDatatypePresent extends EntityJob { } private void checkReference2(final ReferenceDatatype2 datatype) throws Message { + EntityInterface datatypeEntity = resolve(datatype.getId(), datatype.getName(), (String) null); - if (datatype.getId() == null) { - // try and get from container... - final EntityInterface datatypeEntity = getEntityByName(datatype.getName()); - - // if the container carried a corresponding entity - if (datatypeEntity != null) { - assertAllowedToUse(datatypeEntity); - - // ... we set it as the datatypevalue - datatype.setEntity(datatypeEntity); - } else { - - // else try and get from database. - final EntityInterface validDatatypeEntity = - retrieveValidSparseEntityByName(datatype.getName()); - assertAllowedToUse(validDatatypeEntity); - datatype.setId(validDatatypeEntity.getId()); - } - } else if (datatype.getId().isTemporary()) { - final EntityInterface datatypeEntity = getEntityById(datatype.getId()); - - // if the container carried a corresponding entity - if (datatypeEntity != null) { - assertAllowedToUse(datatypeEntity); - // ... we set it as the datatype - datatype.setEntity(datatypeEntity); - } else { - - throw ServerMessages.UNKNOWN_DATATYPE; - } - } else { - - final EntityInterface validDatatypeEntity = - retrieveValidSparseEntityById(datatype.getId(), null); - assertAllowedToUse(validDatatypeEntity); - datatype.setEntity(validDatatypeEntity); + if (datatypeEntity == null) { + throw ServerMessages.UNKNOWN_DATATYPE; } + + // do the actual checking + assertAllowedToUse(datatypeEntity); + datatype.setEntity(datatypeEntity); } private void assertAllowedToUse(final EntityInterface datatype) { @@ -160,62 +131,37 @@ public final class CheckDatatypePresent extends EntityJob { } private void checkIfOverride() throws Message { - if (getEntity().hasId() && !getEntity().getId().isTemporary()) { - // get data type from database - final EntityInterface foreign = retrieveValidSparseEntityById(getEntity().getId(), null); - - if (foreign.hasDatatype() && !foreign.getDatatype().equals(getEntity().getDatatype())) { - // is override! - getEntity().setDatatypeOverride(true); - } - } else { - // get data type from container - EntityInterface abstractProperty = null; - if (getEntity().hasId()) { - abstractProperty = getEntityById(getEntity().getId()); - } else if (getEntity().hasName()) { - abstractProperty = getEntityByName(getEntity().getName()); - } - if (abstractProperty != null && abstractProperty.hasDatatype()) { - if (!getEntity().getDatatype().equals(abstractProperty.getDatatype())) { - // is override! - getEntity().setDatatypeOverride(true); - } - } + EntityInterface abstractProperty = resolve(getEntity()); + if (abstractProperty != null + && abstractProperty.hasDatatype() + && !abstractProperty.getDatatype().equals(getEntity().getDatatype())) { + // is override! + getEntity().setDatatypeOverride(true); } } 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().isTemporary()) { - // get from data base - final EntityInterface foreign = retrieveValidSparseEntityById(getEntity().getId(), null); - inheritDatatypeFromForeignEntity(foreign); - } else if (getEntity().hasId() && getEntity().getId().isTemporary()) { - // get from container - final EntityInterface foreign = getEntityById(getEntity().getId()); - inheritDatatypeFromForeignEntity(foreign); - } - } - - private void inheritDatatypeFromForeignEntity(final EntityInterface foreign) { - if (foreign != null && foreign.hasDatatype()) { - getEntity().setDatatype(foreign.getDatatype()); - } else if (foreign != null && foreign != getEntity() && foreign.getRole() == Role.RecordType) { - getEntity().setDatatype(ReferenceDatatype2.datatypeFactory(foreign.getId())); + EntityInterface abstractProperty = resolve(getEntity()); + if (abstractProperty != null && abstractProperty.hasDatatype()) { + getEntity().setDatatype(abstractProperty.getDatatype()); + } else if (abstractProperty != null + && abstractProperty != getEntity() + && abstractProperty.getRole() == Role.RecordType) { + getEntity().setDatatype(ReferenceDatatype2.datatypeFactory(abstractProperty.getId())); } } private void resolveId(final EntityInterface entity) { if (!entity.hasId() && entity.hasName()) { try { - entity.setId(retrieveValidIDByName(entity.getName())); - if (entity.getEntityStatus() != EntityStatus.UNQUALIFIED) { - entity.setEntityStatus(EntityStatus.VALID); + EntityInterface resolved = resolve(entity); + if (resolved == null) { + entity.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); + } else { + entity.setId(resolved.getId()); } - } catch (final EntityDoesNotExistException exc) { - entity.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); } catch (final EntityWasNotUniqueException exc) { entity.addError(ServerMessages.ENTITY_NAME_DUPLICATES); } @@ -227,14 +173,12 @@ public final class CheckDatatypePresent extends EntityJob { AbstractDatatype datatype = null; for (final EntityInterface parent : getEntity().getParents()) { - EntityInterface parentEntity = null; - if (!parent.getId().isTemporary()) { - parentEntity = retrieveValidSparseEntityById(parent.getId(), null); - } else { - parentEntity = getEntityById(parent.getId()); + EntityInterface parentEntity = resolve(parent); + if (!parentEntity.hasDatatype() && parentEntity.getEntityStatus() == EntityStatus.QUALIFIED) { runJobFromSchedule(parentEntity, CheckDatatypePresent.class); } - if (parentEntity.hasDatatype()) { + if (parentEntity.hasDatatype() + && parentEntity.getEntityStatus() != EntityStatus.UNQUALIFIED) { if (datatype != null && !parentEntity.getDatatype().equals(datatype)) { getEntity().addError(ServerMessages.DATATYPE_INHERITANCE_AMBIGUOUS); return; diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java index e6ba9da430e6218e5c40fba968c309ed94152bf6..eba79831468b1f6799507ca0866a64e594997caa 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java @@ -93,7 +93,7 @@ public class CheckParOblPropPresent extends EntityJob { // loop over all properties of the entity for (final EntityInterface entityProperty : getEntity().getProperties()) { - if (isSubType(entityProperty, parentProperty)) { + if (isSubType(resolve(entityProperty), parentProperty)) { // continue outer loop means that we // found an entityProperty that // implements the obligatory diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java index 8895ae9adb4d12da2f7789a8798ca0fb9d183c05..e125e5dda8edbbecd3873a53e04755faba0874e3 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java @@ -60,73 +60,21 @@ public class CheckParValid extends EntityJob { if (!parent.hasId() && !parent.hasName()) { // The parent has neither an id nor a name. // Therefore it cannot be identified. - - throw ServerMessages.ENTITY_HAS_NO_NAME_OR_ID; + parent.addError(ServerMessages.ENTITY_HAS_NO_NAME_OR_ID); } - - if (parent.hasId()) { - // check parent by id - if (!parent.getId().isTemporary()) { - // id isn't temporary, i.e., parent is already in the database and - // can be retrieved by id - final EntityInterface foreign = retrieveValidSparseEntityById(parent.getId(), null); - // check permissions for this - // parentforeign.acceptObserver(o) - assertAllowedToUse(foreign); - parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole())); - continue; - } else { - // id < 0 (parent is to be stored along with - // this entity) - - // get entity with corresponding (negative) id - // from container - final EntityInterface foreign = getEntityById(parent.getId()); - - // if the container carried a corresponding - // entity - if (foreign != null) { - assertAllowedToUse(foreign); - - parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole())); - - // ... we can set it as the parent - parent.linkIdToEntity(foreign); - continue; - } - } - } - - // parent doesn't have an id. - if (parent.hasName()) { - if (getEntityByName(parent.getName()) != null) { - // get the parent entity from the container by its - // name - final EntityInterface foreign = getEntityByName(parent.getName()); - - assertAllowedToUse(foreign); - parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole())); - parent.linkIdToEntity(foreign); - continue; - } else { - // check parent by name (parent is expected to be - // valid). This only works if the name is unique. - final EntityInterface foreign = retrieveValidSparseEntityByName(parent.getName()); - assertAllowedToUse(foreign); - parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole())); - parent.setId(foreign.getId()); - continue; - } + try { + EntityInterface foreign = resolve(parent.getId(), parent.getName(), (String) null); + assertAllowedToUse(foreign); + parent.linkIdToEntity(foreign); + parent.setAffiliation(getAffiliation(getEntity().getRole(), foreign.getRole())); + } catch (EntityDoesNotExistException e) { + parent.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); } - - parent.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); } catch (final Message m) { parent.addError(m); } catch (AuthorizationException e) { parent.addError(ServerMessages.AUTHORIZATION_ERROR); parent.addInfo(e.getMessage()); - } catch (final EntityDoesNotExistException exc) { - parent.addError(ServerMessages.ENTITY_DOES_NOT_EXIST); } catch (final EntityWasNotUniqueException exc) { parent.addError(ServerMessages.ENTITY_NAME_DUPLICATES); } diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java index 23a92340f5befbfbe7ded2fe95d3244b5ff78594..b57e7abbb1b98b24c107c17372a602370f79afe2 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckPropValid.java @@ -54,75 +54,21 @@ public class CheckPropValid extends EntityJob { if (property.getEntityStatus() == EntityStatus.QUALIFIED) { // this property is to be tested. - // does this property have an id at all? - if (property.hasId()) { - if (!property.getId().isTemporary()) { - - final EntityInterface abstractProperty = - retrieveValidSparseEntityById(property.getId(), null); - - assertAllowedToUse(abstractProperty); - - deriveOverrideStatus(property, abstractProperty); - continue; - } else { - // task here: find the corresponding abstract - // property (or rarely any other entity) in this - // container which has the same (negative) id. - - // fetch the abstractProperty from the container. - final EntityInterface abstractProperty = getEntityById(property.getId()); - - if (abstractProperty != null) { - assertAllowedToUse(abstractProperty); - - // link the id of the property to the id of - // the abstractProperty means. This has the - // effect that the property will have a - // valid id as soon as the abstractProperty - // has been inserted. - property.linkIdToEntity(abstractProperty); - deriveOverrideStatus(property, abstractProperty); - continue; - } else if (!property.hasName()) { - // an abstractProperty with this (negative) id - // had not been found in this container. - throw ENTITY_DOES_NOT_EXIST; - } - } - } - - if (property.hasName()) { - - // try and get it from the container - EntityInterface foreign = getEntityByName(property.getName()); - if (foreign != null) { - assertAllowedToUse(foreign); - - // link the id of the property to the id of - // the abstractProperty means. This has the - // effect that the property will have a - // valid id as soon as the abstractProperty - // has been inserted. - property.linkIdToEntity(foreign); - deriveOverrideStatus(property, foreign); - } else { - foreign = retrieveValidSparseEntityByName(property.getName()); - - assertAllowedToUse(foreign); - - property.setId(foreign.getId()); - - deriveOverrideStatus(property, foreign); - } - } - if (!property.hasName() && !property.hasId()) { // The property has neither an id nor a name. // Thus it cannot be identified. throw ServerMessages.ENTITY_HAS_NO_NAME_OR_ID; } + EntityInterface abstractProperty = + resolve(property.getId(), property.getName(), (String) null); + if (abstractProperty == null) { + property.addError(ENTITY_DOES_NOT_EXIST); + continue; + } + assertAllowedToUse(abstractProperty); + deriveOverrideStatus(property, abstractProperty); + property.linkIdToEntity(abstractProperty); } } catch (final Message m) { property.addError(m); diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java b/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java index 0b8ba45b1cae19812641ed733be7aacc2fb78575..af7269a31756eb556729bf71f43bb0feda02bd67 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java @@ -82,24 +82,8 @@ public class CheckRefidIsaParRefid extends EntityJob implements Observer { for (final IndexedSingleValue v : vals) { if (v != null && v.getWrapped() != null) { final ReferenceValue rv = (ReferenceValue) v.getWrapped(); - if (rv.getEntity() != null - && rv.getEntity().hasRole() - && rv.getEntity().getRole() == Role.File) { - } else if (rv.getId() != null - && rv.getId().isTemporary() - && getEntityById(rv.getId()) != null - && getEntityById(rv.getId()).getRole() == Role.File) { - } else if (rv.getId() == null - && rv.getName() != null - && getEntityByName(rv.getName()) != null - && getEntityByName(rv.getName()).getRole() == Role.File) { - } else if (rv.getId() != null - && !rv.getId().isTemporary() - && retrieveValidSparseEntityById(rv.getId(), rv.getVersion()).getRole() - == Role.File) { - } else if (rv.getName() != null - && retrieveValidSparseEntityByName(rv.getName()).getRole() == Role.File) { - } else { + EntityInterface referencedEntity = resolve(rv.getId(), rv.getName(), rv.getVersion()); + if (referencedEntity.getRole() != Role.File) { throw ServerMessages.REFERENCE_IS_NOT_ALLOWED_BY_DATATYPE; } } diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java index 12b545b8e6fd608e20851d37f34e809acfcd1544..b01c5bf389175d1c087ced9acf4f135d7679a5be 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java @@ -83,61 +83,12 @@ public class CheckRefidValid extends EntityJob implements Observer { } private void checkRefValue(final ReferenceValue ref) throws Message { - if (ref.getId() != null) { - if (!ref.getId().isTemporary()) { - final EntityInterface referencedValidEntity = - retrieveValidSparseEntityById(ref.getId(), ref.getVersion()); - assertAllowedToUse(referencedValidEntity); - - // link the entity as versioned entity iff the reference specified a version - ref.setEntity(referencedValidEntity, ref.getVersion() != null); - - } else { - - // is the referenced entity yet linked to this refid - // property? - if (ref.getEntity() == null) { - - // link the entity with the corresponding - // negative id to this reference object - final EntityInterface referencedEntity = getEntityById(ref.getId()); - if (referencedEntity != null) { - assertAllowedToUse(referencedEntity); - - // link the entity as versioned entity iff the reference specified a version - ref.setEntity(referencedEntity, ref.getVersion() != null); - } else { - throw ServerMessages.REFERENCED_ENTITY_DOES_NOT_EXIST; - } - } - ref.getEntity().acceptObserver(this); - checkRefEntity(ref); - } - } else if (ref.getName() != null) { - // is the referenced entity yet linked to this - // refid property? - if (ref.getEntity() == null) { - // the entity is in this container? - final EntityInterface referencedEntity = getEntityByName(ref.getName()); - - if (referencedEntity != null) { - assertAllowedToUse(referencedEntity); - - // link the entity as versioned entity iff the reference specified a version - ref.setEntity(referencedEntity, ref.getVersion() != null); - if (checkRefEntity(ref)) { - ref.getEntity().acceptObserver(this); - } - } else { - final EntityInterface referencedValidEntity = - retrieveValidSparseEntityByName(ref.getName()); - assertAllowedToUse(referencedValidEntity); - - // link the entity as versioned entity iff the reference specified a version - ref.setEntity(referencedValidEntity, ref.getVersion() != null); - } - } + EntityInterface referencedEntity = resolve(ref.getId(), ref.getName(), ref.getVersion()); + if (referencedEntity == null) { + throw ServerMessages.REFERENCED_ENTITY_DOES_NOT_EXIST; } + assertAllowedToUse(referencedEntity); + ref.setEntity(referencedEntity, ref.getVersion() != null); } private void assertAllowedToUse(final EntityInterface referencedEntity) { diff --git a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java index a4c50f8893935d7bbd6091b970b32a8811a08d93..409718012086063c7de9f5db003b965a188cc061 100644 --- a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java +++ b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java @@ -53,6 +53,7 @@ import org.caosdb.server.entity.container.TransactionContainer; import org.caosdb.server.entity.wrapper.Property; import org.caosdb.server.entity.xml.ToElementable; import org.caosdb.server.jobs.EntityJob; +import org.caosdb.server.jobs.LazyEntityResolver; import org.caosdb.server.permissions.EntityACI; import org.caosdb.server.permissions.EntityACL; import org.caosdb.server.query.Query; @@ -572,7 +573,7 @@ public abstract class EntityStateJob extends EntityJob { final String key = "transition" + refid.toString(); EntityInterface transition = getCached(key); if (transition == null) { - transition = retrieveValidEntity(refid); + transition = resolve(refid); putCache(key, transition); } result.add(new Transition(transition)); @@ -659,7 +660,7 @@ public abstract class EntityStateJob extends EntityJob { private EntityInterface retrieveStateEntity(final String stateName) throws Message { try { - return retrieveValidEntity(retrieveValidIDByName(stateName)); + return resolve(null, stateName, (String) null); } catch (final EntityDoesNotExistException e) { throw STATE_NOT_IN_STATE_MODEL; } @@ -667,7 +668,7 @@ public abstract class EntityStateJob extends EntityJob { private EntityInterface retrieveStateModelEntity(final String stateModel) throws Message { try { - return retrieveValidEntity(retrieveValidIDByName(stateModel)); + return resolve(null, stateModel, (String) null); } catch (final EntityDoesNotExistException e) { throw STATE_MODEL_NOT_FOUND; } @@ -676,7 +677,7 @@ public abstract class EntityStateJob extends EntityJob { protected EntityInterface getStateRecordType() throws Message { EntityInterface stateRecordType = getCached(STATE_RECORD_TYPE_NAME); if (stateRecordType == null) { - stateRecordType = retrieveValidSparseEntityByName(STATE_RECORD_TYPE_NAME); + stateRecordType = resolve(null, STATE_RECORD_TYPE_NAME, (String) null); putCache(STATE_RECORD_TYPE_NAME, stateRecordType); } return stateRecordType; @@ -797,7 +798,7 @@ public abstract class EntityStateJob extends EntityJob { EntityInterface stateEntity = getCached(key); if (stateEntity == null) { - stateEntity = retrieveValidEntity(refid.getId()); + stateEntity = resolve(refid.getId()); putCache(key, stateEntity); } @@ -834,7 +835,7 @@ public abstract class EntityStateJob extends EntityJob { getUser(), c); query.execute(getTransaction().getAccess()); - result = retrieveValidEntity(c.get(0).getId()); + result = resolve(c.get(0).getId()); putCache(key, result); return result; } @@ -852,6 +853,11 @@ public abstract class EntityStateJob extends EntityJob { if (value instanceof DeleteEntity) { throw new RuntimeException("Delete entity in cache. This is an implementation error."); } + if (value instanceof LazyEntityResolver) { + // resolve immediately, otherwise the access might be released when + // the object is being resolved. + ((LazyEntityResolver) value).resolveAll(); + } id_in_cache.add(value.getId()); cache.put(key, value); } diff --git a/src/main/java/org/caosdb/server/jobs/core/Inheritance.java b/src/main/java/org/caosdb/server/jobs/core/Inheritance.java index a1bd800c7ca40b28d7b9ff27dd8f828ed112891f..7bcda3b96cd64bf233444e429b72bb74ca69333d 100644 --- a/src/main/java/org/caosdb/server/jobs/core/Inheritance.java +++ b/src/main/java/org/caosdb/server/jobs/core/Inheritance.java @@ -27,12 +27,10 @@ package org.caosdb.server.jobs.core; import java.util.ArrayList; import java.util.List; import org.caosdb.api.entity.v1.MessageCode; -import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransaction; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.InsertEntity; import org.caosdb.server.entity.Message; import org.caosdb.server.entity.Message.MessageType; -import org.caosdb.server.entity.RetrieveEntity; import org.caosdb.server.entity.StatementStatus; import org.caosdb.server.entity.UpdateEntity; import org.caosdb.server.entity.wrapper.Property; @@ -88,12 +86,7 @@ public class Inheritance extends EntityJob { runJobFromSchedule(getEntity(), CheckParValid.class); // try to get the parent entity from the current transaction container - EntityInterface foreign = getEntityByName(parent.getName()); - if (foreign == null) { - // was not in container -> retrieve from database. - execute(new RetrieveFullEntityTransaction(parent)); - foreign = parent; - } + EntityInterface foreign = resolve(parent); collectInheritedProperties(transfer, foreign, inheritance); } catch (final IllegalArgumentException e) { @@ -136,26 +129,24 @@ public class Inheritance extends EntityJob { break propertyLoop; } - EntityInterface validProperty = new RetrieveEntity(property.getId()); + EntityInterface abstractProperty = null; if (getEntity().hasParents()) { outer: for (EntityInterface par : getEntity().getParents()) { - if (!par.hasProperties()) { - par = resolve(par); - } + par = resolve(par); for (final EntityInterface prop : par.getProperties()) { - if (validProperty.hasId() && validProperty.getId().equals(prop.getId())) { - validProperty = prop; + if ((property.hasId() && property.getId().equals(prop.getId())) + || property.hasName() && property.getName().equals(prop.getName())) { + abstractProperty = prop; break outer; } } } - } else { - execute(new RetrieveFullEntityTransaction(validProperty)); } - if (validProperty.getEntityStatus() == EntityStatus.VALID) { - collectInheritedProperties(transfer, validProperty, inheritance); + if (abstractProperty == null) { + abstractProperty = resolve(property); } + collectInheritedProperties(transfer, abstractProperty, inheritance); } catch (final IllegalArgumentException e) { property.addWarning(ILLEGAL_INHERITANCE_MODE); break propertyLoop; diff --git a/src/main/java/org/caosdb/server/jobs/core/NoCache.java b/src/main/java/org/caosdb/server/jobs/core/NoCache.java index e408330ee2639d1c5d7dc5f145848e292daa9b3b..6ad38f49268fae7d38612cbf552b7c8cd2d68b85 100644 --- a/src/main/java/org/caosdb/server/jobs/core/NoCache.java +++ b/src/main/java/org/caosdb/server/jobs/core/NoCache.java @@ -37,6 +37,6 @@ public class NoCache extends FlagJob { @Override protected void job(final String value) { - getTransaction().getAccess().setUseCache(Boolean.valueOf(value)); + getTransaction().setUseCache(Boolean.valueOf(value)); } } diff --git a/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java b/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java index cbcf738ee99716f58e2ca9a9526497e7b9113029..1fdd59e2327425b56b02d478eb1b31f4c135ce5b 100644 --- a/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java +++ b/src/main/java/org/caosdb/server/jobs/core/ProcessNameProperties.java @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; +import org.caosdb.server.database.exceptions.EntityDoesNotExistException; import org.caosdb.server.datatype.AbstractDatatype; import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; @@ -142,12 +143,13 @@ public class ProcessNameProperties extends EntityJob { } return ret; } else if (prop.hasId()) { - EntityInterface propertyEntity = getEntityById(prop.getId()); - if (propertyEntity == null) { - propertyEntity = retrieveValidEntity(prop.getId()); - } - if (propertyEntity != null) { - return getNearestValidParents(propertyEntity); + try { + EntityInterface propertyEntity = resolve(prop.getId()); + if (propertyEntity != null) { + return getNearestValidParents(propertyEntity); + } + } catch (EntityDoesNotExistException e) { + // return null } return null; } else { diff --git a/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java b/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java index 5ab722c7176e89485e2bd40dfd515a77bc09e38b..d1ab07b7bf5edb967abda9d23bb9828c0acfd69e 100644 --- a/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java +++ b/src/main/java/org/caosdb/server/jobs/core/ResolveNames.java @@ -25,6 +25,7 @@ package org.caosdb.server.jobs.core; import java.util.ArrayList; import java.util.List; import org.caosdb.server.database.backend.transaction.GetIDByName; +import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity; import org.caosdb.server.database.exceptions.EntityDoesNotExistException; import org.caosdb.server.entity.Entity; import org.caosdb.server.entity.EntityID; @@ -45,6 +46,20 @@ public class ResolveNames extends ContainerJob { public void resolve(final TransactionContainer container) { final ArrayList<Entity> add = new ArrayList<Entity>(); for (final EntityInterface e : container) { + if (!e.hasId() && e.hasName() && getTransaction().matchIdPattern(e.getName())) { + try { + EntityInterface valid = + execute( + new RetrieveSparseEntity( + new EntityID(e.getName()), + e.hasVersion() ? e.getVersion().getId() : null)) + .getEntity(); + e.setId(valid.getId()); + } catch (final EntityDoesNotExistException exc) { + // definitely not an id. + } + } + if (e.hasName() && !e.hasId()) { try { final List<EntityID> c = execute(new GetIDByName(e.getName(), false)).getList(); diff --git a/src/main/java/org/caosdb/server/jobs/core/UniqueName.java b/src/main/java/org/caosdb/server/jobs/core/UniqueName.java index 86e6c37e35ec91db647e14e30896abb6b884555b..079afdd9a922fa5758e5f4eb6bec80538338db21 100644 --- a/src/main/java/org/caosdb/server/jobs/core/UniqueName.java +++ b/src/main/java/org/caosdb/server/jobs/core/UniqueName.java @@ -40,7 +40,7 @@ public class UniqueName extends FlagJob { // check against data base try { - final EntityID foreign = retrieveValidIDByName(entity.getName()); + final EntityID foreign = retrieveValidIDByName(entity.getName(), null); if (entity.hasId() && !foreign.equals(entity.getId())) { throw new EntityWasNotUniqueException(); } diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java index ad3fb778c67c1390973fab1d8ed6391a0f5b7317..038e4d1895c3025759a8d259f27bcd246ac4f683 100644 --- a/src/main/java/org/caosdb/server/query/Query.java +++ b/src/main/java/org/caosdb/server/query/Query.java @@ -3,8 +3,8 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * Copyright (C) 2019-2021 IndiScale GmbH <info@indiscale.com> - * Copyright (C) 2019-2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2019-2023 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2019-2023 Timm Fitschen <t.fitschen@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -73,7 +73,6 @@ import org.caosdb.server.query.CQLParser.CqContext; import org.caosdb.server.query.CQLParsingErrorListener.ParsingError; import org.caosdb.server.transaction.TransactionInterface; import org.caosdb.server.transaction.WriteTransaction; -import org.caosdb.server.utils.ResultSetIterator; import org.jdom2.Element; import org.slf4j.Logger; @@ -218,22 +217,22 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac /** A data class for storing triplets of (Entity ID, version hash, ACL string) */ public static class IdVersionAclTriplet { - public IdVersionAclTriplet(final Integer id, final String version, final String acl) { + public IdVersionAclTriplet(final String id, final String version, final String acl) { this.id = id; this.version = version; this.acl = acl; } - public Integer id; + public String id; public String version; public String acl; @Override public String toString() { if (version == null) { - return Integer.toString(id); + return id; } - return Integer.toString(id) + "@" + version; + return id + "@" + version; } @Override @@ -256,6 +255,14 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac public int hashCode() { return toString().hashCode(); } + + public boolean isInternal() { + try { + return Integer.parseInt(id) < 101; + } catch (NumberFormatException e) { + return false; + } + } } private final boolean filterEntitiesWithoutRetrievePermisions = @@ -480,7 +487,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac + "` AS r ON (r.id=q.id);"); rs = stmt.executeQuery(); while (rs.next()) { - ret.put(new EntityID(rs.getInt("id")), rs.getString("definition")); + ret.put(new EntityID(rs.getString("id")), rs.getString("definition")); } return ret; } finally { @@ -652,9 +659,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac private String generateSelectStatementForResultSet( final String resultSetTableName, final boolean versioned) { if (resultSetTableName.equals("entity_ids")) { - // TODO remove "DOMAIN" final String baseStatement = - "SELECT entities.id AS internal_id, (SELECT id FROM entity_ids WHERE internal_id = entities.id) as id, entity_acl.acl FROM entities INNER JOIN entity_acl ON entity_acl.id=entities.acl WHERE entities.role!='DOMAIN'"; + "SELECT entities.id AS internal_id, (SELECT id FROM entity_ids WHERE internal_id = entities.id) as id, entity_acl.acl FROM entities INNER JOIN entity_acl ON entity_acl.id=entities.acl"; if (!versioned) { return baseStatement + ";"; } @@ -667,7 +673,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac return (" SELECT (SELECT id FROM entity_ids WHERE internal_id = tmp.id) AS id, entity_acl.acl FROM " + " (SELECT results.id AS id, entities.acl AS acl_id FROM `" + resultSetTableName - + "` AS results JOIN entities ON results.id=entities.id WHERE entities.role!='DOMAIN') AS tmp" + + "` AS results JOIN entities ON results.id=entities.id) AS tmp" + " JOIN entity_acl ON entity_acl.id=tmp.acl_id") + ";"; } @@ -698,10 +704,14 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac finishResultSet = finish.executeQuery(); final List<IdVersionAclTriplet> rs = new LinkedList<>(); while (finishResultSet.next()) { + final String id = finishResultSet.getString("id"); + if (finishResultSet.wasNull()) { + continue; + } final String version = versioned ? finishResultSet.getString("version") : null; final String acl = finishResultSet.getString("acl"); - rs.add(new IdVersionAclTriplet(finishResultSet.getInt("id"), version, acl)); + rs.add(new IdVersionAclTriplet(id, version, acl)); } return rs; } catch (final SQLException e) { @@ -804,7 +814,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac final List<IdVersionAclTriplet> filtered = new ArrayList<>(); for (final IdVersionAclTriplet triplet : resultSet) { - if (triplet.id >= 100) { + if (!triplet.isInternal()) { filtered.add(triplet); } } @@ -914,11 +924,11 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac + "left join entity_acl on entity_n_acl.acl=entity_acl.id;"); final ResultSet entitiesRS = stmt.executeQuery(query); final ResultSetIterator entitiesWithACL = new ResultSetIterator(entitiesRS); - final List<Integer> toBeDeleted = collectIdsWithoutPermission(entitiesWithACL); + final List<String> toBeDeleted = collectIdsWithoutPermission(entitiesWithACL); try (final PreparedStatement pstmt = this.getConnection().prepareStatement("DELETE FROM `" + tabname + "` WHERE id = ?")) { - for (final Integer id : toBeDeleted) { - pstmt.setInt(1, id); + for (final String id : toBeDeleted) { + pstmt.setString(1, id); pstmt.execute(); } } @@ -937,8 +947,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac */ private List<IdVersionAclTriplet> filterEntitiesWithoutRetrievePermission( final List<IdVersionAclTriplet> resultSet) { - final List<Integer> toBeDeleted = collectIdsWithoutPermission(resultSet.iterator()); - final List<IdVersionAclTriplet> filtered = new ArrayList<>(); + final List<String> toBeDeleted = collectIdsWithoutPermission(resultSet.iterator()); + final List<IdVersionAclTriplet> filtered = new LinkedList<>(); for (final IdVersionAclTriplet triplet : resultSet) { if (-1 == toBeDeleted.indexOf(triplet.id)) { filtered.add(triplet); @@ -953,9 +963,9 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac * triplets. * @return compiled list */ - private List<Integer> collectIdsWithoutPermission(Iterator<IdVersionAclTriplet> entityIterator) { - final HashMap<String, Boolean> acl_cache = new HashMap<String, Boolean>(); - final List<Integer> toBeDeleted = new LinkedList<Integer>(); + private List<String> collectIdsWithoutPermission(Iterator<IdVersionAclTriplet> entityIterator) { + final Map<String, Boolean> acl_cache = new HashMap<>(); + final List<String> toBeDeleted = new LinkedList<>(); while (entityIterator.hasNext()) { final long t1 = System.currentTimeMillis(); diff --git a/src/main/java/org/caosdb/server/utils/ResultSetIterator.java b/src/main/java/org/caosdb/server/query/ResultSetIterator.java similarity index 95% rename from src/main/java/org/caosdb/server/utils/ResultSetIterator.java rename to src/main/java/org/caosdb/server/query/ResultSetIterator.java index 71429f1a704299555ab1d86be0695e3104be828d..27c5e9226ac153bc65e2a42b15d3539f61526c89 100644 --- a/src/main/java/org/caosdb/server/utils/ResultSetIterator.java +++ b/src/main/java/org/caosdb/server/query/ResultSetIterator.java @@ -1,4 +1,4 @@ -package org.caosdb.server.utils; +package org.caosdb.server.query; import static org.caosdb.server.database.backend.implementation.MySQL.DatabaseUtils.bytes2UTF8; @@ -50,7 +50,7 @@ public class ResultSetIterator implements Iterator<IdVersionAclTriplet> { throw new NoSuchElementException(); } try { - final Integer id = resultSet.getInt("id"); + final String id = resultSet.getString("id"); final String acl_str = bytes2UTF8(resultSet.getBytes("ACL")); return new IdVersionAclTriplet(id, "", acl_str); } catch (SQLException e) { diff --git a/src/main/java/org/caosdb/server/resource/UserResource.java b/src/main/java/org/caosdb/server/resource/UserResource.java index de07331e9637549285d71ca2fd910916cd13316a..362e5eb661cd05ef2098aad5baa1604f8cd5dc09 100644 --- a/src/main/java/org/caosdb/server/resource/UserResource.java +++ b/src/main/java/org/caosdb/server/resource/UserResource.java @@ -104,12 +104,12 @@ public class UserResource extends AbstractCaosDBServerResource { form.getFirstValue("status") != null ? UserStatus.valueOf(form.getFirstValue("status").toUpperCase()) : null; - Integer userEntity = null; + String userEntity = null; if (form.getFirst("entity") != null) { if (form.getFirstValue("entity").isEmpty()) { - userEntity = 0; + userEntity = ""; } else { - userEntity = Integer.parseInt(form.getFirstValue("entity")); + userEntity = form.getFirstValue("entity"); } } @@ -150,9 +150,9 @@ public class UserResource extends AbstractCaosDBServerResource { "status", CaosDBServer.getServerProperty(ServerProperties.KEY_NEW_USER_DEFAULT_ACTIVITY)) .toUpperCase()); - Integer userEntity = null; + String userEntity = null; if (form.getFirst("entity") != null) { - userEntity = Integer.parseInt(form.getFirstValue("entity")); + userEntity = form.getFirstValue("entity"); } final InsertUserTransaction t = diff --git a/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java index 4cd7b2fcbd4ae9e9dd3d047555194172c4224d38..c920d8c92ce48258822d3ac1c6eed913fbbe84d7 100644 --- a/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java +++ b/src/main/java/org/caosdb/server/resource/transaction/EntityResource.java @@ -67,18 +67,14 @@ public class EntityResource extends RetrieveEntityResource { for (final String item : getRequestedItems()) { final String[] elem = item.split("@", 1); - Integer id = null; + String id = null; String version = null; - try { - id = Integer.parseInt(elem[0]); - } catch (final NumberFormatException e) { - // pass - } + id = elem[0]; if (elem.length > 1) { version = elem[1]; } - if (id != null && id > 0) { + if (id != null) { container.add(new DeleteEntity(new EntityID(id), version)); } } diff --git a/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java b/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java index 6527376d71ba31718394f887b7335615d80db5c6..8f2809b27e420da7e014088a15a07d7b5405b098 100644 --- a/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java +++ b/src/main/java/org/caosdb/server/resource/transaction/RetrieveEntityResource.java @@ -26,7 +26,6 @@ import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import org.caosdb.server.CaosDBException; import org.caosdb.server.database.backend.implementation.MySQL.ConnectionException; -import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.container.RetrieveContainer; import org.caosdb.server.resource.AbstractCaosDBServerResource; import org.caosdb.server.transaction.Retrieve; @@ -51,23 +50,14 @@ public abstract class RetrieveEntityResource extends AbstractCaosDBServerResourc for (final String item : getRequestedItems()) { final String[] elem = item.split("@", 2); - Integer id = null; - String name = null; + String id = null; String version = null; - try { - id = Integer.parseInt(elem[0]); - } catch (final NumberFormatException e) { - name = elem[0]; - } + id = elem[0]; if (elem.length > 1) { version = elem[1]; } - if (id != null) { - container.add(new EntityID(id), version); - } else { - container.add(name); - } + container.add(null, id, version); } } diff --git a/src/main/java/org/caosdb/server/transaction/EntityTransactionInterface.java b/src/main/java/org/caosdb/server/transaction/EntityTransactionInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..dc98f826bff2c3ebed809f45b1f05a197e61b9a7 --- /dev/null +++ b/src/main/java/org/caosdb/server/transaction/EntityTransactionInterface.java @@ -0,0 +1,12 @@ +package org.caosdb.server.transaction; + +import org.caosdb.server.entity.EntityID; + +public interface EntityTransactionInterface extends TransactionInterface { + + public boolean matchIdPattern(String id); + + public default boolean matchIdPattern(EntityID id) { + return id != null && matchIdPattern(id.toString()); + } +} diff --git a/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java b/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java index f3f4c7f5fd583ff0ff16d4fd1ce583394258f35b..3174dabf4e3d6a581f27aaf59cb8ffd866401bf5 100644 --- a/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java @@ -50,7 +50,7 @@ public class InsertUserTransaction extends AccessControlTransaction { final String password, final String email, final UserStatus status, - final Integer entity) { + final String entity) { this(new ProtoUser(), password); this.user.realm = UserSources.getInternalRealm().getName(); this.user.name = username; diff --git a/src/main/java/org/caosdb/server/transaction/Retrieve.java b/src/main/java/org/caosdb/server/transaction/Retrieve.java index 643c1201b530af9821c9a5c1a7b62f7c5d04cf52..4fc4fbc2c534aba2d24793d1efd3cbc6d1512914 100644 --- a/src/main/java/org/caosdb/server/transaction/Retrieve.java +++ b/src/main/java/org/caosdb/server/transaction/Retrieve.java @@ -115,6 +115,21 @@ public class Retrieve extends Transaction<RetrieveContainer> { private void retrieveFullEntities(final RetrieveContainer container, final Access access) throws Exception { execute(new RetrieveFullEntityTransaction(container), access); + for (EntityInterface e : container) { + if (e.getEntityStatus() == EntityStatus.NONEXISTENT + && e.hasId() + && e.hasName() + && e.getName().equals(e.getId().toString())) { + // remove duplicates by name + for (EntityInterface o : container) { + if (o.getEntityStatus() == EntityStatus.VALID + && o.hasName() + && e.getName().equalsIgnoreCase(o.getName())) { + e.setEntityStatus(EntityStatus.IGNORE); + } + } + } + } } @Override diff --git a/src/main/java/org/caosdb/server/transaction/RetrieveACL.java b/src/main/java/org/caosdb/server/transaction/RetrieveACL.java index ac0a2896451a43ca10985bd38787ad4f847a05cc..b5a4a489c60269dbae906bba1942f8e9525eb710 100644 --- a/src/main/java/org/caosdb/server/transaction/RetrieveACL.java +++ b/src/main/java/org/caosdb/server/transaction/RetrieveACL.java @@ -40,7 +40,7 @@ public class RetrieveACL extends Transaction<TransactionContainer> { new TransactionContainer( SecurityUtils.getSubject(), System.currentTimeMillis(), UUID.randomUUID().toString())); for (String strId : idList) { - getContainer().add(new RetrieveEntity(new EntityID(Integer.parseInt(strId)))); + getContainer().add(new RetrieveEntity(new EntityID(strId))); } } diff --git a/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java b/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java index eb24fb24db4f1b6a50a279cfcd9e158003a70948..72a1d61929e692e551a53013ac1aabb1a4f28f5a 100644 --- a/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/RetrieveUserTransaction.java @@ -77,7 +77,7 @@ public class RetrieveUserTransaction extends AccessControlTransaction { ret.setAttribute("email", user.email); } if (user.entity != null) { - ret.setAttribute("entity", Integer.toString(user.entity)); + ret.setAttribute("entity", user.entity); } if (user.status != null) { ret.setAttribute("status", user.status.toString()); diff --git a/src/main/java/org/caosdb/server/transaction/Transaction.java b/src/main/java/org/caosdb/server/transaction/Transaction.java index 5fc06f5ec82066d3515cbf524e64beb001ba0fcd..8474125d3c83d6445bb44c9d8ef0ff20759d20b7 100644 --- a/src/main/java/org/caosdb/server/transaction/Transaction.java +++ b/src/main/java/org/caosdb/server/transaction/Transaction.java @@ -21,8 +21,12 @@ */ package org.caosdb.server.transaction; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import org.apache.shiro.subject.Subject; import org.caosdb.datetime.UTCDateTime; import org.caosdb.server.accessControl.Principal; @@ -31,6 +35,7 @@ import org.caosdb.server.database.access.Access; import org.caosdb.server.database.backend.transaction.InsertTransactionHistory; import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.database.misc.TransactionBenchmark; +import org.caosdb.server.entity.EntityIdRegistry; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.Message; import org.caosdb.server.entity.container.TransactionContainer; @@ -47,9 +52,73 @@ import org.caosdb.server.permissions.EntityACL; import org.caosdb.server.utils.AbstractObservable; import org.caosdb.server.utils.Info; import org.caosdb.server.utils.Observer; +import org.caosdb.server.utils.UseCacheResource; +import org.caosdb.server.utils.UseCacheResourceDelegate; + +@SuppressWarnings("rawtypes") +class NoOpCache implements Map { + + @Override + public int size() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isEmpty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public Object get(Object key) { + return null; + } + + @Override + public Object put(Object key, Object value) { + return null; + } + + @Override + public Object remove(Object key) { + return null; + } + + @Override + public void putAll(Map m) {} + + @Override + public void clear() {} + + @Override + public Set keySet() { + return Collections.EMPTY_SET; + } + + @Override + public Collection values() { + return Collections.EMPTY_LIST; + } + + @Override + public Set entrySet() { + return Collections.EMPTY_SET; + } +} public abstract class Transaction<C extends TransactionContainer> extends AbstractObservable - implements TransactionInterface { + implements EntityTransactionInterface, UseCacheResource { @Override public TransactionBenchmark getTransactionBenchmark() { @@ -59,6 +128,8 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra private static final DatabaseAccessManager monitor = DatabaseAccessManager.getInstance(); public static final String CLEAN_UP = "TransactionCleanUp"; + + protected EntityIdRegistry idRegistry = null; private final C container; private Access access = null; private final Schedule schedule = new Schedule(); @@ -304,27 +375,50 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra /** @see {@link #execute()} */ protected void commit() throws Exception {} - public boolean useCache() { - return getContainer().getFlags() != null - && !getContainer().getFlags().containsKey("disableCache"); - } - public final Access getAccess() { return this.access; } protected void setAccess(final Access a) { this.access = a; + if (access != null) { + this.access.setUseCacheResourceDelegate(useCacheResourceDelegate); + } } @SuppressWarnings("unchecked") - public <S, T> HashMap<S, T> getCache(final String name) { + public <S, T> Map<S, T> getCache(final String name) { + if (!useCache()) { + return NO_OP_CACHE; + } if (!this.caches.containsKey(name)) { this.caches.put(name, new HashMap<S, T>()); } return this.caches.get(name); } + private static final NoOpCache NO_OP_CACHE = new NoOpCache(); + @SuppressWarnings("rawtypes") - private final HashMap<String, HashMap> caches = new HashMap<>(); + private final Map<String, Map> caches = new HashMap<>(); + + private final UseCacheResource useCacheResourceDelegate = new UseCacheResourceDelegate(); + + @Override + public UseCacheResource getUseCacheResourceDelegate() { + return this.useCacheResourceDelegate.getUseCacheResourceDelegate(); + } + + @Override + public void setUseCacheResourceDelegate(UseCacheResource delegate) { + this.useCacheResourceDelegate.setUseCacheResourceDelegate(delegate); + } + + @Override + public boolean matchIdPattern(String id) { + if (this.idRegistry == null) { + this.idRegistry = new EntityIdRegistry(this); + } + return idRegistry.matchIdPattern(id); + } } diff --git a/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java b/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java index 6808968f20574242cfdaa9b87793d7a4ad4b6914..7730d82b2fc2fb7ff3d34430ea3d1b60ffb9c16e 100644 --- a/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/UpdateUserTransaction.java @@ -63,7 +63,7 @@ public class UpdateUserTransaction extends AccessControlTransaction { final String username, final UserStatus status, final String email, - final Integer entity, + final String entity, final String password) { this.user = new ProtoUser(); this.user.realm = @@ -177,7 +177,7 @@ public class UpdateUserTransaction extends AccessControlTransaction { ACMPermissions.PERMISSION_UPDATE_USER_ENTITY(this.user.realm, this.user.name)); isToBeUpdated = true; - if (this.user.entity.equals(0)) { + if (this.user.entity.isEmpty()) { // this means that the entity is to be reset. this.user.entity = null; } else { diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java index 87d299477119dcc20b6f730d1bb014b253a49497..9a355410c9c29429296d4329e697a2cbca1d5980 100644 --- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java @@ -74,7 +74,6 @@ public class WriteTransaction extends Transaction<WritableContainer> implements WriteTransactionInterface { private boolean noIdIsError = true; - private EntityIdRegistry idRegistry; public WriteTransaction(final WritableContainer container) { super(container); diff --git a/src/main/java/org/caosdb/server/utils/UseCacheResource.java b/src/main/java/org/caosdb/server/utils/UseCacheResource.java new file mode 100644 index 0000000000000000000000000000000000000000..2319601260a7116d4299f6823628ef2c4346875e --- /dev/null +++ b/src/main/java/org/caosdb/server/utils/UseCacheResource.java @@ -0,0 +1,16 @@ +package org.caosdb.server.utils; + +public interface UseCacheResource { + + public default boolean useCache() { + return getUseCacheResourceDelegate().useCache(); + } + + public default void setUseCache(boolean useCache) { + getUseCacheResourceDelegate().setUseCache(useCache); + } + + public void setUseCacheResourceDelegate(UseCacheResource delegate); + + public UseCacheResource getUseCacheResourceDelegate(); +} diff --git a/src/main/java/org/caosdb/server/utils/UseCacheResourceDelegate.java b/src/main/java/org/caosdb/server/utils/UseCacheResourceDelegate.java new file mode 100644 index 0000000000000000000000000000000000000000..81d862b07c9c6e1cf1309e085213fe9ffeb0b780 --- /dev/null +++ b/src/main/java/org/caosdb/server/utils/UseCacheResourceDelegate.java @@ -0,0 +1,42 @@ +package org.caosdb.server.utils; + +import org.caosdb.server.CaosDBServer; + +public class UseCacheResourceDelegate implements UseCacheResource { + private boolean useCache = CaosDBServer.useCache(); + private UseCacheResource delegate = null; + + @Override + public void setUseCache(boolean useCache) { + if (this.delegate != null) { + this.delegate.setUseCache(useCache); + } else { + this.useCache = useCache; + } + } + + @Override + public boolean useCache() { + if (delegate != null) { + return delegate.useCache(); + } + return CaosDBServer.useCache() && useCache; + } + + @Override + public void setUseCacheResourceDelegate(UseCacheResource delegate) { + if (delegate == this) { + this.delegate = null; + } else { + this.delegate = delegate; + } + } + + @Override + public UseCacheResource getUseCacheResourceDelegate() { + if (this.delegate != null) { + return this.delegate; + } + return this; + } +} diff --git a/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java b/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java index 94febb12a91bc4db8f8878bb5a670f856b17edf5..648880fcd018d36bc73f2b2e8d1b4ea2c41e364d 100644 --- a/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java +++ b/src/test/java/org/caosdb/server/database/backend/implementation/MySQL/InsertTest.java @@ -50,7 +50,7 @@ public class InsertTest { private Deque<EntityID> registerReplacementIds(int count) { Deque<EntityID> replacementIds = new ArrayDeque<>(); for (int i = 1; i < count + 1; i++) { - replacementIds.add(new EntityID(-i)); + replacementIds.add(new EntityID(Integer.toString(-i))); } return replacementIds; } @@ -63,70 +63,70 @@ public class InsertTest { @Test public void testTransformation1() throws Exception { final Entity r = new InsertEntity("Test", Role.Record); - final Property p1 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p1 = new Property(new RetrieveEntity(new EntityID("1"))); p1.setRole("Property"); p1.setValue(new GenericValue("V1")); p1.setDatatype("TEXT"); p1.setStatementStatus(StatementStatus.FIX); r.addProperty(p1); - final Property p2 = new Property(new RetrieveEntity(new EntityID(2))); + final Property p2 = new Property(new RetrieveEntity(new EntityID("2"))); p2.setRole("Property"); p2.setValue(new GenericValue("V2")); p2.setDatatype("TEXT"); p2.setStatementStatus(StatementStatus.RECOMMENDED); r.addProperty(p2); - final Property p3 = new Property(new RetrieveEntity(new EntityID(3))); + final Property p3 = new Property(new RetrieveEntity(new EntityID("3"))); p3.setRole("Property"); p3.setValue(new GenericValue("V3")); p3.setDatatype("TEXT"); p3.setStatementStatus(StatementStatus.OBLIGATORY); p2.addProperty(p3); - final Property p4 = new Property(new RetrieveEntity(new EntityID(4))); + final Property p4 = new Property(new RetrieveEntity(new EntityID("4"))); p4.setRole("Property"); p4.setValue(new GenericValue("V4")); p4.setDatatype("TEXT"); p4.setStatementStatus(StatementStatus.OBLIGATORY); r.addProperty(p4); - final Property p5 = new Property(new RetrieveEntity(new EntityID(5))); + final Property p5 = new Property(new RetrieveEntity(new EntityID("5"))); p5.setRole("Property"); p5.setValue(new GenericValue("V5")); p5.setDatatype("TEXT"); p5.setStatementStatus(StatementStatus.OBLIGATORY); p4.addProperty(p5); - final Property p6 = new Property(new RetrieveEntity(new EntityID(6))); + final Property p6 = new Property(new RetrieveEntity(new EntityID("6"))); p6.setRole("Property"); p6.setValue(new GenericValue("V6")); p6.setDatatype("TEXT"); p6.setStatementStatus(StatementStatus.OBLIGATORY); p5.addProperty(p6); - final Property p7 = new Property(new RetrieveEntity(new EntityID(7))); + final Property p7 = new Property(new RetrieveEntity(new EntityID("7"))); p7.setRole("Property"); p7.setValue(new GenericValue("V7")); p7.setDatatype("TEXT"); p7.setStatementStatus(StatementStatus.OBLIGATORY); r.addProperty(p7); - final Property p8 = new Property(new RetrieveEntity(new EntityID(8))); + final Property p8 = new Property(new RetrieveEntity(new EntityID("8"))); p8.setRole("Property"); p8.setValue(new GenericValue("V8")); p8.setDatatype("TEXT"); p8.setStatementStatus(StatementStatus.OBLIGATORY); p7.addProperty(p8); - final Property p9 = new Property(new RetrieveEntity(new EntityID(9))); + final Property p9 = new Property(new RetrieveEntity(new EntityID("9"))); p9.setRole("Property"); p9.setValue(new GenericValue("V9")); p9.setDatatype("TEXT"); p9.setStatementStatus(StatementStatus.OBLIGATORY); p8.addProperty(p9); - final Property p10 = new Property(new RetrieveEntity(new EntityID(10))); + final Property p10 = new Property(new RetrieveEntity(new EntityID("10"))); p10.setRole("Property"); p10.setValue(new GenericValue("V10")); p10.setDatatype("TEXT"); @@ -171,29 +171,29 @@ public class InsertTest { assertEquals("V9", ((SingleValue) stage1Inserts.get(6).getValue()).toDatabaseString()); assertEquals(6, stage2Inserts.size()); - assertEquals(new EntityID(3), stage2Inserts.get(0).getId()); + assertEquals(new EntityID("3"), stage2Inserts.get(0).getId()); assertEquals("V3", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString()); - assertEquals(new EntityID(2), stage2Inserts.get(0).getDomain()); + assertEquals(new EntityID("2"), stage2Inserts.get(0).getDomain()); - assertEquals(new EntityID(5), stage2Inserts.get(1).getId()); + assertEquals(new EntityID("5"), stage2Inserts.get(1).getId()); assertEquals("V5", ((SingleValue) stage2Inserts.get(1).getValue()).toDatabaseString()); - assertEquals(new EntityID(4), stage2Inserts.get(1).getDomain()); + assertEquals(new EntityID("4"), stage2Inserts.get(1).getDomain()); - assertEquals(new EntityID(6), stage2Inserts.get(2).getId()); + assertEquals(new EntityID("6"), stage2Inserts.get(2).getId()); assertEquals("V6", ((SingleValue) stage2Inserts.get(2).getValue()).toDatabaseString()); - assertEquals(new EntityID(-1), stage2Inserts.get(2).getDomain()); + assertEquals(new EntityID("-1"), stage2Inserts.get(2).getDomain()); - assertEquals(new EntityID(8), stage2Inserts.get(3).getId()); + assertEquals(new EntityID("8"), stage2Inserts.get(3).getId()); assertEquals("V8", ((SingleValue) stage2Inserts.get(3).getValue()).toDatabaseString()); - assertEquals(new EntityID(7), stage2Inserts.get(3).getDomain()); + assertEquals(new EntityID("7"), stage2Inserts.get(3).getDomain()); - assertEquals(new EntityID(9), stage2Inserts.get(4).getId()); + assertEquals(new EntityID("9"), stage2Inserts.get(4).getId()); assertEquals("V9", ((SingleValue) stage2Inserts.get(4).getValue()).toDatabaseString()); - assertEquals(new EntityID(-2), stage2Inserts.get(4).getDomain()); + assertEquals(new EntityID("-2"), stage2Inserts.get(4).getDomain()); - assertEquals(new EntityID(10), stage2Inserts.get(5).getId()); + assertEquals(new EntityID("10"), stage2Inserts.get(5).getId()); assertEquals("V10", ((SingleValue) stage2Inserts.get(5).getValue()).toDatabaseString()); - assertEquals(new EntityID(-3), stage2Inserts.get(5).getDomain()); + assertEquals(new EntityID("-3"), stage2Inserts.get(5).getDomain()); } /** @@ -205,21 +205,21 @@ public class InsertTest { @Test public void testTransformation2() throws Exception { final Entity r = new InsertEntity("Test", Role.Record); - final Property p1 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p1 = new Property(new RetrieveEntity(new EntityID("1"))); p1.setRole("Property"); p1.setValue(new GenericValue("V1-1")); p1.setDatatype("TEXT"); p1.setStatementStatus(StatementStatus.FIX); r.addProperty(p1); - final Property p2 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p2 = new Property(new RetrieveEntity(new EntityID("1"))); p2.setRole("Property"); p2.setValue(new GenericValue("V1-2")); p2.setDatatype("TEXT"); p2.setStatementStatus(StatementStatus.FIX); r.addProperty(p2); - final Property subp = new Property(new RetrieveEntity(new EntityID(2))); + final Property subp = new Property(new RetrieveEntity(new EntityID("2"))); subp.setRole("Property"); subp.setValue(new GenericValue("V2")); subp.setDatatype("TEXT"); @@ -235,21 +235,21 @@ public class InsertTest { assertEquals(3, stage1Inserts.size()); assertFalse(stage1Inserts.get(0) instanceof Replacement); - assertEquals(new EntityID(1), stage1Inserts.get(0).getId()); + assertEquals(new EntityID("1"), stage1Inserts.get(0).getId()); assertEquals("V1-1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString()); assertTrue(stage1Inserts.get(1) instanceof Replacement); assertEquals("V1-2", ((SingleValue) stage1Inserts.get(1).getValue()).toDatabaseString()); - assertEquals(new EntityID(-1), stage1Inserts.get(1).getId()); + assertEquals(new EntityID("-1"), stage1Inserts.get(1).getId()); assertFalse(stage1Inserts.get(2) instanceof Replacement); - assertEquals(new EntityID(-1), stage1Inserts.get(2).getId()); + assertEquals(new EntityID("-1"), stage1Inserts.get(2).getId()); assertEquals("1", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString()); assertEquals(1, stage2Inserts.size()); assertFalse(stage2Inserts.get(0) instanceof Replacement); - assertEquals(new EntityID(2), stage2Inserts.get(0).getId()); + assertEquals(new EntityID("2"), stage2Inserts.get(0).getId()); assertEquals("V2", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString()); } @@ -262,25 +262,25 @@ public class InsertTest { @Test public void testTransformation3() throws Exception { final Entity r = new InsertEntity("Test", Role.Record); - final Property p1 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p1 = new Property(new RetrieveEntity(new EntityID("1"))); p1.setRole("Property"); p1.setDatatype("TEXT"); p1.setStatementStatus(StatementStatus.FIX); r.addProperty(p1); - final Property p2 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p2 = new Property(new RetrieveEntity(new EntityID("1"))); p2.setRole("Property"); p2.setDatatype("TEXT"); p2.setStatementStatus(StatementStatus.FIX); r.addProperty(p2); - final Property p3 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p3 = new Property(new RetrieveEntity(new EntityID("1"))); p3.setRole("Property"); p3.setDatatype("TEXT"); p3.setStatementStatus(StatementStatus.FIX); r.addProperty(p3); - final Property sub1 = new Property(new RetrieveEntity(new EntityID(2))); + final Property sub1 = new Property(new RetrieveEntity(new EntityID("2"))); sub1.setRole("Property"); sub1.setDatatype("TEXT"); sub1.setValue(new GenericValue("V1")); @@ -295,25 +295,25 @@ public class InsertTest { assertEquals(4, stage1Inserts.size()); assertTrue(stage1Inserts.get(0) instanceof Replacement); - assertEquals(new EntityID(-1), stage1Inserts.get(0).getId()); + assertEquals(new EntityID("-1"), stage1Inserts.get(0).getId()); assertEquals(null, stage1Inserts.get(0).getValue()); assertFalse(stage1Inserts.get(1) instanceof Replacement); - assertEquals(new EntityID(-1), stage1Inserts.get(1).getId()); + assertEquals(new EntityID("-1"), stage1Inserts.get(1).getId()); assertEquals("1", ((ReferenceValue) stage1Inserts.get(1).getValue()).getId().toString()); assertFalse(stage1Inserts.get(2) instanceof Replacement); - assertEquals(new EntityID(1), stage1Inserts.get(2).getId()); + assertEquals(new EntityID("1"), stage1Inserts.get(2).getId()); assertEquals(null, stage1Inserts.get(2).getValue()); assertFalse(stage1Inserts.get(3) instanceof Replacement); - assertEquals(new EntityID(1), stage1Inserts.get(3).getId()); + assertEquals(new EntityID("1"), stage1Inserts.get(3).getId()); assertEquals(null, stage1Inserts.get(3).getValue()); assertEquals(1, stage2Inserts.size()); - assertEquals(new EntityID(2), stage2Inserts.get(0).getId()); + assertEquals(new EntityID("2"), stage2Inserts.get(0).getId()); assertEquals("V1", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString()); - assertEquals(new EntityID(-1), stage2Inserts.get(0).getDomain()); + assertEquals(new EntityID("-1"), stage2Inserts.get(0).getDomain()); } /** @@ -325,14 +325,14 @@ public class InsertTest { public void testTransformation4() throws Exception { final Entity r = new InsertEntity("Test", Role.Record); - final Property p1 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p1 = new Property(new RetrieveEntity(new EntityID("1"))); p1.setRole("Property"); p1.setDatatype("TEXT"); p1.setValue(new GenericValue("V1")); p1.setStatementStatus(StatementStatus.FIX); r.addProperty(p1); - final Property p2 = new Property(new RetrieveEntity(new EntityID(2))); + final Property p2 = new Property(new RetrieveEntity(new EntityID("2"))); p2.setRole("Property"); p2.setDatatype("LIST<TEXT>"); p2.setStatementStatus(StatementStatus.FIX); @@ -343,7 +343,7 @@ public class InsertTest { p2.setValue(vals); r.addProperty(p2); - final Property p3 = new Property(new RetrieveEntity(new EntityID(3))); + final Property p3 = new Property(new RetrieveEntity(new EntityID("3"))); p3.setRole("Property"); p3.setDatatype("TEXT"); p3.setValue(new GenericValue("V3")); @@ -359,19 +359,19 @@ public class InsertTest { assertEquals(4, stage1Inserts.size()); assertFalse(stage1Inserts.get(0) instanceof Replacement); - assertEquals(new EntityID(1), stage1Inserts.get(0).getId()); + assertEquals(new EntityID("1"), stage1Inserts.get(0).getId()); assertEquals("V1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString()); assertTrue(stage1Inserts.get(1) instanceof Replacement); - assertEquals(new EntityID(-1), stage1Inserts.get(1).getId()); + assertEquals(new EntityID("-1"), stage1Inserts.get(1).getId()); assertTrue(stage1Inserts.get(1).getValue() instanceof CollectionValue); assertFalse(stage1Inserts.get(2) instanceof Replacement); - assertEquals(new EntityID(-1), stage1Inserts.get(2).getId()); + assertEquals(new EntityID("-1"), stage1Inserts.get(2).getId()); assertEquals("2", ((ReferenceValue) stage1Inserts.get(2).getValue()).getId().toString()); assertFalse(stage1Inserts.get(3) instanceof Replacement); - assertEquals(new EntityID(3), stage1Inserts.get(3).getId()); + assertEquals(new EntityID("3"), stage1Inserts.get(3).getId()); assertEquals("V3", ((SingleValue) stage1Inserts.get(3).getValue()).toDatabaseString()); assertEquals(0, stage2Inserts.size()); @@ -381,7 +381,7 @@ public class InsertTest { @Test public void testTransformation5() { final Entity r = new InsertEntity("Test", Role.RecordType); - final Property p1 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p1 = new Property(new RetrieveEntity(new EntityID("1"))); p1.setRole("Property"); p1.setDatatype("TEXT"); p1.setDescription("desc1"); @@ -391,7 +391,7 @@ public class InsertTest { p1.setStatementStatus(StatementStatus.RECOMMENDED); r.addProperty(p1); - final Property p2 = new Property(new RetrieveEntity(new EntityID(2))); + final Property p2 = new Property(new RetrieveEntity(new EntityID("2"))); p2.setRole("Property"); p2.setDatatype("TEXT"); p2.setDescription("desc2"); @@ -401,7 +401,7 @@ public class InsertTest { p2.setStatementStatus(StatementStatus.RECOMMENDED); r.addProperty(p2); - final Property p21 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p21 = new Property(new RetrieveEntity(new EntityID("1"))); p21.setRole("Property"); p21.setDatatype("TEXT"); p21.setDescription("desc21"); @@ -411,7 +411,7 @@ public class InsertTest { p21.setStatementStatus(StatementStatus.FIX); p2.addProperty(p21); - final Property p22 = new Property(new RetrieveEntity(new EntityID(2))); + final Property p22 = new Property(new RetrieveEntity(new EntityID("2"))); p22.setRole("Property"); p22.setDatatype("TEXT"); p22.setDescription("desc22"); @@ -421,7 +421,7 @@ public class InsertTest { p22.setStatementStatus(StatementStatus.FIX); p2.addProperty(p22); - final Property p3 = new Property(new RetrieveEntity(new EntityID(3))); + final Property p3 = new Property(new RetrieveEntity(new EntityID("3"))); p3.setRole("Property"); p3.setDatatype("TEXT"); p3.setDescription("desc3"); @@ -431,7 +431,7 @@ public class InsertTest { p3.setStatementStatus(StatementStatus.RECOMMENDED); r.addProperty(p3); - final Property p31 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p31 = new Property(new RetrieveEntity(new EntityID("1"))); p31.setRole("Property"); p31.setDatatype("TEXT"); p31.setDescription("desc31"); @@ -441,7 +441,7 @@ public class InsertTest { p31.setStatementStatus(StatementStatus.FIX); p3.addProperty(p31); - final Property p32 = new Property(new RetrieveEntity(new EntityID(2))); + final Property p32 = new Property(new RetrieveEntity(new EntityID("2"))); p32.setRole("Property"); p32.setDatatype("TEXT"); p32.setDescription("desc32"); @@ -451,7 +451,7 @@ public class InsertTest { p32.setStatementStatus(StatementStatus.FIX); p3.addProperty(p32); - final Property p321 = new Property(new RetrieveEntity(new EntityID(1))); + final Property p321 = new Property(new RetrieveEntity(new EntityID("1"))); p321.setRole("Property"); p321.setDatatype("TEXT"); p321.setDescription("desc321"); @@ -461,7 +461,7 @@ public class InsertTest { p321.setStatementStatus(StatementStatus.FIX); p32.addProperty(p321); - final Property p322 = new Property(new RetrieveEntity(new EntityID(2))); + final Property p322 = new Property(new RetrieveEntity(new EntityID("2"))); p322.setRole("Property"); p322.setDatatype("TEXT"); p322.setDescription("desc322"); @@ -471,7 +471,7 @@ public class InsertTest { p322.setStatementStatus(StatementStatus.FIX); p32.addProperty(p322); - final Property p323 = new Property(new RetrieveEntity(new EntityID(3))); + final Property p323 = new Property(new RetrieveEntity(new EntityID("3"))); p323.setRole("Property"); p323.setDatatype("TEXT"); p323.setDescription("desc323"); @@ -481,7 +481,7 @@ public class InsertTest { p323.setStatementStatus(StatementStatus.FIX); p32.addProperty(p323); - final Property p33 = new Property(new RetrieveEntity(new EntityID(3))); + final Property p33 = new Property(new RetrieveEntity(new EntityID("3"))); p33.setRole("Property"); p33.setDatatype("TEXT"); p33.setDescription("desc33"); diff --git a/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java b/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java index 72c84d1f7b262a854a257c8ae764d4e3da9b8e80..4ba5ce46023aa020b2939f1734e4cfe9ec65622d 100644 --- a/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java +++ b/src/test/java/org/caosdb/server/database/backend/transaction/RetrieveFullEntityTest.java @@ -43,14 +43,14 @@ public class RetrieveFullEntityTest { @Test public void testRetrieveSubEntities() { final RetrieveFullEntityTransaction r = - new RetrieveFullEntityTransaction(new EntityID(0)) { + new RetrieveFullEntityTransaction(new EntityID("0")) { /** Mock-up */ @Override public void retrieveFullEntity( final EntityInterface e, final List<Selection> selections) { // The id of the referenced window - assertEquals(new EntityID(1234), e.getId()); + assertEquals(new EntityID("1234"), e.getId()); // The level of selectors has been reduced by 1 assertEquals("description", selections.get(0).getSelector()); @@ -59,16 +59,16 @@ public class RetrieveFullEntityTest { }; }; - final Property window = new Property(new RetrieveEntity(new EntityID(2345))); + final Property window = new Property(new RetrieveEntity(new EntityID("2345"))); window.setName("Window"); window.setDatatype("Window"); - window.setValue(new ReferenceValue(1234)); + window.setValue(new ReferenceValue("1234")); - final Entity house = new RetrieveEntity(new EntityID(3456)); + final Entity house = new RetrieveEntity(new EntityID("3456")); house.addProperty(window); final ReferenceValue value = - (ReferenceValue) house.getProperties().getEntityById(new EntityID(2345)).getValue(); - assertEquals(new EntityID(1234), value.getId()); + (ReferenceValue) house.getProperties().getEntityById(new EntityID("2345")).getValue(); + assertEquals(new EntityID("1234"), value.getId()); assertNull(value.getEntity()); final List<Selection> selections = new ArrayList<>(); @@ -76,7 +76,7 @@ public class RetrieveFullEntityTest { r.retrieveSubEntities(house, selections); - assertEquals(new EntityID(1234), value.getId()); + assertEquals(new EntityID("1234"), value.getId()); assertNotNull(value.getEntity()); assertEquals("A heart-shaped window.", value.getEntity().getDescription()); } diff --git a/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java b/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java index a8ccdbdc9f7a9522020332e01cba96a1667d70b6..8220097ba2d4f814691bd493156b4abcbf2eb7b7 100644 --- a/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java +++ b/src/test/java/org/caosdb/server/entity/container/PropertyContainerTest.java @@ -48,7 +48,7 @@ public class PropertyContainerTest { @BeforeAll public static void setup() { - window = new RetrieveEntity(new EntityID(1234)); + window = new RetrieveEntity(new EntityID("1234")); windowHeight = new Property(new RetrieveEntity("window.height", Role.Property)); window.addProperty(windowHeight); windowHeight.setValue(new GenericValue("windowHeight")); @@ -59,7 +59,7 @@ public class PropertyContainerTest { houseHeight = new Property(new RetrieveEntity("height", Role.Property)); houseHeight.setValue(new GenericValue("houseHeight")); house.addProperty(houseHeight); - windowProperty = new Property(new RetrieveEntity(new EntityID(2345))); + windowProperty = new Property(new RetrieveEntity(new EntityID("2345"))); windowProperty.setName("window"); windowProperty.setValue(new ReferenceValue(window.getId())); house.addProperty(windowProperty); diff --git a/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java b/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java index a2c9676b9759fc55fb0d1e089808ab50d016288e..ab658722c77983d86d5611808adea8302b0933cc 100644 --- a/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java +++ b/src/test/java/org/caosdb/server/entity/xml/PropertyToElementStrategyTest.java @@ -66,7 +66,7 @@ public class PropertyToElementStrategyTest { @BeforeEach public void setup() { - window = new RetrieveEntity(new EntityID(1234), Role.Record); + window = new RetrieveEntity(new EntityID("1234"), Role.Record); windowHeight = new Property(new RetrieveEntity("height", Role.Property)); window.addProperty(windowHeight); windowHeight.setValue(new GenericValue("windowHeight")); @@ -77,7 +77,7 @@ public class PropertyToElementStrategyTest { houseHeight = new Property(new RetrieveEntity("height", Role.Property)); houseHeight.setValue(new GenericValue("houseHeight")); house.addProperty(houseHeight); - windowProperty = new Property(new RetrieveEntity(new EntityID(2345))); + windowProperty = new Property(new RetrieveEntity(new EntityID("2345"))); windowProperty.setName("window"); windowProperty.setDatatype("window"); windowProperty.setValue(new ReferenceValue(window.getId())); diff --git a/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java b/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java index d46c187324b76e179ef8d562cd5a150ab7968a45..b5bdb3802d4338dc093b385a54716dcbaf0df604 100644 --- a/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java +++ b/src/test/java/org/caosdb/server/grpc/CaosDBToGrpcConvertersTest.java @@ -74,7 +74,7 @@ public class CaosDBToGrpcConvertersTest { RetrieveEntity entity = new RetrieveEntity(); // must be printed - entity.setId(new EntityID(1234)); + entity.setId(new EntityID("1234")); entity.addInfo("info"); entity.addWarning(new Message("warning")); entity.addError(new Message("error")); @@ -136,7 +136,7 @@ public class CaosDBToGrpcConvertersTest { RetrieveEntity person1 = new RetrieveEntity(); person1.addProperty(fullName1); - ReferenceValue val1 = new ReferenceValue(new EntityID(1234)); + ReferenceValue val1 = new ReferenceValue(new EntityID("1234")); val1.setEntity(person1, false); col.add(val1); @@ -147,7 +147,7 @@ public class CaosDBToGrpcConvertersTest { RetrieveEntity person2 = new RetrieveEntity(); person2.addProperty(fullName2); - ReferenceValue val2 = new ReferenceValue(new EntityID(1234)); + ReferenceValue val2 = new ReferenceValue(new EntityID("1234")); val2.setEntity(person2, false); col.add(val2); p.setValue(col); diff --git a/src/test/java/org/caosdb/server/jobs/JobConfigTest.java b/src/test/java/org/caosdb/server/jobs/JobConfigTest.java index e176c2111189fb52ca9946e10ae5ec705549b6c8..1134a55c9d3c08a4981807f2cbb66bb7c174744c 100644 --- a/src/test/java/org/caosdb/server/jobs/JobConfigTest.java +++ b/src/test/java/org/caosdb/server/jobs/JobConfigTest.java @@ -26,7 +26,7 @@ public class JobConfigTest { final JobConfig jobConfig = JobConfig.getInstance(); assertEquals("Retrieve", jobConfig.getTransactionType(new RetrieveEntity("test"))); assertEquals("Insert", jobConfig.getTransactionType(new InsertEntity("test", Role.Record))); - assertEquals("Delete", jobConfig.getTransactionType(new DeleteEntity(new EntityID(1234)))); + assertEquals("Delete", jobConfig.getTransactionType(new DeleteEntity(new EntityID("1234")))); assertEquals("Update", jobConfig.getTransactionType(new UpdateEntity(new Element("Record")))); } } diff --git a/src/test/java/org/caosdb/server/transaction/RetrieveTest.java b/src/test/java/org/caosdb/server/transaction/RetrieveTest.java index a3ac40e1bf1e0fe6489a74f45d6c253b903b4478..00c23d2362495bd1c7a871de7bd84ddab2f0e1c2 100644 --- a/src/test/java/org/caosdb/server/transaction/RetrieveTest.java +++ b/src/test/java/org/caosdb/server/transaction/RetrieveTest.java @@ -62,7 +62,7 @@ public class RetrieveTest { public void testMissingRetrievePermission() { Subject subject = SecurityUtils.getSubject(); subject.login(AnonymousAuthenticationToken.getInstance()); - EntityInterface entity = new RetrieveEntity(new EntityID(1234)); + EntityInterface entity = new RetrieveEntity(new EntityID("1234")); EntityACLFactory fac = new EntityACLFactory(); fac.deny(AnonymousAuthenticationToken.PRINCIPAL, "RETRIEVE:ENTITY"); entity.setEntityACL(fac.create()); diff --git a/src/test/java/org/caosdb/server/transaction/UpdateTest.java b/src/test/java/org/caosdb/server/transaction/UpdateTest.java index a0891a3eb34e1759100c78916d0fb250de149ef8..fd064ba0882912a44f3282e9aa412b6a560287ca 100644 --- a/src/test/java/org/caosdb/server/transaction/UpdateTest.java +++ b/src/test/java/org/caosdb/server/transaction/UpdateTest.java @@ -75,11 +75,11 @@ public class UpdateTest { @Test public void testDeriveUpdate_SameProperty() throws NoSuchAlgorithmException, IOException, CaosDBException { - final Entity newEntity = new RetrieveEntity(new EntityID(1234)); - final Property newProperty = new Property(new RetrieveEntity(new EntityID(1))); + final Entity newEntity = new RetrieveEntity(new EntityID("1234")); + final Property newProperty = new Property(new RetrieveEntity(new EntityID("1"))); newEntity.addProperty(newProperty); - final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1))); - final Entity oldEntity = new RetrieveEntity(new EntityID(1234)); + final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1"))); + final Entity oldEntity = new RetrieveEntity(new EntityID("1234")); oldEntity.addProperty(oldProperty); new WriteTransaction(null).deriveUpdate(newEntity, oldEntity); @@ -89,13 +89,13 @@ public class UpdateTest { @Test public void testDeriveUpdate_AnotherProperty() throws NoSuchAlgorithmException, IOException, CaosDBException { - final Entity newEntity = new RetrieveEntity(new EntityID(1234)); - final Property newProperty = new Property(new RetrieveEntity(new EntityID(1))); - final Property newProperty2 = new Property(new RetrieveEntity(new EntityID(2))); + final Entity newEntity = new RetrieveEntity(new EntityID("1234")); + final Property newProperty = new Property(new RetrieveEntity(new EntityID("1"))); + final Property newProperty2 = new Property(new RetrieveEntity(new EntityID("2"))); newEntity.addProperty(newProperty); newEntity.addProperty(newProperty2); - final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1))); - final Entity oldEntity = new RetrieveEntity(new EntityID(1234)); + final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1"))); + final Entity oldEntity = new RetrieveEntity(new EntityID("1234")); oldEntity.addProperty(oldProperty); new WriteTransaction(null).deriveUpdate(newEntity, oldEntity); @@ -107,15 +107,15 @@ public class UpdateTest { @Test public void testDeriveUpdate_SameUnit() throws NoSuchAlgorithmException, IOException, CaosDBException { - final EntityInterface magicUnit = new RetrieveEntity(new EntityID(1234)); + final EntityInterface magicUnit = new RetrieveEntity(new EntityID("1234")); magicUnit.setName("Unit"); - magicUnit.setId(new EntityID(24)); + magicUnit.setId(new EntityID("24")); magicUnit.setDatatype("TEXT"); - final Entity newEntity = new RetrieveEntity(new EntityID(1234)); - final Property newProperty = new Property(new RetrieveEntity(new EntityID(1))); + final Entity newEntity = new RetrieveEntity(new EntityID("1234")); + final Property newProperty = new Property(new RetrieveEntity(new EntityID("1"))); - final Property newUnit = new Property(new RetrieveEntity(new EntityID(5))); + final Property newUnit = new Property(new RetrieveEntity(new EntityID("5"))); newUnit.setName(magicUnit.getName()); newUnit.setId(magicUnit.getId()); newUnit.setDatatype(magicUnit.getDatatype()); @@ -126,10 +126,10 @@ public class UpdateTest { newEntity.addProperty(newProperty); - final Entity oldEntity = new RetrieveEntity(new EntityID(1234)); - final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1))); + final Entity oldEntity = new RetrieveEntity(new EntityID("1234")); + final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1"))); - final Property oldUnit = new Property(new RetrieveEntity(new EntityID(5))); + final Property oldUnit = new Property(new RetrieveEntity(new EntityID("5"))); oldUnit.setName(magicUnit.getName()); oldUnit.setId(magicUnit.getId()); oldUnit.setDatatype(magicUnit.getDatatype()); @@ -149,15 +149,15 @@ public class UpdateTest { @Test public void testDeriveUpdate_DifferentUnit() throws NoSuchAlgorithmException, IOException, CaosDBException { - final EntityInterface magicUnit = new RetrieveEntity(new EntityID(1234)); + final EntityInterface magicUnit = new RetrieveEntity(new EntityID("1234")); magicUnit.setName("Unit"); - magicUnit.setId(new EntityID(24)); + magicUnit.setId(new EntityID("24")); magicUnit.setDatatype("TEXT"); - final Entity newEntity = new RetrieveEntity(new EntityID(1234)); - final Property newProperty = new Property(new RetrieveEntity(new EntityID(1))); + final Entity newEntity = new RetrieveEntity(new EntityID("1234")); + final Property newProperty = new Property(new RetrieveEntity(new EntityID("1"))); - final Property newUnit = new Property(new RetrieveEntity(new EntityID(5))); + final Property newUnit = new Property(new RetrieveEntity(new EntityID("5"))); newUnit.setName(magicUnit.getName()); newUnit.setId(magicUnit.getId()); newUnit.setDatatype(magicUnit.getDatatype()); @@ -168,10 +168,10 @@ public class UpdateTest { newEntity.addProperty(newProperty); - final Entity oldEntity = new RetrieveEntity(new EntityID(1234)); - final Property oldProperty = new Property(new RetrieveEntity(new EntityID(1))); + final Entity oldEntity = new RetrieveEntity(new EntityID("1234")); + final Property oldProperty = new Property(new RetrieveEntity(new EntityID("1"))); - final Property oldUnit = new Property(new RetrieveEntity(new EntityID(5))); + final Property oldUnit = new Property(new RetrieveEntity(new EntityID("5"))); oldUnit.setName(magicUnit.getName()); oldUnit.setId(magicUnit.getId()); oldUnit.setDatatype(magicUnit.getDatatype()); @@ -192,10 +192,10 @@ public class UpdateTest { throws NoSuchAlgorithmException, CaosDBException, IOException { final Entity newEntity = new UpdateEntity(); - final Property newProperty = new Property(new UpdateEntity(new EntityID(1))); + final Property newProperty = new Property(new UpdateEntity(new EntityID("1"))); newProperty.setDatatype("List<Person>"); CollectionValue newValue = new CollectionValue(); - newValue.add(new ReferenceValue(1234)); + newValue.add(new ReferenceValue("1234")); newValue.add(null); newValue.add(new GenericValue(2345)); newValue.add(new GenericValue(3465)); @@ -206,14 +206,14 @@ public class UpdateTest { // old entity represents the stored entity. final Entity oldEntity = new UpdateEntity(); - final Property oldProperty = new Property(new UpdateEntity(new EntityID(1))); + final Property oldProperty = new Property(new UpdateEntity(new EntityID("1"))); oldProperty.setDatatype("List<Person>"); CollectionValue oldValue = new CollectionValue(); // Values are shuffled but have the correct index oldValue.add(1, null); oldValue.add(3, new GenericValue(3465)); - oldValue.add(2, new ReferenceValue(2345)); - oldValue.add(0, new ReferenceValue(1234)); + oldValue.add(2, new ReferenceValue("2345")); + oldValue.add(0, new ReferenceValue("1234")); oldProperty.setValue(oldValue); oldEntity.addProperty(oldProperty); @@ -245,8 +245,8 @@ public class UpdateTest { // Values are shuffled but have the correct index oldValue2.add(0, null); oldValue2.add(1, new GenericValue(3465)); - oldValue2.add(2, new ReferenceValue(2345)); - oldValue2.add(3, new ReferenceValue(1234)); + oldValue2.add(2, new ReferenceValue("2345")); + oldValue2.add(3, new ReferenceValue("1234")); oldValue2.add(4, null); oldProperty.setValue(oldValue2); @@ -266,8 +266,8 @@ public class UpdateTest { public void testDeriveUpdate_UpdateList() throws NoSuchAlgorithmException, CaosDBException, IOException { // @review Florian Spreckelsen 2022-03-15 - final Property oldProperty = new Property(new UpdateEntity(new EntityID(1))); - final Property newProperty = new Property(new UpdateEntity(new EntityID(1))); + final Property oldProperty = new Property(new UpdateEntity(new EntityID("1"))); + final Property newProperty = new Property(new UpdateEntity(new EntityID("1"))); oldProperty.setDatatype("List<Person>"); newProperty.setDatatype("List<Person>"); final Entity oldEntity = new UpdateEntity();