Basic Customization > User Interface Customization > Presenting Information in the UI > UI Validation > Procedure – Pre-Validation > Implementing Validation Filters
  
Implementing Validation Filters
Assuming the solution-based and role-based checks pass, the next thing the validation service will do when performing a pre-validation activity is to determine which filters apply to the UI component. As previously mentioned, a typical validation filter will contain pre-validation logic that applies to multiple UI components. So rather than duplicating this logic in multiple validators, a single filter can be created and the logic can be selectively applied to UI components or applied to all UI components.
Choose Your Filter Type – Simple or Universal
The first thing you’ll need to decide when implementing a filter is whether it should be a simple filter or a universal filter. To do this, ask if your filter logic is more global in nature or if it only applies to a relatively small number of actions.
If the logic applies to most actions, you would create a universal filter. In this case, the filter will be applied to all actions, although actions can always be configured to "opt out" of the filter.
If your filter logic only applies to a small subset of actions, you would create a simple filter. In this case, you would need to individually configure actions where you want this filter applied.
If you're not sure which type of Filter to implement, it's probably easier to start with a simple filter, and convert it to a universal filter later, if necessary. One additional consideration is that there is currently no support for applying a simple filter to attributes, nor is there support for configuring attributes to ignore universal filters. So if you have filtering logic that you want applied to attributes, your only choice is a universal filter. Just be conscious that any universal filter will be applied to all attributes, all the time, no matter what.
Implementing a Simple Filter
When implementing a simple filter, you’ll need to create a class that extends com.ptc.core.ui.validation.DefaultSimpleValidationFilter. Then simply override the preValidateAction() method to contain your validation logic and return a validation status.
The following class skeleton is an example of a simple filter that would hide an action if the context object is marked for delete.
public class MarkedForDeleteFilter extends
DefaultSimpleValidationFilter{
@Override
public UIValidationStatus preValidateAction(UIValidationKey key,
UIValidationCriteria criteria){
// ENABLE by default
UIValidationStatus status = UIValidationStatus.ENABLED;
WTReference contextObj = criteria.getContextObject();
if (/*contextObj.isMarkedForDelete() == */ true){
status = UIValidationStatus.HIDDEN;
}
return status;
)
)
Implementing a Universal Filter
You implement a universal filter the exact same way as you would implement a simple filter, with one exception. When implementing a universal filter, you need to extend com.ptc.core.ui.validation.DefaultUniversalValidationFilter. Otherwise, the implementation is exactly the same as a simple filter.
Suppose we wanted to implement the filter in the simple filter example as a universal filter instead. Here is what that class skeleton would look like as a universal filter:
public class MarkedForDeleteFilter extends
DefaultUniversalValidationFilter{
@Override
public UIValidationStatus preValidateAction(UIValidationKey key,
UIValidationCriteria criteria){
// ENABLE by default
UIValidationStatus status = UIValidationStatus.ENABLED;
WTReference contextObj = criteria.getContextObject();
if (/*contextObj.isMarkedForDelete() == */ true){
status = UIValidationStatus.HIDDEN;
}
return status;
}
}
Registering Filters
Once you've created a filter, the next step is to register it.
Depending on the type of filter you implement (universal or simple), your filter registry will differ. When providing a selector in your registry, the convention is to use the filter class name with replacing the first letter with a lower-case letter, and eliminating the "filter" suffix (e.g., "MarkedForDeleteFilter" would have a selector of "markedForDelete"). The following details should clarify:
To register a universal filter, in *service.proeprties.xconf, create an entry like this:
<Service context="default"
name="com.ptc.core.ui.validation.UniversalValidationFilter">
<Option
serviceClass="com.ptc.windchill.enterprise.markedfordelete.validat
ors.MarkedForDeleteFilter"
selector="markedForDelete" requestor="null" />
</Service>

When registering a simple filter, the only difference is the name
attribute of the Service element:

<Service context="default"
name="com.ptc.core.ui.validation.SimpleValidationFilter">
<Option
serviceClass="com.ptc.windchill.enterprise.somepackage.validators.
MarkedForDeleteFilter"
selector="markedForDelete" requestor="null" />
</Service>
Associating and Dissociating Actions with a Filter
Once you've created and registered your filter, the last thing to do is to associate actions with your Simple Filter, or dissociate actions with your Universal Filter. This is done in *actions.xml.
Dissociating Actions from a Universal Filter
In cases where you don't want a global filter to be applied to specific actions, you need to find those actions in *acitons.xml that and update them to include an excludeFilter element, as shown below:
<objecttype name="navigation" class=""
resourceBundle="com.ptc.core.ui.navigationRB">
<action name="home" renderType="GENERAL">
<command class="netmarkets"
method="servlet/Navigation?tab=home" windowType="page"/>
<excludeFilter name="markedForDelete" />
</action>

