There are situations when custom rules need to be coded. These are for situations too complex for a declarative rule. The process is as follows:
For details on the "events" that can be processed by the custom validation, please refer to the JavaDocs.
When coding a CustomValidation that will be used by a CustomRule. It is important to understand when these events fire.
validateAdd() fires only on an add
validateChange() fires only when an existing entity is changed
validateAddOrChange fires in addition to either validateAdd() or validateChange()
validateDelete fires when the entity is being deleted
validateRegisteredChange() fires when "some other object is changed" (like a child). This can be any random entity instance that feels like notifying you regarding a change of state or, more commonly, the framework automatically registers a change when a child collection is manipulated. Your custom code can determine if a change has been made to a child it's interested in by calling the getChangeToList() method on the change detail passed in. You just pass in the class of your child collection and it passes back changes, if any.
validateSave() can be used to implement validations that needs to be performed "at the end" of some set of changes. By default a set of changes is both started and saved within individual calls to setDTO or createBusinessEntity, etc. However, this can be controlled programmatically by calling the startChanges() and saveChanges() methods that are available from within all business objects (change handlers, entities, components, etc). Any type of change (add, change, deleted, register change) will trigger validateSave().