Basic Customization > User Interface Customization > Presenting Information in the UI > UI Validation > Procedure – Pre-Validation > Implementing Solution-Based Pre-Validation
  
Implementing Solution-Based Pre-Validation
As indicated in the “Pre-Validation Sequence” section, the first pre-validation check performed by the validation service is to determine whether or not the UI component should be hidden based on the installed set of Windchill solutions. For example, if Windchill PDMLink is not installed, certain actions should never be available.
As a rule of thumb, this type of solution-based logic should NEVER be included in your validator or filter classes. You can assume that if your validator or filter has been called, the UI component being validated has already passed any applicable solution-based checks.
Solution-based logic should be implemented in a solution group.
Implementing a Solution Group
Implementing a solution group class is very easy. All you need to do is create a class that implements the UIComponentSolutionGroup Interface, and in your class, implement the getInvalidInstallKeys() method. In that method, you check to see which solutions are installed, and return a list of validation keys representing actions or UI components that should never be available based on the installed solutions.
The class on the following page is an simple example of a solution group whose getInvalidInstallKeys() method checks to see if Pro/INTRALINK is installed. If Pro/I is installed, it returns a list of validation keys representing actions or components that should never be available.
package com.ptc.windchill.enterprise.myPackage;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import wt.log4j.LogR;
import wt.util.InstalledProperties;

public class MySolutionGroup implements UIComponentSolutionGroup
{
private static UIValidationKey listKey =
UIValidationKey.newInstance("list", "change");
private static UIValidationKey crKey =
UIValidationKey.newInstance("listChangeRequests", "change");
private static UIValidationKey cnKey =
UIValidationKey.newInstance("listChangeNotices", "change");
private static UIValidationKey viewKey =
UIValidationKey.newInstance("view", "change");
/*
* DEFINE ADDITIONAL ACTIONS AND UI COMPONENTS AS NEEDED
*/

private static Logger logger =
LogR.getLogger(MySolutionGroup.class.getName());

public List getInvalidInstallKeys()
{
if (logger.isDebugEnabled()){
logger.debug("ENTERING MySolutionGroup.getInvalidKeys");
}
ArrayList invalidList = new ArrayList();

// if PRO-I is installed, the following UI components are
not valid.
if
(InstalledProperties.isInstalled(InstalledProperties.PRO_I)){
invalidList.add(listKey);
invalidList.add(listKey);
invalidList.add(cnKey);
invalidList.add(viewKey);
}

/*
* ADD ADDITIONAL SOLUTION-BASED CHECKS AS NEEDED
*/

if (logger.isTraceEnabled()){
logger.trace("RETURNING " + (List)invalidList);
}
(logger.(trace("RETURNING " + (List)invalidList))){
logger.debug("EXITING MySolutionGroup.getInvalidKeys");
}
return invalidList;
}
}
If you’re wondering how to determine which values to include in the validation key factory methods, it depends on whether you’re creating a validation key for an action or an attribute. If you’re creating a validation key for an action, the first argument represents the action name (from *actions.xml) and the second argument represents the object type (from *actions.xml). For example, to create a validation key to represent the product action below, you would call UIValidationKey.newInstance(“product”, “navigation”);
<objecttype name="navigation" class=""
resourceBundle="com.ptc.core.ui.navigationRB">
<action name="product" renderType="GENERAL">
<command class="netmarkets"
method="servlet/Navigation?tab=product" windowType="page"/>
</action>
...
Constructing the ValidationKey
If you’re wondering how to determine which values to include in the validation key factory methods, it depends on whether you’re creating a validation key for an action, an action model, or an attribute.
If you are creating a validation key for an action, the first argument represents the action name (from *actions.xml) and the second argument represents the object type (from *actions.xml). For example, to create a validation key to represent the product action below, you would call UIValidationKey.newInstance(“product”, “navigation”);
<objecttype name="navigation" class=""
resourceBundle="com.ptc.core.ui.navigationRB">
<action name="product"
renderType="GENERAL">
<command class="netmarkets"
method="servlet/Navigation?tab=product"
windowType="page"/>
</action>
...
If you are creating a validation key for an action model, the first argument represents the action model name (from *actionModels.xml) and the seconfdargument represents the object type which is always “object”. For example, to create a validation key to represent the carambola_sub_model below you would call UIValidationKey.newInstance(“carambola_sub_model”, “object”);
<model name="carambola_sub_model">
<action name="ripe" type="carambola" />
<action name="grow" type="carambola" />
</model>
If you are creating a validation key for an attribute, simply use the descriptor ID used for that attribute in the Windchill client architecture. For example, to create a validation key for the attribute whose descriptor ID is “iteration”, you would call UIValidationKey.newInstance(“iteration”);
Registering a Solution Group
Once you've created and built your solution group, the only thing left to do is register it. You register a solution group in *service.properties.xconf by creating an entry like this:
<Service context="default"
name="com.ptc.core.ui.validation.UIComponentSolutionGroup">
<Option requestor="null" serviceClass="[your fully-qualified
SolutionGroup class name
]"
selector="[any unique key, e.g.,
"ChangeMgmtSolutionGroup")
]" />
</Service>
The propagated entry in *service.properties should look like this:
wt.services/svc/default/com.ptc.core.ui.validation.UIComponentSolu
tionGroup/[any unique key, e.g., "MySolutionGroup"]/null/0=[your
fully-qualified solution group class name
]
Once your solution group is registered, its logic should be checked any time the validation service is called to perform pre-validation. (Its results are actually cached after the first invocation.)
Implementing Role-Based Pre-Validation
The second pre-validation check performed by the validation service is to call the role-based UI service to see whether or not an admin user has configured a component to be hidden or disabled for certain users. This check is built into the validation service, so there is no work for a customizer to perform. For more information about configuring the role-based UI service as an admin user, please see Customizing Role-Based UI Functions — Action Visibility