Customizing Document Search

Each document carries an XML payload that describes metadata. You can specify pieces of that metadata to be indexed and searched on. This area focuses on the interface for searching through that data. For each Document Search page, you must setup the XML configuration files to define the search criteria and result fields.

Custom Search Screen

As an example of customizing a Document Search screen, we’ll use a customized Delete Course Request screen:

Figure 3.24. Custom Search Screen: Delete Course Example

Custom Search Screen: Delete Course Example

What are custom document search attributes?

Custom document search attributes are associated with a document type. They specify which pieces of document data will be made searchable for documents of that type. When you take action on a document in the workflow engine, a background process extracts the custom search attributes from the document and adds them to a database table where they can be queried as part of a custom document search. These custom search attributes are defined and associated along with document types in WorflowData XML files, and are added to Rice via the XML ingester. They are defined within (using XPath notation) /data/ruleAttributes/ruleAttribute tags, and are associated with specific document types within /data/documentTypes/documentType/attributes/attribute tags.

A custom search attribute's logic is defined in a Java class that implements the SearchAttribute interface. A SearchableAttribute implementation defines:

  • What parts of the document content will be made searchable

  • Which fields will be present in the document search interface

  • Which columns will be shown in the search results

  • What is considered valid user input for the custom search fields

There is a built in SearchAttribute implementation, SearchableXMLAttribute, that is highly configurable via XML and will meet most requirements. If there is need for more complex or specific behavior, a custom SearchAttribute implementation can be written and utilized as well.

DocumentSearchAttributes is much like XMLRuleAttributes, except that DocumentSearchAttributes is responsible for drawing input fields on the Document Search form and collecting data for the query, as opposed to analyzing data for routing evaluation (done by XMLRuleAttributes).

Hide Search Fields and Result Columns

In a search configuration, the <visibility> tag lets you configure search criteria to be included or excluded from the entry of search criteria or from the search results. You can use the <visibility> tag on all field(s) and column(s) in the Document Search results except for Document Id and Route Log, which must always be visible.

Hide a result column

<visibility>
    <column visible="false"/>

</visibility>

Hide a search field

<visibility>
    <field visible="false"/>
</visibility>

Field and column visibility based on workgroup membership

Use code like this in the XML file to display column(s) and field(s) based on the user's workgroup:

<visibility>
    <field>
        <isMemberOfWorkgroup>WorkflowAdmin</isMemberOfWorkgroup>
    </field>
    <column>
        <isMemberOfWorkgroup>WorkflowAdmin</isMemberOfWorkgroup>
    </column>
</visibility>

The example above indicates that the field and column only display for users who are a member of the workgroup, WorkflowAdmin.

Configure visibility for both field and column

A shortcut to configure the visibility for both fields and columns is the <fieldAndColumn> tag. A <fieldAndColumn> example:

<visibility>
    <fieldAndColumn>
        <isMemberOfWorkgroup>WorkflowAdmin</isMemberOfWorkgroup>
    </fieldAndColumn>
</visibility>

No field visibility

Declaring <type> as hidden is equivalent to setting visibility to false. An example of <type> and <visibility>, equivalent to a hidden field:

