Filter Criteria

Infinity Process Platform services are provided to filter for activities, processes, users etc. The following sections describe how these filters work.

For a detailed description on how to use filter criteria efficiently please refer to the section Using Filter Criteria efficiently.

Activity Filter

ActivityFilter

This filter restricts the resulting items to the ones related to a specific activity. The search can be further restricted to certain models by passing in a collection of model OIDs. Please refer to the Javadoc of the ActivityFilter for detailed information.

ActivityInstanceFilter

This is a filter criterion for matching specific activity instances. Please refer to the Javadoc of the ActivityInstanceFilter for detailed information.

ActivityStateFilter

This is a predefined filter matching activity instances being in states other than a list of given states. Please refer to the Javadoc of the ActivityStateFilter for detailed information.

Process Filter

ProcessDefinitionFilter

This filter restricts the resulting items to the ones related to a specific process definition. Please refer to the Javadoc of the ProcessDefinitionFilter for detailed information.

ProcessInstanceFilter

This is a filter criterion for matching specific process instances. Please refer to the Javadoc of the ProcessInstanceFilter for detailed information.

ProcessStateFilter

Filter for finding process instances in a given state. Please refer to the Javadoc of the ProcessStateFilter for detailed information.

Data Filter

The following data filters are provided:

The DataFilter will filter all process instances from the scope, whereas the SubprocessDataFilter (mode "Subprocesses") retrieves all subprocesses of qualifying scope process instances and the HierarchyDataFilter (mode "AllFromHierarchy") all the sub- and super-processes of qualifying scope process instances.

A set of methods provide different filter functionality for matching workflow data:

Filtering for matching Workflow Data

public static DataFilter isEqual(String dataID, Serializable value)
public static DataFilter isEqual(String dataID, String value, boolean caseSensitive)
public static DataFilter isEqual(String dataID, String attributeName, Serializable value)
public static DataFilter isEqual(String dataID, String attributeName,
         String value, boolean caseSensitive)

Filtering for matching Workflow Data not equal a given value

To filter for matching workflow data being not equal with a given value, use method notEqual.

public static DataFilter notEqual(String dataID, Serializable value)
public static DataFilter notEqual(String dataID, String attributeName, Serializable value)

Filtering for matching Workflow Data less than a given value

public static DataFilter lessThan(String dataID, Serializable value)
public static DataFilter lessThan(String dataID, String attributeName, Serializable value)

Filtering for matching Workflow Data less or equal a given value

public static DataFilter lessOrEqual(String dataID, Serializable value)
public static DataFilter lessOrEqual(String dataID, String attributeName, Serializable value)

Filtering for matching Workflow Data greater or equal a given value

public static DataFilter greaterOrEqual(String dataID, Serializable value)
public static DataFilter greaterOrEqual(String dataID, String attributeName, Serializable value)

Filtering for matching Workflow Data greater than a given value

public static DataFilter greaterThan(String dataID, Serializable value)
public static DataFilter greaterThan(String dataID, String attributeName, Serializable value)

Filtering for matching Workflow Data like a given value

public static DataFilter like(String dataID, String value)
public static DataFilter like(String dataID, String value, boolean caseSensitive)
public static DataFilter like(String dataID, String attributeName, String value)
public static DataFilter like(String dataID, String attributeName, String value,
         boolean caseSensitive)

Filtering for matching Workflow Data equal a list of given value

public static DataFilter in(String dataID, Collection values)
public static DataFilter in(String dataID, String attributeName, Collection values)

Filtering for matching Workflow Data not equal a list of given value

public static DataFilter notIn(String dataID, Collection values)
public static DataFilter notIn(String dataID, String attributeName, Collection values)

Filtering for Workflow Data excluding Process and Activity Instances with specified List Values

This DataFilter notAnyOf is applicable for Structured Data Type list values only. Structured Data Types are defined as lists via a cardinality, which is set to one or more or zero or more. For details on Structured Data Type lists refer to section Composite Types of chapter Defining Structured Types.

public static DataFilter notAnyOf(String dataID, String attributeName, Collection values)

