Advanced Customization > Business Logic Customization > Customizations for PDM > Customizing the HTML Client Object Selection Page
  
Customizing the HTML Client Object Selection Page
The HTML client object selection page is used in the Creo Parametric HTML client to allow the user to choose objects in the Windchill database that are required to complete an action.
To determine the drop down list, search criteria, and result columns for the object selection page the configured com.ptc.windchill.cadx.common.picker.PickerSearchAttributeListDelegate is used. The default configured PickerSearchAttributeListDelegate is com.ptc.windchill.cadx.common.picker.PickerSearchAttributeList. PickerSearchAttributeList delegates to the configured wt.query.SearchAttributeListDelegate to create the various type lists on the object selection page will be configured to support and determine the search criteria, and determine the result columns displayed in the object selection page. (For more SearchAttributeListDelegate details see Customizing the HTML Search.)
If this PickerSearchAttributeListDelegate implementation is not sufficient, then you can create and configure your own PickerSearchAttributeList to be used by the object selection page.
* 
This functionality is applicable to all Windchill Workgroup Managers integrating with 3rd party CAD tools
Modifying the Search Attribute List Delegate
To implement your own custom PickerSearchAttributeListDelegate, create a class that implements wt.query.SearchAttributeListDelegate and com.ptc.windchill.cadx.common.picker.PickerSearchAttributeListDelegate or create a class which sub-classes com.ptc.windchill.cadx.common.picker.PickerSearchAttributeList.
See the javadoc for PickerSearchAttributeListDelegate and PickerSearchAttributeList and their methods for more details.
* 
PickerSearchAttributeList extends SearchAttributeList; therefore, the custom class can be used as the SearchAttributeListDelegate and PickerSearchAttributeListDelegate.
* 
If extending PickerSearchAttributeList, you may have to set the filter to avoid NullPointerExceptions. This issue will be addressed in a future release.
To configure a new PickerSearchAttributeListDelegate :
1. Use the xconfmanager to add an entry to com/ptc/windchill/cadx/common/picker/picker.properties similar to:
wt.services/svc/default/com.ptc.windchill.cadx.common.picker.PickerSearchAttributeListDelegate/
<unique delegate id which is also specified for com.ptc.windchill.cadx.common.picker.pickerSearchAttributeList>/java.lang.Object/0=mine.MyPickerSearchAttributeList/duplicate.
2. Using the xconfmanager, change the pickerSearchAttributeList entry in the wt.properties to com.ptc.windchill.cadx.common.picker.pickerSearchAttributeList=<unique delegate id>. If there is no entry in wt.properties, then STANDARD is used as the delegate ID
Modifying Type Lists
The Creo Parametric HTML client object selection page uses configured type lists identified by type list IDs, which are specified as the object selection page typeListID property value.
Type lists are defined in com\ptc\windchill\cadx\propfiles\picker.properties.
To add a type list entry for a new type list ID, use the xconfmanager to add an entry similar to: wt.services/rsc/default/<type list id>/java.lang.Object/0=<comma-seperated list of valid query values>
If there is only one value in the list, then you do not need any commas. If you want an “All” entry in the type list, you must specify the type list entry value for ALL in the list of type IDs.
* 
For the default implementation of the object selection page these valid type list values are query values specified in wt.query.queryResource.
You can remove type IDs from the list of type IDs specified for a type list ID, but you cannot remove an entry or leave the type list empty.
Customizing the HTML Search
To customize the HTML search to either change the display of the default search objects or to add new classes, see the following file that is distributed as source Windchill\src\wt\query\SearchAttributeList.java. As explained in the javadoc for this class, subclass SearchAttributeList and make the appropriate entries in service.properties and wt.properties. Following are methods that should be implemented in a custom SearchAttributeList, with examples:
public final class MySearchAttributeList extends SearchAttributeList implements Externalizable {
public void setLocale( Locale locale ) {
// Load in the values for the drop down list for selecting what to search against.
clientLocale = locale;
// **Customize --------------------------------------------------------------
--------------
// Add new classes to search to list below.
// Make sure that they are assigned numbers in sequence from 0 to N.
// Set dropDownListCount to N+1.
final int ALL = 0;
final int WTPART = 1;

final int MYCLASS = 22
int dropDownListCount = 23;
// -------------------------------------------------------------------------
------------…
pickList = new String[classCount];
pickList[ALL] =
WTMessage.getLocalizedMessage(RESOURCE,queryResource.ALL,null,clientLocale);
pickList[WTPART] =
WTMessage.getLocalizedMessage(RESOURCE,queryResource.WTPART,null,clientLocale);

pickList[MYCLASS] = WTMessage.getLocalizedMessage(RESOURCE,queryResource.
MYCLASS,null,clientLocale);
pickValues = new String[classCount];
pickValues[ALL] = queryResource.ALL;
pickValues[WTPART] = queryResource.WTPART;

pickValues[MYCLASS] = queryResource.MYCLASS;
// **Customize You will need a string in here to correspond to each item in
pickList
// The string is a space separated list of what classes to query
// against. If you want to query against multiple classes that have a common
parent that
// has all of the attributes that you are interested in use that one class. If
you want
// to query against multiple classes that don't have a good common parent then
you can
// add them to a list and the search will loop through each class and combine
the results
// at the end. All classes in one list must only search against COMMON
attributes or
// attributes with the same name and of the same class! If you add both a
parent and
// a child class to the list you will get duplicate entries, when the results
are
// combined duplicate entries are not deleted.
queryClass = new String[classCount];
queryClass[ALL] =
"wt.part.WTPart wt.doc.WTDocument wt.change2.WTChangeIssue
wt.change2.WTChangeRequest2 " +
"wt.change2.WTChangeInvestigation wt.change2.WTAnalysisActivity
wt.change2.WTChangeProposal " +
"wt.change2.WTChangeOrder2 wt.change2.WTChangeActivity2
wt.csm.businessentity.BusinessEntity " +
"wt.effectivity.ConfigurationItem wt.epm.EPMDocument " +
"wt.replication.unit.WTUnit " +
"wt.part.WTProductConfiguration " +
"wt.part.WTProductInstance2 "; // Please remember to keep a space at the
end so that conditionally added items work.

queryClass[WTPART] = "wt.part.WTPart";

queryClass[MYCLASS] = "?.?.MyClass";
// **Customize These are the
// attributes that can be queried against.
inputAttributes = new String[classCount];
inputAttributes[ALL] =
"number name lifeCycleState projectId cabinet creator modifier
modifyTimestamp";
inputAttributes[WTPART] =
"number name view versionIdentifier partType source lifeCycleState projectId
cabinet creator modifier modifyTimestamp";

inputAttributes[MYCLASS] =
"name modifyTimestamp";
// **Customize Each individual
// string must match with the string listed above for the inputAttributes. "0"
stands for no
// input processing. If an attribute is an enumerated type use "0" and the
code will generate
// the drop down list. In the first string: projectId is in the fourth
position in inputAttributes
// so the method to generate the drop down list for it is also in the fourth
position in the
// string. The "0"s and methods must match in number with the number of
attributes listed
// under inputAttributes. You may add a fully qualified method from your
customization package
// as long as it is static and returns a vector of strings.
inputProcessing = new String[classCount];
inputProcessing[ALL] =
"0 0 0 wt.query.LocalSearchProcessor.getProjectList
wt.query.LocalSearchProcessor.getCabinetList 0 0 0";
inputProcessing[WTPART] =
"0 0 wt.query.LocalSearchProcessor.getViewList 0 0 0 0
wt.query.LocalSearchProcessor.getProjectList
wt.query.LocalSearchProcessor.getCabinetList 0 0 0";

inputProcessing[MYCLASS] =
"0 0";
// **Customize This is similar in concept to inputAttributes only these are
the attributes
// that will be displayed in the search results.
outputAttributes = new String[classCount];
outputAttributes[ALL] =
"number name versionDisplayIdentifier displayType lifeCycleState projectId
modifyTimestamp";
outputAttributes[WTPART] =
"number name versionDisplayIdentifier projectId lifeCycleState
modifyTimestamp";

outputProcessing[MYCLASS] =
"ObjProps 0";
// **New for 6.0
// **Customize This is similar in concept to outputAttributes only this list
is used
// to indicate which attributes can be sorted, can't be sorted, or an alternate
attribute
// that can be sorted to have the same affect as the display attribute. The
string that is used
// here should be the column descriptor so that it can be used to create the
ClassAttribute for
// the query. The query that is used for search is a simple query that will
not sort on all
// of the display attributes. Changing the 0 to 1 for an unsupported attribute
will
// either cause exceptions or sorts that don't work. Attributes of the
following types are
// just some examples of the attributes that will either throw exceptions or
sort incorrectly:
// EnumeratedType, CabinetReference, DataFormatReference,
LifeCycleTemplateReference, ProjectReference,
// and ViewReference.
sortAttributes = new String[classCount];
sortAttributes[ALL] =
"1 1 versionInfo.identifier.versionId 0 0 01";
sortAttributes[WTPART] =
"1 1 versionInfo.identifier.versionId 0 0 1";

sortAttributes[MYCLASS] =
"1 1";
// **New for 6.0
// **Customize This is similar in concept to outputAttributes only this list
is used
// for assigning a unique key to the sort preferences for this search. This
string will
// be persisted and used to retrieve the sort preferences for users. If the
value of one
// of these strings is changed or deleted after the system is in operation it
will create orphaned
// preferences in the system and users will lose the value that they had
persisted for that
// search. New entries can be added when a new search is added so that sort
preferences
// can be saved for that new search. These strings are arbitrary and never
displayed to the user.
sortPref = new String[classCount];
sortPref[ALL] =
"all";
sortPref[WTPART] =
"wtpart";

sortPref[MYCLASS] =
"myclass";
}
/**
*
* <BR><BR><B> Supported API: </B>false
*
* @param locale
* @return MySearchAttributeList
**/
public MySearchAttributeList( Locale locale ) {
setLocale(locale);
}
/**
*
* <BR><BR><B> Supported API: </B>false
*
* @return MySearchAttributeList
**/
public MySearchAttributeList() {
return;
}
}
wt.query.SearchAttributeList is always the most up-to-date and should be used as a reference.
The remainder of this section describes two new arrays in wt.query.SearchAttributeList, sortAttributes and sortPref.
Due to the data structures used on some classes, not all attributes that can be displayed in search results are sortable in the search results. The sortAttributes array in wt.query.SearchAttributeList is used to designate which attributes are sortable, and if an alternate attribute should be used for sorting.
The version attribute is an example of an alternate attribute used for sorting: the attribute used to display is versionDisplayIdentifier, but the attribute used to sort on is versionInfo.identifier.versionId.
Base java types, such as String and int, are sortable. Use the examples in wt.query.SearchAttributeList to determine if any custom types are sortable. Otherwise, a simple test will show if the attribute works, has no effect, or throws an exception.
The sortPref array (shown in the preceding code sample) is used to define a sort preference base name so users can define their sort preferences for that “Search On” object. A default for the sort preferences should be defined at the system level so that the first time the user uses the system, or if a user never defines preferences, the columns will be sorted logically. A default can be defined using wt.load.LoadFromFile or by using the Preference Management utility System Administration portal page.
If this is a new database, the defaults are loaded as part of running the required section of wt.load.Demo (which runs wt.load.LoadFromFile). The site defaults can easily be added to or modified using the Preference Management utility. If the database was created on a system before Release 6.0, wt.load.LoadFromFile can be used to load the base defaults for the delivered configuration of the HTML search classes. See the “PrefEntry…/wt/query/htmlsearch” entries in Windchill\loadFiles\preferences.txt as examples.
Each user preference has an internal name, which is never seen from the client except in the Preference Management utility. Because the current search uses the wt.query.SearchAttributeList to allow users to add new searches, and because there has to be a set of sort preferences for each, a unique sort name is needed for each name in the "Search On" list.
Each object in the “Search On” list is not necessarily one object, but can be a list of objects. The sortPref array in wt.query.SearchAttributeList defines a unique string that forms part of the name of the preference. The preferences for sorting are stored in the /wt/query/htmlsearch preference node, and the naming format is as follows:
<sort preference base name>sortAttrib<#>
<sort preference base name>sortDirect<#>
The <sort preference base name> is the unique string from the sortPref array in wt.query.SearchAttributeList; it has only to be unique within the sort names. The sortAttrib is for the attribute name, and the sortDirect is to indicate ascending or descending. It is false for ascending and true for descending. The <#> is the number of the sort key, 0 = first key, and so on. Following are the preferences that are loaded using wt.load.LoadFromFile and Windchill\loadFiles\preferences.txt for the All sort:
#All

PrefEntry~allsortAttrib0~number~/wt/query/htmlsearch

PrefEntry~allsortDirect0~false~/wt/query/htmlsearch

PrefEntry~allsortAttrib1~versionInfo.identifier.versionId~/wt/query/htmlsearch

PrefEntry~allsortDirect1~true~/wt/query/htmlsearch
In the all-default example, the results are sorted first by the number column and then by the version column, with the number being in ascending order and the version in descending order. Currently, the supported number of sort keys is 3, although theoretically the number of sort keys is limited only by Oracle performance. No testing beyond 3 keys has been done on the system.