<searchingConfig>
    <fieldDef name="department" title="Department">
        <display>
            <type>text</type>
        </display>
        <visibility>
            <field visible="false"/>
        </visibility>
        <fieldEvaluation>
            <xpathexpression>normalize-space(substring-before(//department, ' '))</xpathexpression>
        </fieldEvaluation>
    </fieldDef>

</searchingConfig>


<!-- The above is equivalent to the following searching configuration -->

<searchingConfig>
    <fieldDef name="department" title="Department">
        <display>
            <type>hidden</type>
        </display>
        <fieldEvaluation>
            <xpathexpression>normalize-space(substring-before(//department, ' '))</xpathexpression
>
        </fieldEvaluation>
    </fieldDef>

</searchingConfig>

Configure Lookup Function

To make a lookupable available on the Document Search screen, you can use the <quickfinder> tag in the attribute definition. You can use the terms quickfinder, lookup, and lookupable interchangeably.

For example, you could set up an organizational hierarchic concept such as Charts and Orgs to implement a search. You could set up the code to perform this search using the ChartOrgLookupableImpl institutional plugin. This is an example of a standard lookupable component.

In the institutional plug-in, ChartOrgLookupableImpl is identified in the LookupableServiceExtension by the name of ChartOrgLookupableImplservice. ChartOrgLookupableImpl exposes two return parameters, which are:

  • Fin_coa_cd: Represents the chart code

  • Org_cd: Represents the organization code

An XML example of setting up a lookupable on the Document Search screen: ChartOrgSearchAttribute.xml

<ruleAttribute>
    <name>ChartOrgSearchAttribute</name>
    <className>org.kuali.rice.kew.docsearch.xml.StandardGenericXMLSearchableAttribute</className>
    <label>TestQuickfinderSearchAttribute</label>
    <description>TestQuickfinderSearchAttribute</description>
    <type>SearchableXmlAttribute</type>
    <searchingConfig>
        <fieldDef name="chart" title="Chart">
            <display>
                <type>text</type>
            </display>
            <quickfinder service="ChartOrgLookupableImplService" appliesTo="fin_coa_cd" draw="false"/>
            <fieldEvaluation>
                <xpathexpression>//chart</xpathexpression>
            </fieldEvaluation>
        </fieldDef>
        <fieldDef name="org" title="Organization">
            <display>
                <type>text</type>
            </display>
            <quickfinder service="ChartOrgLookupableImplService" appliesTo="org_cd" draw="true"/>
            <fieldEvaluation>
                <xpathexpression>//org</xpathexpression>
            </fieldEvaluation>
        </fieldDef>
        <xmlSearchContent>
            <chartOrg>
                <chart>%chart%</chart>
                <org>%org%</org>
            </chartOrg>
        </xmlSearchContent>
    </searchingConfig>
</ruleAttribute>

In the XML example above, there are two <quickfinder> tags representing the Chart (fin_coa_cd) and Org (org_cd) search. Notice the draw attribute for the Org (org_cd) search is set true. This means that a search icon will be displayed on the Document Search screen. Based on the XML code above, the final Document Search screen looks like this:

Figure 3.25. Custom Document Search: Department Example

Custom Document Search: Department Example

Define Keyword Search

XMLSearchableAttributeStdFloatRang is an XML searchable attribute that enhances the keyword search function. It provides multiple searchable elements for a user to select under the <searchingConfig> section. This example is the XMLSearchableAttributeStdFloatRang attribute in the default setting:

<ruleAttribute>
    <name>XMLSearchableAttributeStdFloatRange</name>
    <className>org.kuali.rice.kew.docsearch.xml.StandardGenericXMLSearchableAttribute</className>
    <label>XML Searchable attribute</label>
    <description>XML Searchable attribute</description>
    <type>SearchableXmlAttribute</type>
    <searchingConfig>
        <fieldDef name="testFloatKey" title="Float in the Water">
            <display>
                <type>text</type>
            </display>
            <searchDefinition dataType="float">
                <rangeDefinition inclusive="false">
                    <lower label="starting"/>
                    <upper label="ending"/>
                </rangeDefinition>
            </searchDefinition>
            <fieldEvaluation>
                <xpathexpression>//putWhateverWordsIwantInsideThisTag/testFloatKey/value</xpathexpression>
            </fieldEvaluation>
        </fieldDef>
        <xmlSearchContent>
            <putWhateverWordsIwantInsideThisTag>
                <testFloatKey>
                    <value>%testFloatKey%</value>
                </testFloatKey>
            </putWhateverWordsIwantInsideThisTag>
        </xmlSearchContent>
    </searchingConfig>
</ruleAttribute>

Caution

Cautions about the <searchingConfig> section:

  1. <searchDefinition> identifies the search data type and search ranges.

  2. <rangeDefinition> contains both the <lower> and <upper> elements that set up the parameters for the range search.

  3. If you set the <display><type> tag to be date, then KEW automatically sets: <searchDefinition dataType="datetime">.

  4. If the data type that you enter is not a datetime, then KEW sets all datePicker attributes to false.

  5. Based on the dataType you enter, datePicker changes the default setting to either true or false.

  6. To use a range search, you can either set <searchDefinition rangeSearch="true"> or put the tag <rangeDefinition> under the <searchDefinition> tag. Either way, KEW will force a range search.

Custom Search Criteria Processing

URL Parameter Options

You can modify the search criteria and the display of the search screen by passing in URL parameters. Only use this method when the configuration desired is preferable and not required. If a particular piece of the search criteria is required, please see the section below titled, Using a Custom Search Criteria Processor.

Force the link to display the Detailed Search screen

Use the parameter isAdvancedSearch and set the value to YES.

Show or Hide All Criteria and/or the Workflow Header Bar

The default value of each of these parameters must be set to true to show both the criteria and the header bar.

  • To hide the header bar, use the URL parameter headerBarEnabled and set the value to false.

  • To hide the search criteria (including the buttons), use the URL parameter searchCriteriaEnabled and set the value to false.

Passing in Searchable Attribute Values

Use the URL parameter searchableAttributes to pass in searchable attribute values. The value for searchableAttributes should be a comma-delimited list of searchable attribute <fieldDef> names and values in the form name:value.

Here is an example using two <fieldDef> objects with names firstname and lastname:

http://yourlocalip:8080/DocumentSearch.do?searchableAttributes=firstname:John,lastname:Smith

Using a Custom Search Criteria Processor

The best way to do custom criteria processing is to implement a custom class that extends the class org.kuali.rice.kew.docsearch.DocumentSearchCriteriaProcessor. This file is ingested as a Workflow Attribute in KEW, using the <type> of DocumentSearchCriteriaProcessorAttribute. Once the Workflow Attribute is ingested, you can set the name value of the ingested attribute on one or more document type xml definitions in the Attributes section. A document type can only have one Criteria Processor Attribute.

Creating a child class of the DocumentSearchCriteriaProcessor class, a client can override various methods to modify the behavior of the search. The DocumentSearchCriteriaProcessor class can access the WorkflowUser object of the user performing the search. By having access to these objects, a custom processor class could implement dynamic hiding and showing of specific criteria fields based on ordinary user’s data or search field data.

Show or Hide All Criteria and/or the Workflow Header Bar

Here are some helpful methods that you may override from the DocumentSearchCriteriaProcessor class file to hide or display full criteria (including buttons) and/or the header bar:

  • isHeaderBarDisplayed() – If this function returns false, KEW hides the header bar on both the advanced and basic search screens (default return value is true).

  • isBasicSearchCriteriaDisplayed() – If this function returns false, KEW hides criteria on the basic search screen (default return value is true).

  • isAdvancedSearchCriteriaDisplayed() – If this function returns false, KEW hides the criteria on the advanced search screen (default return value is true).

Hiding Specific Fields or Criteria Using Field Key Values

The DocumentSearchCriteriaProcessor class has methods that allow classes to extend from it for basic field display. This is based on static string key values and makes it easier for clients to allow basic field display or to hide particular fields, whether they are searchable attributes or standard Document Search fields.

You may override these methods from the DocumentSearchCriteriaProcessor class to do specific field hiding by returning a list of string keys:

  • getGlobalHiddenFieldKeys() – This function returns a list of keys (strings) for fields to be hidden on both the basic and advanced search screen.

  • getBasicSearchHiddenFieldKeys() – This function returns a list of keys (strings) for fields to be hidden on the basic search screen.

  • getAdvancedSearchHiddenFieldKeys() – This function returns a list of keys (strings) for fields to be hidden on the advanced search screen.

You can find the standard Document Search field key names in the class file org.kuali.rice.kew.docsearch.DocumentSearchCriteriaProcessor. They are constants prefixed by the text CRITERIA_KEY_. For example, the static criteria key for the Document Id field is DocumentSearchCriteriaProcessor.CRITERIA_KEY_DOCUMENT_ID.

A client can also use searchable attribute <fieldDef> name values to hide fields in the same way that you use constants. If a particular searchable attribute <fieldDef> name exists in a list returned by one of the above hidden field key methods, the criteria processor class overrides the default behavior of that <fieldDef> searchable attribute for visibility.

Here is a general example of a custom criteria processor class that extends StandardDocumentSearchCriteriaProcessor:

public class CustomDocumentSearchCriteriaProcessor extends DocumentSearchCriteriaProcessor {

/**
     
  *  Always hide the header bar on all search screens
     
  */
   
    @Override
    public boolean isHeaderBarDisplayed() {
        return Boolean.FALSE;
    
    }

    

/**
  *  Always hide all criteria and buttons on the advanced search screen
     
  */
    
    @Override
    public Boolean isAdvancedSearchCriteriaDisplayed() {
        return Boolean.FALSE;
    }


/**
  *  Hide the Initiator Criteria field on both Basic and Advanced Search screens
  */
    @Override
    public List<String> getGlobalHiddenFieldKeys() {
        List<String> hiddenKeys = super.getGlobalHiddenFieldKeys();
        hiddenKeys.add(DocumentSearchCriteriaProcessor.CRITERIA_KEY_INITIATOR);
        return hiddenKeys;
    }


/**
  *  Hide the Document Title criteria field on the basic search screen
  *  Hide the searchable attribute field with name 'givenname' on the basic search screen
  */
    @Override
    public List<String> getBasicSearchHiddenFieldKeys() {
        List<String> hiddenKeys = super.getAdvancedSearchHiddenFieldKeys();
        hiddenKeys.add(DocumentSearchCriteriaProcessor.CRITERIA_KEY_DOCUMENT_TITLE);
        hiddenKeys.add("givenname");
        return hiddenKeys;
    }


/**
  *  Hide the Document Title criteria field on the advanced search screen
  *  Hide the searchable attribute field with name 'givenname' on the basic search screen
  */
    
    @Override
    public List<String> getAdvancedSearchHiddenFieldKeys() {
        List<String> hiddenKeys = super.getAdvancedSearchHiddenFieldKeys();
        hiddenKeys.add(DocumentSearchCriteriaProcessor.CRITERIA_KEY_DOCUMENT_TITLE);
        hiddenKeys.add("givenname");
        return hiddenKeys;
    
    }
}

Custom Search Generation

The best way to do custom search generation or processing is to implement a custom class that extends the class org.kuali.rice.kew.impl.document.lookup.DocumentSearchGenerator. This file is ingested as a Workflow Attribute in KEW using the <type> value of DocumentSearchGeneratorAttribute. Once the Workflow Attribute is ingested, the name value of the ingested attribute can be set on one or more document type xml definitions in the Attributes section. A Document Type can only have one Search Generator Attribute.

Using an extension of the DocumentSearchGenerator class, a client has access to override various methods to modify the behavior of the search. Also, the DocumentSearchGenerator class has helper methods that may be used to get the WorkflowUser object of the user performing the search.

Implementing a Custom Result Set Limit

To implement a custom result set limit, simply override the method getDocumentSearchResultSetLimit() from the StandardDocumentSearchGenerator class.

Custom Search Results

You can create a Custom Search Result table using an XML rule attribute of the type DocumentSearchRsultXMLResultProcessorAttribute.

The standard Search Result table:

Figure 3.26. Standard Doc Search Results Set

Standard Doc Search Results Set

The Standard Search Result fields:

  • Document Id

  • Type

  • Title

  • Route Status

  • Initiator

  • Date Created

  • Route log

The fields of Document Id and Route Log are always shown in the farthest left and right columns of the Search Result table. These fields cannot be hidden. You can add both columns a second time in the XML search result attributes if needed.

Custom XML Document Search Result Processor Attribute

An example of a custom XML result processor:

<ruleAttribute>
    <name>KualiContractsAndGrantsDocSearchResultProcessor</name>

    <className>org.kuali.rice.kew.docsearch.xml.DocumentSearchXMLResultProcessorImpl</className>
    <label>Contracts &amp; Grants Document Search Result Processor</label>
    <description>Attribute to allow for custom search results for Contracts &amp; Grants documents</description>
    <type>DocumentSearchXMLResultProcessorAttribute</type>
    <searchResultConfig overrideSearchableAttributes="false" showStandardSearchFields="false">
        <column name="docTypeLabel" />
        <column name="docRouteStatusCodeDesc" />
        <column name="initiator" />
        <column name="dateCreated" />
    </searchResultConfig>

</ruleAttribute>

The result of the code displayed above is a Search Result table with these columns:

  • Document Id

  • Type

  • Route Status

  • Initiator

  • Date Created

  • Route Log

The key for the search result customization is focused on the elements and column tag(s) under the <searchResultConfig>.

Attributes that are included in the <searchResultConfig> tag:

  • overrideSearchableAttributes: The indicator of whether to display the column name attributes defined by the searchAttribute fieldDef 'name's configured by setting the true or false

    • true: Display the <column> name attributes based on searchAttribute fieldDef names.

    • false: Display the name based on the <column> attribute.

  • showStandardSearchFields: The indicator of whether to display the standard search fields by setting the value true or false.

    • true: Display the search result with the standard result fields; the name attribute of the <column> tag should match the values in the java file DocumentSearchResult.java.

    • false: Display the search result based on the custom result fields.

Attributes that can be added in a <column> tag:

  • Name: The key for connecting the value of a particular attribute. For example, routeHeaderId equals Document Id. For more information about the attribute key, please refer to the Key reference table below.

  • Title: The title of the field

  • Sortable: The indicator of whether to sort the search result by setting the value true or false

    • true: Sort option for this column is enabled to sort either alphabetically or numerically depending on attribute type.

    • false: Sort option for this column is disabled.

For <column> with sortable = true, the field title becomes a link and when a user clicks the link, KEW sorts the results by that column.

An example of a custom ruleAttribute:

<ruleAttribute>
    <name>KualiContractsAndGrantsDocSearchResultProcessor</name>

    <className>org.kuali.rice.kew.docsearch.xml.DocumentSearchXMLResultProcessorImpl</className>
    <label>Contracts &amp; Grants Document Search Result Processor</label>
    <description>Attribute to allow for custom search results for Contracts &amp; Grants documents</description>
    <type>DocumentSearchXMLResultProcessorAttribute</type>
    <searchResultConfig overrideSearchableAttributes="true" showStandardSearchFields="false">
        <column name="docTypeLabel" />
        <column name="docRouteStatusCodeDesc" />
        <column name="initiator" />
        <column name="dateCreated" />
        <column name="proposal_number" />
        <column name="chart" />
        <column name="organization" />
        <column name="proposal_award_status" />
        <column name="agency_report_name" />
    </searchResultConfig>
</ruleAttribute>

Table 3.17. Key Reference Table: Default field names and reference keys

FieldKey
Document Id routeHeaderId
Type docTypeLabel
Title documentTitle
Route Status docRouteStatusCodeDesc
Initiator initiator
Date Created dateCreated
Route Log routeLog


Custom Document Search Result Processor Class File

You may also use a custom Document Search Result Processor by extending the class org.kuali.rice.kew.docsearch.StandardDocumentSearchResultProcessor and overriding individual methods.

Differences between SearchableAttribute and RuleAttribute

  • SearchableAttribute does NOT have a workflowType attribute in the field tag.

  • For SearchableAttribute, xpathexpression indicates the value's location in the document; it does not use wf:ruledata(''). For RuleAttribute, xpathexpression is a Boolean expression.

  • SearchableAttribute uses xmlSearchContent instead of xmlDocumentContent; xmlDocumentContent is for RuleAttribute.

Document Security

Kuali Enterprise Workflow provides a declarative mechanism to facilitate Document-level security for these three screens:

  • Document Search

  • Route Log

  • Doc Handler Redirection

Overview

  1. You can create a security definition on a Document Type, which allows you to apply varying levels and types of security.

  2. This definition is inheritable through the Document Type hierarchy.

  3. If security is defined on a Document Type, rows for that Document Type that are returned from a search apply the security constraints and filter the row if the constraints fail.

  4. Security constraints are evaluated against a document when its Route Log is accessed. If the security constraints fail, the user receives a Not Authorized message.

  5. Security constraints are evaluated against a document when a Doc Handler link is clicked from either the Action List or Document Search. If the security constraints fail, the user receives a Not Authorized message.

Security Definition

You can define the security constraints in the Document Type XML. Here's a sample of the XML format:

<documentType>
    ....
    <security>
        <securityAttribute class="org.kuali.security.SecurityFilterAttribute"/>
        <securityAttribute name="TestSecurityAttribute"/>
        <initiator>true</initiator>
        <routeLogAuthenticated>true</routeLogAuthenticated>
        <searchableAttribute idType="emplid" name="emplid"/>
        <group>MyWorkgroup</group>
        <role allowed="true">FACULTY</role>
        <role allowed="true">STAFF</role>
    </security>
    ....

</documentType>

There is an implicit OR in the evaluation of these constraints. Thus, the definition above states that the authenticated user has access to the document if:

  • The attribute org.kuali.security.SecurityFilterAttribute defines the user as having access OR

  • The attribute defined in the system by the name TestSecurityAttribute defines the user as having access OR

  • The user is the initiator of the document OR

  • The user is on the Route Log of the document OR

  • The user’s EMPL ID is equal to the searchable attribute on the document with the key of emplid OR

  • The user is a member of the MyWorkgroup workgroup OR

  • The user has the FACULTY role OR

  • The user has the STAFF role

<initiator>

Validates that the authenticated user is or isn't the initiator of the document.

<routeLogAuthenticated>

Validates that the authenticated user is or isn't Route Log Authenticated.

Route Log Authenticated means that one of these is true:

  1. The user is the initiator of the document.

  2. The user has taken action on the document.

  3. The user has received a request for the document (either directly or as the member of a workgroup).

Route Log Authenticated checks for security but does not simulate or check future requests.

<securityAttribute>

Validates based on a custom-defined class. Class must have implemented the SecurityAttribute interface class. There are two methods of defining a security attribute:

  • Class Name: Define the fully qualified class name using the XML attribute class

    <documentType>
        ....
    	
        <security>
            <securityAttribute class="org.kuali.security.SecurityFilterAttribute"/>
        </security>
        ....
    
    </documentType>
    
  • KEW Attribute Name: Specify an already-defined attribute (via KEW XML ingestion) using the XML attribute name

    <documentType>
        ....
        <security>
            <securityAttribute name="TestSecurityAttribute"/>
        </security>
        ...
    .
    </documentType>
    

<searchableAttribute>

Validate that the authenticated User ID of the given idType is equivalent to the searchable attribute field with the given name.

The following id types are valid:

  • emplid

  • authenticationid

  • uuid

  • workflowid

<group>

Validate that the authenticated user is a member of the workgroup with the given name.

<role>

Validate that the authenticated user has the given role. The existence and names of these roles are determined by your setup in KEW. (You can create these roles when you implement WebAuthenticationService.) Typically, the roles mirror your organization structure.

For example, you may choose to expose these roles:

  • STAFF

  • FACULTY

  • ALUMNI

  • STUDENT

  • FORMER-STUDENT

  • APPLICANT

  • ENROLLED

  • ADMITTED

  • PROSPECT

  • GRADUATE

  • UNDERGRADUATE

If the role is marked as allowed=true, than anyone with that role passes the security constraint. If the role is marked as allowed=false, then if the individual has the given disallowed role but none of the allowed roles, he or she fails the security check.

Order of Evaluation

The security constraints are evaluated in the following order. If any single constraint passes, it bypasses evaluating the remaining constraints.

  1. Security attribute

  2. Initiator

  3. Role

  4. Workgroup

  5. Searchable attribute

  6. Route log authenticated

Security - Warning Messages

These security scenarios generate security warning messages:

Document Search

  • If no rows are filtered because of security, the user sees the search result without any warning message on the Document Search page.

  • If rows are filtered because of security, a red warning message on top of the Document Search page shows how many rows were filtered. For example, "19 rows were filtered for security purposes."

  • If the initial result set returns more than the search result threshold (500 rows), and rows in the set subsequently get filtered because of security, then a red warning message shows how many rows were returned and filtered. For example, "Too many results returned, displaying only the first 450. 50 rows were filtered for security purpose. Please refine your search."

Route Log and Doc Handler

  • If the defined security constraints stop a user from viewing a document, a red warning message shows at the top of the page if they attempt to access the Route Log. For example, "You are not authorized to access this portion of the application."

Service Layer

In an out-of-the-box installation of KEW, Document Security is handled by org.kuali.rice.kew.doctype.DocumentSecurityServiceImpl, which implements the org.kuali.rice.kew.doctype.DocumentSecurityService service interface.