Hereby, dataID determines the ID of the workflow data to be matched against. Parameter attributeName specifies the name of the data attribute to search for (XPath, etc.). Note that only Structured Data value list nodes are supported. The last parameter provides a list of values to match with, which will be excluded from the result set.

The resulting SQL adds for each applied filter an additional OUTER JOIN. For example for DataFilter.notAnyOf("SD1", "list", listWithXYZ):

from process_instance pi
OUTER JOIN structured_data_value sdv on (pi.oid and sdv.string_value in ('X', 'Y', 'Z'))

As DataFilter.notAnyOf() is used to exclude process and activity instances, which have any value mentioned in the list argument in their corresponding Structured Data Value entries, the corresponding WHERE clause will select for NULL entries as shown below:

WHERE sdv.oid is null

OUTER JOIN is used because it generates NULL values for lines which do not match the join condition.

Example

The following example shows the usage of the notAnyOf DataFilter with three process instances piABC, piKLM, piXYZ having a Structured Data Type list element with ID SD1. The values of this list element for each process instance are as in the following table:

Process Instance Values in List Element SD1
piABC A, B, C
piKLM K, L, M
piXYZ X, Y, Z

The following table shows some example queries with these process instances and the according results:

Query (Pseudo Java) Result SQL (Pseudo)
DataFilter.notAnyOf("SD1", "list", [X]) piABC, piKLM (note that piXYZ is excluded as it matches)
from process_instance pi
OUTER JOIN structured_data_value sdv on (pi.oid and sdv.string_value in ('X'))
WHERE sdv.oid is null
DataFilter.notAnyOf("SD1", "list", [Y]) piABC, piKLM
from process_instance pi
OUTER JOIN structured_data_value sdv on (pi.oid and sdv.string_value in ('Y'))
WHERE sdv.oid is null
DataFilter.notAnyOf("SD1", "list", [Z]) piABC, piKLM
DataFilter.notAnyOf("SD1", "list", [U]) piABC, piKLM, piXYZ (none excluded as U has no match)
DataFilter.notAnyOf("SD1", "list", [A,X]) piKLM (piABC and piXYZ are excluded as both match)
from process_instance pi
OUTER JOIN structured_data_value sdv on (pi.oid and sdv.string_value in ('A', 'X'))
WHERE sdv.oid is null
DataFilter.notAnyOf("SD1", "list", [A,Y]) piKLM
DataFilter.notAnyOf("SD1", "list", [A,X,Z]) piKLM
DataFilter.notAnyOf("SD1", "list", [A,X,M]) <empty>
from process_instance pi
OUTER JOIN structured_data_value sdv on (pi.oid and sdv.string_value in ('A', 'X', 'M'))
WHERE sdv.oid is null

Now we use three process instances piABC, piALM, piAYZ also having the Structured Data Type list element with ID SD1, but with the following values:

Process Instance Values in List Element SD1
piABC A, B, C
piALM A, L, M
piAYZ A, Y, Z

See some example queries and the according results for these process instances, which all have A as value in their list element, in the table below:

Query (Pseudo Java) Result SQL (Pseudo)
DataFilter.notAnyOf("SD1", "list", [A]) <empty>
(all excluded as all match A)
DataFilter.notAnyOf("SD1", "list", [A,B]) <empty>
(all excludes as all match A even if they do not match B)
DataFilter.notAnyOf("SD1", "list", [A])
AND
DataFilter.notAnyOf("SD1", "list", [B])
<empty>
(See Match Matrix table)
from process_instance pi
OUTER JOIN structured_data_value sdvA on (pi.oid and sdvA.string_value in ('A'))
OUTER JOIN structured_data_value sdvB on (pi.oid and sdvB.string_value in ('B'))
WHERE sdvA.oid is null AND sdvB.oid is null
DataFilter.notAnyOf("SD1", "list", [A])
OR
DataFilter.notAnyOf("SD1", "list", [B])
piALM, piAYZ (See Match Matrix table)
from process_instance pi
OUTER JOIN structured_data_value sdvA on (pi.oid and sdvA.string_value in ('A'))
OUTER JOIN structured_data_value sdvB on (pi.oid and sdvB.string_value in ('B'))
WHERE sdvA.oid is null OR sdvB.oid is null