<action name="program" renderType="GENERAL">
<command class="netmarkets"
method="servlet/Navigation?tab=program"windowType="page"/>
<excludeFilter name="markedForDelete" />
</action>

<action name="product" renderType="GENERAL">
<command class="netmarkets"
method="servlet/Navigation?tab=product" windowType="page"/>
<excludeFilter name="markedForDelete" />
</action>
...
* 
The name attribute of the excludeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Associating Actions with a Simple Filter
Suppose (hypothetically) you created and registered a simple filter called ProblemReportStatusFilter (and registered it with a selector of "problemReportStatus") that disabled actions if a problem report had a certain status. And suppose you wanted to apply it to a few actions. You would find the actions you want to apply your Filter to in *actions.xml and modify them to include includeFilter elements like this:
<objecttype name="problemReport" class="wt.change2.WTChangeIssue"

resourceBundle="com.ptc.windchill.enterprise.change2.changeManagem
entActionsRB">
<action name="create" >
<command class=…/>
<includeFilter name="problemReportStatus" />
</action>
<action name="edit" >
<command class=…/>
<includeFilter name="problemReportStatus" />
</action>
<action name="editModifyContentOnly"
id="editModifyContentOnly">
<command class="…/>
<includeFilter name="problemReportStatus" />
</action>
...
* 
Again, the name attribute of the includeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Multiple Filter Inclusions/Exclusions for the Same Action
In theory, an action can have any number of universal filters dissociated from it and any number of simple filters associated with it. You would just add as many includeFilter and excludeFilter elements as you need in *actions.xml.
For example:
<action name="removeChangeTask" renderType="GENERAL" ajax="row">
<command onClick="removeChangeTask(event)"
windowType="no_content" />
<includeFilter name="problemReportStatus />
<excludeFilter name="markedForDelete" />
<includeFilter name="someSimpleFilter" />
<excludeFilter name="someUniversalFilter" />
...
</action>
* 
The order of the includeFilter and excludeFilter elements does not matter, nor does it have any bearing on the order in which the filters are called.
Associating and Dissociating Action Models with a Filter
Once you've created and registered your filter, you can also associate action models with your Simple Filter, or dissociate action models with your Universal Filter. This is done in *actionModels.xml.
Dissociating Action Models from a Universal Filter
In cases where you don't want a global filter to be applied to specific action models, you need to find those action models in *actionModels.xml that and update them to include an excludeFilter element, as shown below:
<model name="CustEx_default_myTab">
<action name="CustEx_simpleTable1" type="object" />
<action name="CustEx_simpleTable2" type="object" />
<action name="CustEx_simpleTable3" type="object" />
<excludeFilter name=" someUniversalFilter " />
</model>
* 
The name attribute of the excludeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Associating Action Models with a Simple Filter
Suppose (hypothetically) you created and registered a simple filter called ProblemReportStatusFilter (and registered it with a selector of "problemReportStatus") and you wanted to apply it to a few action models. You would find the action models you want to apply your Filter to in *actionModels.xml and modify them to include includeFilter elements like this:
<model name="CustEx_default_myTab">
<action name="CustEx_simpleTable1" type="object" />
<action name="CustEx_simpleTable2" type="object" />
<action name="CustEx_simpleTable3" type="object" />
<includeFilter name="testFilter" />
</model>
* 
The name attribute of the includeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Multiple Filter Inclusions/Exclusions for the Same Action Model
In theory, an action can have any number of universal filters dissociated from it and any number of simple filters associated with it. You would just add as many includeFilter and excludeFilter elements as you need in *actionModels.xml.
For example:
<model name="CustEx_default_myTab">
<action name="CustEx_simpleTable1" type="object" />
<action name="CustEx_simpleTable2" type="object" />
<action name="CustEx_simpleTable3" type="object" />
<includeFilter name="problemReportStatus />
<excludeFilter name="markedForDelete" />
<includeFilter name="someSimpleFilter" />
<excludeFilter name="someUniversalFilter" />
...
</model>
* 
The order of the includeFilter and excludeFilterelements does not matter, nor does it have any bearing on the order in which the filters are called.