Property definers: support for composition, conversion to post-condition.
Description
Unlike property validators (aka property pre-conditions, constraints), which support composition and a deterministic execution order, property definers do not support composition explicitly, supporting only a single class to be specified for a property as its definer. Such design worked well in most cases due to the fact that definers tend to be very specific for an entity/property. However, there are situations where ability to abstract some common logic into separate definers that could be used in conjunction with a specific definer or in their own right, would simplify the implementation and improve capacity for code reuse.
Also, practical use cases suggest that turning definers into first-class post-conditions, returning result of their execution, would provide more suitable mechanism for domain modelling with RESTful object, simplifying otherwise convoluted logic. A failure returned by a post-condition/definer would then be associated with a property in the same manner as a failure returned by a pre-condition (i.e., associated with a property).
The following is proposed:
-
[ ] 1. Convert
@AfterChangeto be in line with@BeforeChange, expressing after-change event handlers in terms of a sequence of handlers. -
[ ] 2.
IAfterChangeEventHandlershould be provided with new methodResult handle(final MetaProperty<T> property)with a default implementation invoking existinghandlein try-catch, returning failure in case of an exception and success otherwise. Existing methodhandle(property, entityPropertyValue)should be declared as@Deprecatedin favour of the new one. Such approach would guarantee that the change is non-breaking. -
[ ] 3.
ObservableMutatorInterceptorshould be enhanced to process multiple post-conditions/definers in the order of their declaration. If the returnedResultrepresents a failure, it should be associated with the property as it's validation result and no other post-condition should be executed. -
[ ] 4. It could be the case that a post-condition returned either a failure or a warning, or an informative result, while a pre-condition returned a warning or an informative result. In order not to lose the information from pre-conditions, it is required to combine the results of pre- and post-conditions into the most severe out of all (i.e., if failure is the most severe then failure, if warning is the most severe -- warning, else informative). More analysis is required to come up with a good design for presenting users with such combined information. Also, combining non-failure results from several pre- and post-conditions should be considered.
Expected outcome
Support for post-conditions with composition.