The following table provides a matching matrix for combinations of list values and process instances when using AND and OR operators:

PI sdvA.oid sdvB.oid AND
  • all filters need to be null
  • excludes PIs which match at least one filter
OR
  • at least one result needs to be null
  • excludes PIs which match all filters
piABC A B excluded excluded
piALM A null excluded included
piAYZ A null excluded included

Filtering for matching Workflow Data between given values

public static DataFilter between(String dataID, Serializable lowerBound,
         Serializable upperBound)
public static DataFilter between(String dataID, String attributeName, Serializable lowerBound,
         Serializable upperBound)

Filtering for matching Case Descriptors

public static DataFilter equalsCaseDescriptor(String id, Object value)
public static DataFilter likeCaseDescriptor(String id, Object value)

Known restrictions for String comparison using MySQL

Please note that MySQL always performs a case sensitive String comparison, so the usage of the Boolean parameter caseSensitive for a String comparison in a DataFilter query using MySQL will have no affect.

Participant and User Filter

ParticipantAssociationFilter

The ParticipantAssociationFilter will query for fetching workflow users matching specific criteria. Use one of the following kinds:

PerformingParticipantFilter

The PerformingParticipantFilter filter retrieves items performed by any participant (roles, organizations or user groups) associated with the calling user. Finding such participants will perform a deep search. Use one of the following kinds:

Use forParticipant(ParticipantInfo participant) to construct a filter criterion matching the participant identified by the given participant info. You can also use forParticipant(ParticipantInfo participant, boolean recursively), with recursively as flag to indicate that evaluation of this filter should traverse the participant hierarchy.

Please refer to the Javadoc of the PerformingParticipantFilter for detailed information.

PerformedByUserFilter

This filter indicates a match against the currently logged in user. Please refer to the Javadoc of the PerformedByUserFilter for detailed information.

PerformingUserFilter

The PerformingUserFilter is a predefined filter indicating a match against the currently logged in user.

PerformingOnBehalfOfFilter

The PerformingOnBehalfOfFilter filter will get all activity instances for that you have an appropriate permission, including those which are in a different user worklist. Use one of the following kinds:

Use one of the following methods to construct a filter criterion matching the participant identified by the given participant info:

Please refer to the Javadoc of the PerformingOnBehalfOfFilter for detailed information.

Note
Note that the PerformingOnBehalfOfFilter is only evaluated in case the property Carnot.AuditTrail.ActivityInstanceHistory.Enabled is set to true, as it requires the values ONBEHALFOFKIND, ONBEHALFOF and ONBEHALFOFDEPARTMENT from the ACT_INST_HISTORY table. If the property is set to false, the query throws an org.eclipse.stardust.engine.api.runtime.IllegalOperationException.

StartingUserFilter

This is a filter for finding processes started by a specific user. Please refer to the Javadoc of the StartingUserFilter for detailed information.

UserStateFilter

The UserStateFilter is a filter that reduces the query result to users with the given status.

To create a filter matching the currently logged in users, use:

UserQuery query = new UserQuery();
query.getFilter().add(UserStateFilter.forLoggedInUsers());

This will return all users which are currently logged on.

Using Filter Criteria efficiently

There is a basic performance difference between criteria directly targeting attributes of the queried type and complex criteria.

Filter criteria against attributes are applied by using the Attribute -constants defined for each Query subclass. For example, common attributes are the runtime object ID, provided as an OID attribute and the appropriate model element object ID, provided as ACTIVITY_OID attribute or PROCESS_DEFINITION_OID attribute. As Attribute is a specialization of FilterableAttribute , it provides various methods for creating a concrete FilterCriterion instances, like isEqual() for matching a specific value or between()for matching a range of values. Most common SQL search condition operators are supported.

Complex filter criteria are all high-level filters like ProcessDefinitionFilter, ProcessInstanceFilter and most prominently DataFilter, as well as the SubprocessDataFilter and the HierarchyDataFilter. The sole purpose of those complex filters is providing a programmers friendly API for doing such complex things like hierarchy unrolling, versioning and finding the right joins.

