Using filters in the history manager

The history manager can use filters to enable you to specify objects for which changes are logged on subscribed events. This is important to limit the number of objects of a specific object type whose history changes are logged, and leads to improved system performance as well as optimization of storage space.

The history_subscriptions.xml file contains the filter definitions for logging events for Product Master objects. The history manager provides two types of filters:
  • Named List filter
  • Regular Expressions filter
To be able to use a named list filter or regular expressions filter, you need to declare the filter name and filter implementation in the history_subscriptions.xml file. Once declared, you can use the filter in subscription policies. The filter_definition tags for the default filter exist in the history_subscriptions.xml file.
Attention: Do not remove or modify the filter_definition tags for the named list filter and regular expressions filter in the history_subscription.xml file.

This example demonstrates the declaration of a filter_definition tag for a regular expression filter:

<subscription_filter_definition>
     	<filter_name>regex filter</filter_name>
 			<filter_implementation>com.ibm.ccd.api.history.RegularExpressionFilter
			</filter_implementation>
</subscription_filter_definition>
subscription_filter_definition
The definition tags of the filter are mentioned on this tag.
filter_name
The name of the filter is mentioned on this tag.
filter_implementation
The fully qualified name of the Java™ class that implements this filter is mentioned on this tag.
The name that you specify on the <filter_name> tag is the name that you must specify on the <subscription_filter> tag for the subscription node. The order of precedence for the filters that apply to a subscription policy is the following:
  • A subscription policy by using named list filters is evaluated first irrespective of the order of the definition of named list filter in the filters section.
  • Subscription policies using other filters are evaluated in the order of filter definition in the subscription_history.xml file including the regex filter.
  • A subscription policy without any filter is evaluated in the end.
  • If two subscription policies for the same object type use the same filter, or do not use a filter, then the order of definition of those policies in thehistory_subscriptions.xml file will determine their relative precedence.
For example, if events are logged for an object with a filter, but subscription policies for different filters have different levels of logging defined, then the object is evaluated first by using the NamedListFilter. Then, the object is evaluated by using the RegularExpressionFilter. The order of precedence of these filters are in the order in which they are defined in the filters section of the history_subscriptions.xml file.
Users can implement their own filters. A filter must implement the Filter interface, which provides two methods: setup() and apply().
This example demonstrates the implementation of a filter:
public class ReportFilter implements Filter {

	private String distributionType = null;

	public String getDistributionType() {
		return distributionType;
	}

	public void setDistributionType(String distributionType) {
		this.distributionType = distributionType;
	}

	public void setup(Node policyArguments) {
		try {
			Node nArguments = findNode(policyArguments,"filter_arguments",true);
			Node nDistributionType = findNode(nArguments,"distribution_type",true);
			distributionType = nDistributionType.getFirstChild().getNodeValue();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean apply(PIMObject object) {
		Report report = null;
		try {
			report = (Report) object;
		} catch (ClassCastException e) {
			e.printStackTrace();
		}
		boolean returnValue = getDistributionType().equalsIgnoreCase(report.getDistribution().getType().toString());
		return returnValue;
	}
	
    public static Node findNode(Node node, String name, boolean required) throws Exception{
        Node result = null;
        if (null != node){
            NodeList children = node.getChildNodes();
            for (int i = 0; i < children.getLength(); i++){
                Node child = children.item(i);
                if (child.getNodeName().equals(name)){
                        result = child;
                        break;
                }
            }
            if (result == null && required){
                throw new Exception("node '" + name + "' missing");
            }
        }
        return result;
    }
    
}
After implementing the filter, you need to add the filter definition of this filter to the history_subscriptions.xml file. Here is how the filter definition is added to the history_subscriptions.xml file.
<subscription_filter_definition>
    <filter_name>report filter</filter_name>
<filter_implementation> com.abc.pim.history.ReportFilter </filter_implementation>
  </subscription_filter_definition>
Note: The fully qualified name of the class depends on the actual location of the class. For this example, you can assume it to be com.abc.pim.history.ReportFilter.
You can create a custom filter for the report object based on distribution. The distribution can be any of the predefined Report.Type. You can capture changes that are made to the report objects, which have a given distribution type such as email.
This is an example of using a report filter. There are only two <log> nodes because the REPORT object supports only the CREATE and DELETE events.
<subscription object_type="REPORT">
  <subscription_filter>report filter</subscription_filter>
  	<filter_arguments>
      <distribution_type>Email</distribution_type> 
    </filter_arguments>
    <subscription_levels>
      <log event_type="CREATE" history_level="PRE_AND_POST_EVENT_SNAPSHOTS"/>
      <log event_type="DELETE" history_level="DELTA"/>
    </subscription_levels>
  </subscription>
If no subscription_filter is defined for a policy, then the policy applies to all objects of the given object_type, in this case the REPORT object.