Activatable entities - fieldenms/tg GitHub Wiki
Activatable entities provide a way to model those domain aspects that have temporal or lifecycle-like nature (i.e going through various stages) that lead to activation (switch-on) and deactivation (switch-off) of entities.
For example, WorkActivity
, PmRoutine
and Person
are activatable entities.
There are following rules related to such entities:
1. Activatable entitiy should extend ActivatableAbstractEntity.
public class PmRoutine extends ActivatableAbstractEntity<...>
Also it is a good idea to override its parent's method setActive()
in the following manner:
@Observable
public PmRoutine setActive(final boolean active) {
super.setActive(active);
return this;
}
Sometimes user is in control and decides when entity becomes active/inactive (in case of PmRoutine
and Person
), but sometimes it is totally controlled by system and entity changes it's state automatically (in case of WorkActivity
).
For example, existing PM Routine is replaced be newer version, as result it may become inactive at some point of time and system's manager is in charge of making this decision.
When in case of Work Activity it becomes inactive when it's status progresses to the status F (finished) or C (Closed), and deactivation is happening automatically in the WorkActivityStatusDefiner
:
@Override
public void handle(final MetaProperty<WorkActivityStatus> property, final WorkActivityStatus newStatus) {
final WorkActivity workActivity = property.getEntity();
if (!workActivity.isInitialising()) {
// A user or some business logic has changed the status - set "active" flag accordingly.
workActivity.setActive(newStatus.isActiveStatus());
}
}
Therefore if activation/deactivation should be automatically controlled the business rule have to be provided.
2. Properties refCount
and active
have to be included in the model.
If you are creating activatable entity in the new system you have to include two properties in the entity's retriever: refCount
and active
.
@Override
public SortedMap<String, String> resultFields() {
return map(
field("key", "LTRIM(RTRIM(CRAFT))"),
field("desc", "CRAFT_DESC"),
field("active", "COALESCE(CASE UPPER(LTRIM(RTRIM(CONTRACTOR))) WHEN 'Y' THEN 'Y' WHEN 'N' THEN 'Y' WHEN
'EY' THEN 'N' WHEN 'EN' THEN 'N' ELSE NULL END, 'N')"),
field("refCount", "0"),
.....................
);
}
If you are modifying an existing entity you have to provide SQL script that changes database structure by adding REFCOUNT_
and ACTIVE_
columns.
ALTER TABLE MODIFICATION_ ADD REFCOUNT_ [int] NOT NULL
GO
ALTER TABLE MODIFICATION_ ADD ACTIVE_ [char](1) NOT NULL
GO
3. Activatable dependencies have to be considered.
Very often activatable entity could be a property of another entity. For example, activatable entity Timesheet
has property person
that is activatable entity. We therefore refer to Timesheet
as an activatable dependency of Person
.
Activatable entities cannot be deactivated if active dependencies exist. Property refCount
is used to keep track of active activatable dependencies. Therefore it is critical to provide an SQL script to calculate the number of active activatable dependencies.
UPDATE Modification_ SET REFCOUNT_ = 0;
GO
UPDATE Modification_ SET REFCOUNT_ =
(SELECT COUNT(*) FROM WORKORDER_ AS DEPENDENT_
WHERE DEPENDENT_.ACTIVE_ = 'Y' AND
DEPENDENT_.Modification_ = Modification_._ID
)
WHERE ACTIVE_ = 'Y'
GO
Please note that method main
in ApplicationDomain
can be used to locate all activatable dependencies in the model domain for a given entity.
4. Deactivatable dependencies.
Sometimes when activatable entity is made inactive it should also automatically deactivate dependent active entities.
For example, activatable entity PmRoutine
has an activatable dependency PmTimeXref
. When PmRoutine
is made inactive, there is a requirement for all associated PmTimeXref
s to also be made inactive.
@DeactivatableDependencies(...)
annotation is used to achieve this.
@DeactivatableDependencies(PmTimeXref.class)
public class PmRoutine extends ActivatableAbstractEntity<String>