From a performance point of view, Attribute filter criteria are very efficient as evaluation never requires any join or subselect. On the downside, using those criteria requires giving up a certain level of abstraction when creating queries. For example, as the application developer will have to use numeric OIDs to search for instances of model elements, the application has to take special care in multi model version scenarios.

Complex filters on the other hand allow for more abstract queries, but evaluating those filters usually involves additional preprocessing and, depending on context, join operations.

ProcessInstanceFilter / ProcessDefinitionFilter

A very typical use case is finding activity instances or process instances by process instance OID: while in general such queries will be performed by using an instance of ProcessInstanceFilter , some scenarios may allow for using
ActivityInstanceQuery. PROCESS_INSTANCE_OID , or ProcessInstanceQuery.OID respectively instead, making use of additionally available context information. Especially if the process in question does not involve subprocesses, or even in case of process hierarchies, the exact process instance is known in advance. Filtering against the OID attribute will prevent process hierarchy preprocessing needed in the generic case and potentially reduce query evaluation to one database call. Similar considerations apply for ProcessDefinitionFilter, where the direct use of ProcessInstanceQuery.PROCESS_DEFINITION_OID may lead to considerable performance improvements.

Creating a Filter Provider Java File

By creating the filter provider, you can control the viewing of worklist of a particular location or role. For more information, please refer to chapter Configuring Worklists in the Portal Documentation.

The following is the sample code snippet to create the LocationFilter.java

package com.filters;

import java.util.Iterator;
import java.util.List;

import org.eclipse.stardust.engine.api.web.jsf.common.beans.SessionContext;
import org.eclipse.stardust.engine.api.web.jsf.processportal.spi.AbstractFilterProvider;
import org.eclipse.stardust.engine.api.query.DataFilter;
import org.eclipse.stardust.engine.api.query.FilterAndTerm;
import org.eclipse.stardust.engine.api.query.FilterOrTerm;
import org.eclipse.stardust.engine.api.query.Query;
import org.eclipse.stardust.engine.api.runtime.Grant;
import org.eclipse.stardust.engine.api.runtime.User;


public class LocationFilter extends AbstractFilterProvider
{
   private static final long serialVersionUID = 1L;

   /* (non-Javadoc)
    * @see org.eclipse.stardust.ui.web.client.common.spi.IFilterProvider#applyFilter(org.eclipse.stardust.engine.api.query.Query)
    */
   public void applyFilter(Query query)
   {
      System.out.println("Applying Filter Provider - LocationFilter.applyFilter()");
      User user = SessionContext.findSessionContext().getUser();
      
      boolean puneCenter = false;
      boolean mumbaiCenter = false;

      List<Grant> grants = (List<Grant>) user.getAllGrants();
      Iterator<Grant> iterator = grants.iterator();
      while (iterator.hasNext())
      {
         Grant grant = iterator.next();

         if (grant.getId().equalsIgnoreCase("PuneCenter"))
         {
            puneCenter = true;
         }

         if (grant.getId().equalsIgnoreCase("MumbaiCenter"))
         {
            mumbaiCenter = true;
         }
      }

      System.out.println("puneCenter = " + puneCenter + ":: mumbaiCenter = " + mumbaiCenter);
      
      if (puneCenter && mumbaiCenter)
      {
         FilterOrTerm filter = query.getFilter().addOrTerm();
         filter.add(DataFilter.like("SupportCaseData", "Location", "%Pune%", false));
         filter.add(DataFilter.like("SupportCaseData", "Location", "%Mumbai%", false));
      }
      else if (puneCenter)
      {
         FilterAndTerm filter = query.getFilter().addAndTerm();
         filter.add(DataFilter.like("SupportCaseData", "Location", "%Pune%", false));
      }
      else if (mumbaiCenter)
      {
         FilterAndTerm filter = query.getFilter().addAndTerm();
         filter.add(DataFilter.like("SupportCaseData", "Location", "%Mumbai%", false));
      }
      else
      {
         System.out.println("NOT Applying any Filter");
      }
   }
}