Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Tip
titleSample Business Rule Class
Code Block
public class SampleRuleClass implements SaveDocumentRule, RouteDocumentRule {
    /*
     * @see org.kuali.ricekfs.kns.rule.SaveDocumentRule#processSaveDocument(org.kuali.ricekfs.kns.document.Document)
     *
     */
    public boolean processSaveDocument(Document document) {
        boolean isValid = true;

        isValid &= isDocumentOverviewValid(document);

        if (isValid) {
            isValid &= processCustomSaveDocumentBusinessRules(document);
        }

        return isValid;
    }

    /*
     *
     * @see org.kuali.ricekfs.kns.rule.RouteDocumentRule#processRouteDocument(org.kuali.ricekfs.kns.document.Document)
     */
    public boolean processRouteDocument(Document document) {
        boolean isValid = true;

        isValid &= isDocumentAttributesValid(document);

        if (isValid) {
            isValid &= processCustomRouteDocumentBusinessRules(document);
        }

        return isValid;
    }

}

This class is setup to respond to SaveDocumentRuleEvent and RouteDocumentRuleEvent for the particular document it is registered with in the data dictionary.

Info

Note this class must implement the two interface methods processSaveDocument(Document) and processRouteDocument(Document).

...

Code Block
titleRoute Document Event
/**
     * @see org.kuali.ricekfs.kns.rules.DocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.ricekfs.kns.document.Document)
     */
    @Override
    protected boolean processCustomRouteDocumentBusinessRules(Document document) {
        if (!super.processCustomRouteDocumentBusinessRules(document) || GlobalVariables.getMessageMap().hasErrors())
            return false;

        Asset asset = ((AssetTransferDocument)document).getAsset();
        boolean valid = true;
        if (SpringContext.getBean(AssetService.class).isAssetRetired(asset)) {
            valid &= false;
            GlobalVariables.getMessageMap().putError(CamsConstants.DOC_HEADER_PATH, CamsKeyConstants.Transfer.ERROR_ASSET_RETIRED_NOTRANSFER, asset.getCapitalAssetNumber().toString(), asset.getRetirementReason().getRetirementReasonName());
        }

        if (valid) {
            valid &= applyRules(document);
        }

        // only generate error message if asset is locked by other document without stop saving
        valid &= !this.getAssetLockService().isAssetLocked(retrieveAssetNumberForLocking(document), CamsConstants.DocumentTypeName.ASSET_TRANSFER, document.getDocumentNumber());

        return valid;
    }

...

Code Block
titleModified Data Dictionary file with new rule class
typexml
<dictionaryEntry>
    <maintenanceDocument>
        <businessObjectClass>org.kuali.kfs.coa.businessobject.Chart</businessObjectClass>
        <maintainableClass>org.kuali.ricekfs.kns.maintenance.KualiMaintainableImpl</maintainableClass>

        <businessRulesClass>edu.sample.kfs.modulecoa.chartdocument.rulesvalidation.MyChartRule</businessRulesClass>

...

What are the base events that occur to every document, transactional or otherwise? They are the workflow events: saving a document, submitting a document to routing, approving a document, disapproving a document, and canceling a document. Since checking rules on a document after a cancel or disapprove only tends to annoy users, there is no rule checking for those events. However, rules do get validated for the other three.

org.kuali.ricekfs.kns.rules.TransactionalDocumentRuleBase extends org.kuali.ricekfs.kns.rules.DocumentRuleBase directly, so let's take a look at DocumentRuleBase. We note these methods:

...

The rule will get caused by an org.kuali.kfs.fp.document.validation.event.AddCheckEvent. Rule events ultimately have to implement the org.kuali.ricekfs.kns.rule.event.KualiDocumentEvent, which has an abstract base implementation: org.kuali.ricekfs.kns.rule.event.KualiDocumentEventBase.

...

  • getDocument() - every rule event occurs to a document, and therefore, the event holds a pointer to the document that caused the rule event to be fired.
  • getDescription() - a brief description of the event
  • getName() - this returns the name of the event class itself
  • getErrorPathPrefix() - this is the property prefix for the property where the event occurred
  • validate() - this validates the event itself. KualiDocumentEventBase's implementation simply checks that the document isn't null at the time of event validation; if the document is null, it throws a big, fat IllegalArgumentException. Many other events override this method (making sure to callĀ super), adding more validation.
  • generateEvents() - an event may cause other events to fire. We've already seen an example of this: org.kuali.ricekfs.kns.rule.event.RouteDocumentEvent generates a save event using this method. The default implementation returns an empty list.

...

  • You have to instantiate your Event manually, in the code (most likely in the action method), and then pass it into a call to applyRules(). Do this wherever you feel it's appropriate.

    Code Block
    boolean rulePassed = SpringServiceLocatorSpringContext.getKualiRuleServicegetBean(KualiRuleService.class).applyRules(new InsertPeriodLineEventBase(budgetForm.getDocument(), budgetForm.getNewPeriod()));
    

...