From 351856773d886ec991e24155d3ce70c338e62b3f Mon Sep 17 00:00:00 2001 From: homedirectory Date: Wed, 30 Oct 2024 13:10:46 +0200 Subject: [PATCH] #2349 Introduce a base type for audit-entity companions --- .../platform/audit/CommonAuditEntityDao.java | 76 +++++++++++++++++++ .../platform/audit/IAuditEntityDao.java | 14 ++++ .../audit/IAuditEntityInstantiator.java | 22 ++++++ 3 files changed, 112 insertions(+) create mode 100644 platform-dao/src/main/java/ua/com/fielden/platform/audit/CommonAuditEntityDao.java create mode 100644 platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityDao.java create mode 100644 platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityInstantiator.java diff --git a/platform-dao/src/main/java/ua/com/fielden/platform/audit/CommonAuditEntityDao.java b/platform-dao/src/main/java/ua/com/fielden/platform/audit/CommonAuditEntityDao.java new file mode 100644 index 0000000000..adec9a6db7 --- /dev/null +++ b/platform-dao/src/main/java/ua/com/fielden/platform/audit/CommonAuditEntityDao.java @@ -0,0 +1,76 @@ +package ua.com.fielden.platform.audit; + +import jakarta.inject.Inject; +import ua.com.fielden.platform.dao.CommonEntityDao; +import ua.com.fielden.platform.dao.exceptions.EntityCompanionException; +import ua.com.fielden.platform.entity.AbstractEntity; +import ua.com.fielden.platform.meta.IDomainMetadata; +import ua.com.fielden.platform.security.user.User; + +import static org.apache.commons.lang3.StringUtils.substringAfter; +import static ua.com.fielden.platform.audit.AbstractAuditEntity.A3T; +import static ua.com.fielden.platform.error.Result.failuref; + +/** + * Base type for implementations of audit-entity companion objects. + * + * @param the audited entity type + * @param the audit-entity type + */ +public abstract class CommonAuditEntityDao, AE extends AbstractAuditEntity> + extends CommonEntityDao + implements IAuditEntityDao +{ + + private IDomainMetadata domainMetadata; + + @Inject + protected void setDomainMetadata(final IDomainMetadata domainMetadata) { + this.domainMetadata = domainMetadata; + } + + @Override + public AE newAudit(final E auditedEntity, final String transactionGuid) { + if (auditedEntity.isDirty()) { + throw failuref("Only persisted and non-dirty instances of [%s] can be audited.", auditedEntity.getType().getTypeName()); + } + // TODO Assert that audited entity is valid? + + final AE audit = new_(); + audit.beginInitialising(); + + // properties common to all audit-entities + audit.setAuditedEntity(auditedEntity); + audit.setAuditedVersion(auditedEntity.getVersion()); + // Alternatively, annotate AbstractAuditEntity.auditDate with @IsProperty(assignBeforeSave = true) + audit.setAuditDate(now().toDate()); + // Alternatively, annotate AbstractAuditEntity.auditDate with @IsProperty(assignBeforeSave = true) + audit.setUser(getUserOrThrow()); + audit.setAuditedTransactionGuid(transactionGuid); + + // specific, audited properties + final var auditEntityMetadata = domainMetadata.forEntity(getEntityType()); + for (final var auditProp : auditEntityMetadata.properties()) { + // Audited properties can be identified by their names + final var auditedPropName = substringAfter(auditProp.name(), A3T + "_"); + if (!auditedPropName.isEmpty()) { + audit.set(auditProp.name(), auditedEntity.get(auditedPropName)); + } + } + + audit.endInitialising(); + return audit; + } + + /** + * Returns the current user, if defined; otherwise, throws an exception. + */ + private User getUserOrThrow() { + final var user = getUser(); + if (user == null) { + throw new EntityCompanionException("The current user is not defined."); + } + return user; + } + +} diff --git a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityDao.java b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityDao.java new file mode 100644 index 0000000000..da886c4094 --- /dev/null +++ b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityDao.java @@ -0,0 +1,14 @@ +package ua.com.fielden.platform.audit; + +import ua.com.fielden.platform.dao.IEntityDao; +import ua.com.fielden.platform.entity.AbstractEntity; + +/** + * A contract for all audit-entity companion objects to implement. + * + * @param the audited entity type + * @param the audit-entity type + */ +public interface IAuditEntityDao, AE extends AbstractAuditEntity> + extends IEntityDao, IAuditEntityInstantiator +{} diff --git a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityInstantiator.java b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityInstantiator.java new file mode 100644 index 0000000000..889252e743 --- /dev/null +++ b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/audit/IAuditEntityInstantiator.java @@ -0,0 +1,22 @@ +package ua.com.fielden.platform.audit; + +import ua.com.fielden.platform.entity.AbstractEntity; + +/** + * A contract to instantiate audit-entities. + * + * @param the audited entity type + * @param the audit-entity type + */ +public interface IAuditEntityInstantiator, AE extends AbstractAuditEntity> { + + /** + * Returns a new, initialised instance of this audit-entity type. + * + * @param auditedEntity the audited entity that will be used to initialise the audit-entity instance. + * Must be persisted and non-dirty. + * @param transactionGuid identifier of a transaction that was used to save the audited entity + */ + AE newAudit(E auditedEntity, String transactionGuid); + +}